Skip to content

Commit f24867f

Browse files
committed
test: Add first tests for base module
1 parent 90aa58a commit f24867f

File tree

3 files changed

+172
-0
lines changed

3 files changed

+172
-0
lines changed

test/__init__.py

Whitespace-only changes.

test/_helper.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import asyncio
2+
import functools
3+
import unittest.mock
4+
from typing import Callable, Any, Awaitable
5+
6+
7+
def async_test(f: Callable[..., Awaitable[Any]]) -> Callable[..., Any]:
8+
"""
9+
Decorator to transform async unittest coroutines into normal test methods
10+
"""
11+
@functools.wraps(f)
12+
def wrapper(*args, **kwargs):
13+
loop = asyncio.get_event_loop()
14+
loop.run_until_complete(f(*args, **kwargs))
15+
return wrapper
16+
17+
18+
class AsyncMock(unittest.mock.MagicMock):
19+
async def __call__(self, *args, **kwargs):
20+
return super().__call__(*args, **kwargs)
21+
22+
async def __aenter__(self, *args, **kwargs):
23+
return self.__enter__(*args, **kwargs)
24+
25+
async def __aexit__(self, *args, **kwargs):
26+
return self.__exit__(*args, **kwargs)

test/test_base.py

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import asyncio
2+
import unittest
3+
from typing import List, Any, Type, TypeVar, Generic
4+
5+
from ._helper import async_test, AsyncMock
6+
from shc import base
7+
8+
9+
TOTALLY_RANDOM_NUMBER = 42
10+
T = TypeVar('T')
11+
12+
13+
class ExampleReable(base.Readable[T], Generic[T]):
14+
def __init__(self, type_: Type[T], value: T, side_effect=None):
15+
self.type = type_
16+
super().__init__()
17+
self.read = AsyncMock(return_value=value, side_effect=side_effect)
18+
19+
async def read(self) -> T: ...
20+
21+
22+
class ExampleSubscribable(base.Subscribable[T], Generic[T]):
23+
def __init__(self, type_: Type[T]):
24+
self.type = type_
25+
super().__init__()
26+
27+
async def publish(self, val: T, source: List[Any]) -> None:
28+
await self._publish(val, source)
29+
30+
31+
class ExampleWritable(base.Writable[T], Generic[T]):
32+
def __init__(self, type_: Type[T]):
33+
self.type = type_
34+
super().__init__()
35+
self._write = AsyncMock()
36+
37+
async def _write(self, value: T, source: List[Any]) -> None: ...
38+
39+
40+
class ExampleReading(base.Reading[T], Generic[T]):
41+
def __init__(self, type_: Type[T], optional: bool):
42+
self.is_reading_optional = optional
43+
self.type = type_
44+
super().__init__()
45+
46+
async def do_read(self) -> T:
47+
return await self._from_provider()
48+
49+
50+
class TestSubscribe(unittest.TestCase):
51+
@async_test
52+
async def test_simple_subscribe(self):
53+
a = ExampleSubscribable(int)
54+
b = ExampleWritable(int)
55+
a.subscribe(b)
56+
await a.publish(TOTALLY_RANDOM_NUMBER, [self])
57+
b._write.assert_called_once_with(TOTALLY_RANDOM_NUMBER, [self, a])
58+
59+
@async_test
60+
async def test_loopback_protection(self):
61+
a = ExampleSubscribable(int)
62+
b = ExampleWritable(int)
63+
a.subscribe(b)
64+
await a.publish(TOTALLY_RANDOM_NUMBER, [b])
65+
self.assertEqual(b._write.call_count, 0)
66+
await a.publish(TOTALLY_RANDOM_NUMBER, [b, self])
67+
self.assertEqual(b._write.call_count, 0)
68+
69+
@async_test
70+
async def test_type_conversion(self):
71+
a = ExampleSubscribable(int)
72+
b = ExampleWritable(float)
73+
74+
with self.assertRaises(TypeError):
75+
a.subscribe(b)
76+
a.subscribe(b, convert=True)
77+
await a.publish(TOTALLY_RANDOM_NUMBER, [self])
78+
b._write.assert_called_once()
79+
self.assertEqual(float(TOTALLY_RANDOM_NUMBER), b._write.call_args.args[0])
80+
self.assertIsInstance(b._write.call_args.args[0], float)
81+
82+
c = ExampleWritable(list)
83+
with self.assertRaises(TypeError):
84+
a.subscribe(c)
85+
86+
87+
class TestHandler(unittest.TestCase):
88+
@async_test
89+
async def test_basic_trigger(self):
90+
# TODO
91+
pass
92+
93+
@async_test
94+
async def test_magic_source_passing(self):
95+
# TODO
96+
pass
97+
98+
@async_test
99+
async def test_allow_recursion(self):
100+
# TODO
101+
pass
102+
103+
104+
class TestReading(unittest.TestCase):
105+
@async_test
106+
async def test_simple_reading(self):
107+
a = ExampleReable(int, TOTALLY_RANDOM_NUMBER)
108+
b = ExampleReading(int, False)
109+
b.set_provider(a)
110+
result = await b.do_read()
111+
self.assertEqual(result, TOTALLY_RANDOM_NUMBER)
112+
113+
@async_test
114+
async def test_type_conversion(self):
115+
a = ExampleReable(int, TOTALLY_RANDOM_NUMBER)
116+
b = ExampleReading(float, False)
117+
with self.assertRaises(TypeError):
118+
b.set_provider(a)
119+
120+
b.set_provider(a, convert=True)
121+
result = await b.do_read()
122+
self.assertEqual(result, float(TOTALLY_RANDOM_NUMBER))
123+
self.assertIsInstance(result, float)
124+
125+
c = ExampleReading(list, False)
126+
with self.assertRaises(TypeError):
127+
c.set_provider(a, convert=True)
128+
129+
130+
class TestConnecting(unittest.TestCase):
131+
def test_subscribing(self):
132+
# TODO
133+
pass
134+
135+
def test_mandatory_reading(self):
136+
# TODO
137+
pass
138+
139+
def test_optional_reading(self):
140+
# TODO
141+
pass
142+
143+
def test_connectable_wrapper(self):
144+
# TODO
145+
pass
146+

0 commit comments

Comments
 (0)