Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add github action to run unit tests on every PR #19

Merged
merged 4 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/check_docs.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Pull Request Docs Check"
name: "Check Docs"

on:
- workflow_dispatch
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: "Run Tests"

on:
- workflow_dispatch
- pull_request

jobs:
run-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.11
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies and local packages
run: python -m pip install mpremote click
- name: Install MicroPython
uses: BrianPugh/install-micropython@v2
- name: Install Micropython dependencies
run: micropython -m mip install unittest
- name: Run tests
run: python -m ci.test
6 changes: 5 additions & 1 deletion ci/deploy_to_device.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# SPDX-FileCopyrightText: 2024-present Unital Software <[email protected]>
#
# SPDX-License-Identifier: MIT

from pathlib import Path
import subprocess

Expand All @@ -6,6 +10,7 @@

@click.command()
def deploy():
"""Deploy files to a device via mpremote"""
try:
deploy_py_files(Path("docs/source/examples"), ":")
deploy_py_files(Path("docs/source/examples/devices"), ":/devices")
Expand All @@ -17,7 +22,6 @@ def deploy():
print(exc.stderr)
raise


def deploy_py_files(path: Path, destination):
try:
mpremote("mkdir", destination)
Expand Down
53 changes: 53 additions & 0 deletions ci/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: 2024-present Unital Software <[email protected]>
#
# SPDX-License-Identifier: MIT

from pathlib import Path
import os
import subprocess
import sys

import click



@click.command()
def test():
"""Run unit tests in micropython"""
print("Running Tests")
failures = []
test_dir = Path("tests/ultimo")
os.environ["MICROPYPATH"] = "src:" + os.environ.get('MICROPYPATH', ":.frozen:~/.micropython/lib:/usr/lib/micropython")
for path in sorted(test_dir.glob("*.py")):
print(path.name, "... ", end="", flush=True)
result = run_test(path)
if result:
failures.append(result)
print('FAILED')
else:
print('OK')
print()

for path, stdout, stderr in failures:
print("FAILURE: ", path.name)
print("STDOUT ", "="*70)
print(stdout.decode('utf-8'))
print()
print("STDERR ", "="*70)
print(stderr.decode('utf-8'))
print()

if failures:
sys.exit(1)
else:
print("PASSED")


def run_test(path):
try:
subprocess.run(["micropython", path], capture_output=True, check=True)
except subprocess.CalledProcessError as exc:
return (path, exc.stdout, exc.stderr)

if __name__ == "__main__":
test()
28 changes: 14 additions & 14 deletions tests/ultimo/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: MIT

import unittest
import asyncio
import uasyncio

from ultimo.core import APipeline, ASource, ASink, asynchronize

Expand All @@ -13,7 +13,7 @@ def __init__(self, count):
self.count = count

async def __call__(self):
await asyncio.sleep(0.01)
await uasyncio.sleep(0.01)
value = self.count
self.count -= 1
if value < 0:
Expand Down Expand Up @@ -42,7 +42,7 @@ class TestASource(unittest.TestCase):
def test_immediate(self):
source = FiniteSource(1)

result = asyncio.run(source())
result = uasyncio.run(source())

self.assertEqual(result, 1)

Expand All @@ -55,7 +55,7 @@ async def iterate():
async for value in source:
result.append(value)

asyncio.run(iterate())
uasyncio.run(iterate())

self.assertEqual(result, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

Expand All @@ -66,44 +66,44 @@ def test_immediate(self):
source = FiniteSource(1)
sink = CollectingSink(source=source)

asyncio.run(sink())
uasyncio.run(sink())

self.assertEqual(sink.results, [1])

def test_iterate(self):
source = FiniteSource(10)
sink = CollectingSink(source=source)

asyncio.run(sink.run())
uasyncio.run(sink.run())

self.assertEqual(sink.results, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

def test_connect(self):
source = FiniteSource(10)
sink = CollectingSink()

asyncio.run((source | sink).run())
uasyncio.run((source | sink).run())

self.assertEqual(sink.results, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])

def test_no_source_immediate(self):
sink = CollectingSink()

asyncio.run(sink(1))
uasyncio.run(sink(1))

self.assertEqual(sink.results, [1])

def test_no_source_no_value(self):
sink = CollectingSink()

asyncio.run(sink())
uasyncio.run(sink())

self.assertEqual(sink.results, [])

def test_no_source_iterate(self):
sink = CollectingSink()

asyncio.run(sink.run())
uasyncio.run(sink.run())

self.assertEqual(sink.results, [])

Expand All @@ -115,7 +115,7 @@ def test_immediate(self):
pipeline = IncrementPipeline(source=source)
sink = CollectingSink(source=pipeline)

asyncio.run(sink())
uasyncio.run(sink())

self.assertEqual(sink.results, [2])

Expand All @@ -124,7 +124,7 @@ def test_iterate(self):
pipeline = IncrementPipeline(source=source)
sink = CollectingSink(source=pipeline)

asyncio.run(sink.run())
uasyncio.run(sink.run())

self.assertEqual(sink.results, [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])

Expand All @@ -133,7 +133,7 @@ def test_connect(self):
pipeline = IncrementPipeline(source=source)
sink = CollectingSink(source=pipeline)

asyncio.run((source | pipeline | sink).run())
uasyncio.run((source | pipeline | sink).run())

self.assertEqual(sink.results, [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1])

Expand All @@ -146,7 +146,7 @@ def sync_example():

asynchronized = asynchronize(sync_example)

result = asyncio.run(asynchronized())
result = uasyncio.run(asynchronized())

self.assertEqual(result, 1)

Expand Down
30 changes: 15 additions & 15 deletions tests/ultimo/test_poll.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# SPDX-License-Identifier: MIT

import unittest
import asyncio
import time
import uasyncio
import utime

from ultimo.poll import Poll, apoll, poll

Expand All @@ -16,7 +16,7 @@ def test_immediate(self):

async def decrement():
nonlocal count
await asyncio.sleep(0.001)
await uasyncio.sleep(0.001)
value = count
count -= 1
if value < 0:
Expand All @@ -26,7 +26,7 @@ async def decrement():

source = Poll(decrement, 0.01)

result = asyncio.run(source())
result = uasyncio.run(source())

self.assertEqual(result, 1)

Expand All @@ -35,7 +35,7 @@ def test_iterate(self):

async def decrement():
nonlocal count
await asyncio.sleep(0.001)
await uasyncio.sleep(0.001)
value = count
count -= 1
if value < 0:
Expand All @@ -51,9 +51,9 @@ async def iterate():
async for value in source:
result.append(value)

start = time.ticks_ms()
asyncio.run(iterate())
elapsed = time.ticks_diff(time.ticks_ms(), start)
start = utime.ticks_ms()
uasyncio.run(iterate())
elapsed = utime.ticks_diff(utime.ticks_ms(), start)

self.assertEqual(result, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
self.assertGreaterEqual(elapsed, 100)
Expand All @@ -64,7 +64,7 @@ def test_apoll(self):

@apoll
async def decrement():
await asyncio.sleep(0.001)
await uasyncio.sleep(0.001)
nonlocal count
value = count
count -= 1
Expand All @@ -81,9 +81,9 @@ async def iterate():
async for value in source:
result.append(value)

start = time.ticks_ms()
asyncio.run(iterate())
elapsed = time.ticks_diff(time.ticks_ms(), start)
start = utime.ticks_ms()
uasyncio.run(iterate())
elapsed = utime.ticks_diff(utime.ticks_ms(), start)

self.assertEqual(result, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
self.assertGreaterEqual(elapsed, 100)
Expand All @@ -110,9 +110,9 @@ async def iterate():
async for value in source:
result.append(value)

start = time.ticks_ms()
asyncio.run(iterate())
elapsed = time.ticks_diff(time.ticks_ms(), start)
start = utime.ticks_ms()
uasyncio.run(iterate())
elapsed = utime.ticks_diff(utime.ticks_ms(), start)

self.assertEqual(result, [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
self.assertGreaterEqual(elapsed, 100)
Expand Down