Skip to content

Commit 11132fc

Browse files
germin8Benjamin Townsendfaif
authored
Translate several doctest tests to pytest (#414)
Co-authored-by: Benjamin Townsend <[email protected]> Co-authored-by: Sakis Kasampalis <[email protected]>
1 parent d1e262f commit 11132fc

File tree

8 files changed

+133
-45
lines changed

8 files changed

+133
-45
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@ venv/
1010
.vscode/
1111
.python-version
1212
.coverage
13+
.project
14+
.pydevproject
15+
/.pytest_cache/
1316
build/
14-
dist/
17+
dist/

patterns/behavioral/catalog.py

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88

99

1010
class Catalog:
11-
"""catalog of multiple static methods that are executed depending on an init
12-
13-
parameter
11+
"""catalog of multiple static methods that are executed depending on an init parameter
1412
"""
1513

1614
def __init__(self, param: str) -> None:
@@ -30,25 +28,24 @@ def __init__(self, param: str) -> None:
3028
raise ValueError(f"Invalid Value for Param: {param}")
3129

3230
@staticmethod
33-
def _static_method_1() -> None:
34-
print("executed method 1!")
31+
def _static_method_1() -> str:
32+
return "executed method 1!"
3533

3634
@staticmethod
37-
def _static_method_2() -> None:
38-
print("executed method 2!")
35+
def _static_method_2() -> str:
36+
return "executed method 2!"
3937

40-
def main_method(self) -> None:
38+
def main_method(self) -> str:
4139
"""will execute either _static_method_1 or _static_method_2
4240
4341
depending on self.param value
4442
"""
45-
self._static_method_choices[self.param]()
43+
return self._static_method_choices[self.param]()
4644

4745

4846
# Alternative implementation for different levels of methods
4947
class CatalogInstance:
5048
"""catalog of multiple methods that are executed depending on an init
51-
5249
parameter
5350
"""
5451

@@ -61,29 +58,28 @@ def __init__(self, param: str) -> None:
6158
else:
6259
raise ValueError(f"Invalid Value for Param: {param}")
6360

64-
def _instance_method_1(self) -> None:
65-
print(f"Value {self.x1}")
61+
def _instance_method_1(self) -> str:
62+
return f"Value {self.x1}"
6663

67-
def _instance_method_2(self) -> None:
68-
print(f"Value {self.x2}")
64+
def _instance_method_2(self) -> str:
65+
return f"Value {self.x2}"
6966

7067
_instance_method_choices = {
7168
"param_value_1": _instance_method_1,
7269
"param_value_2": _instance_method_2,
7370
}
7471

75-
def main_method(self) -> None:
72+
def main_method(self) -> str:
7673
"""will execute either _instance_method_1 or _instance_method_2
7774
7875
depending on self.param value
7976
"""
80-
self._instance_method_choices[self.param].__get__(self)() # type: ignore
77+
return self._instance_method_choices[self.param].__get__(self)() # type: ignore
8178
# type ignore reason: https://github.com/python/mypy/issues/10206
8279

8380

8481
class CatalogClass:
8582
"""catalog of multiple class methods that are executed depending on an init
86-
8783
parameter
8884
"""
8985

@@ -98,30 +94,29 @@ def __init__(self, param: str) -> None:
9894
raise ValueError(f"Invalid Value for Param: {param}")
9995

10096
@classmethod
101-
def _class_method_1(cls) -> None:
102-
print(f"Value {cls.x1}")
97+
def _class_method_1(cls) -> str:
98+
return f"Value {cls.x1}"
10399

104100
@classmethod
105-
def _class_method_2(cls) -> None:
106-
print(f"Value {cls.x2}")
101+
def _class_method_2(cls) -> str:
102+
return f"Value {cls.x2}"
107103

108104
_class_method_choices = {
109105
"param_value_1": _class_method_1,
110106
"param_value_2": _class_method_2,
111107
}
112108

113-
def main_method(self):
109+
def main_method(self) -> str:
114110
"""will execute either _class_method_1 or _class_method_2
115111
116112
depending on self.param value
117113
"""
118-
self._class_method_choices[self.param].__get__(None, self.__class__)() # type: ignore
114+
return self._class_method_choices[self.param].__get__(None, self.__class__)() # type: ignore
119115
# type ignore reason: https://github.com/python/mypy/issues/10206
120116

121117

122118
class CatalogStatic:
123119
"""catalog of multiple static methods that are executed depending on an init
124-
125120
parameter
126121
"""
127122

@@ -133,45 +128,45 @@ def __init__(self, param: str) -> None:
133128
raise ValueError(f"Invalid Value for Param: {param}")
134129

135130
@staticmethod
136-
def _static_method_1() -> None:
137-
print("executed method 1!")
131+
def _static_method_1() -> str:
132+
return "executed method 1!"
138133

139134
@staticmethod
140-
def _static_method_2() -> None:
141-
print("executed method 2!")
135+
def _static_method_2() -> str:
136+
return "executed method 2!"
142137

143138
_static_method_choices = {
144139
"param_value_1": _static_method_1,
145140
"param_value_2": _static_method_2,
146141
}
147142

148-
def main_method(self) -> None:
143+
def main_method(self) -> str:
149144
"""will execute either _static_method_1 or _static_method_2
150145
151146
depending on self.param value
152147
"""
153148

154-
self._static_method_choices[self.param].__get__(None, self.__class__)() # type: ignore
149+
return self._static_method_choices[self.param].__get__(None, self.__class__)() # type: ignore
155150
# type ignore reason: https://github.com/python/mypy/issues/10206
156151

157152

158153
def main():
159154
"""
160155
>>> test = Catalog('param_value_2')
161156
>>> test.main_method()
162-
executed method 2!
157+
'executed method 2!'
163158
164159
>>> test = CatalogInstance('param_value_1')
165160
>>> test.main_method()
166-
Value x1
161+
'Value x1'
167162
168163
>>> test = CatalogClass('param_value_2')
169164
>>> test.main_method()
170-
Value x2
165+
'Value x2'
171166
172167
>>> test = CatalogStatic('param_value_1')
173168
>>> test.main_method()
174-
executed method 1!
169+
'executed method 1!'
175170
"""
176171

177172

patterns/behavioral/mediator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class ChatRoom:
1515
"""Mediator class"""
1616

1717
def display_message(self, user: User, message: str) -> None:
18-
print(f"[{user} says]: {message}")
18+
return f"[{user} says]: {message}"
1919

2020

2121
class User:
@@ -26,7 +26,7 @@ def __init__(self, name: str) -> None:
2626
self.chat_room = ChatRoom()
2727

2828
def say(self, message: str) -> None:
29-
self.chat_room.display_message(self, message)
29+
return self.chat_room.display_message(self, message)
3030

3131
def __str__(self) -> str:
3232
return self.name
@@ -39,11 +39,11 @@ def main():
3939
>>> ethan = User('Ethan')
4040
4141
>>> molly.say("Hi Team! Meeting at 3 PM today.")
42-
[Molly says]: Hi Team! Meeting at 3 PM today.
42+
'[Molly says]: Hi Team! Meeting at 3 PM today.'
4343
>>> mark.say("Roger that!")
44-
[Mark says]: Roger that!
44+
'[Mark says]: Roger that!'
4545
>>> ethan.say("Alright.")
46-
[Ethan says]: Alright.
46+
'[Ethan says]: Alright.'
4747
"""
4848

4949

patterns/behavioral/visitor.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ def visit(self, node, *args, **kwargs):
4646
return meth(node, *args, **kwargs)
4747

4848
def generic_visit(self, node, *args, **kwargs):
49-
print("generic_visit " + node.__class__.__name__)
49+
return "generic_visit " + node.__class__.__name__
5050

5151
def visit_B(self, node, *args, **kwargs):
52-
print("visit_B " + node.__class__.__name__)
52+
return "visit_B " + node.__class__.__name__
5353

5454

5555
def main():
@@ -58,13 +58,13 @@ def main():
5858
>>> visitor = Visitor()
5959
6060
>>> visitor.visit(a)
61-
generic_visit A
61+
'generic_visit A'
6262
6363
>>> visitor.visit(b)
64-
visit_B B
64+
'visit_B B'
6565
6666
>>> visitor.visit(c)
67-
visit_B C
67+
'visit_B C'
6868
"""
6969

7070

tests/behavioral/test_catalog.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
3+
from patterns.behavioral.catalog import Catalog, CatalogClass, CatalogInstance, CatalogStatic
4+
5+
def test_catalog_multiple_methods():
6+
test = Catalog('param_value_2')
7+
token = test.main_method()
8+
assert token == 'executed method 2!'
9+
10+
def test_catalog_multiple_instance_methods():
11+
test = CatalogInstance('param_value_1')
12+
token = test.main_method()
13+
assert token == 'Value x1'
14+
15+
def test_catalog_multiple_class_methods():
16+
test = CatalogClass('param_value_2')
17+
token = test.main_method()
18+
assert token == 'Value x2'
19+
20+
def test_catalog_multiple_static_methods():
21+
test = CatalogStatic('param_value_1')
22+
token = test.main_method()
23+
assert token == 'executed method 1!'

tests/behavioral/test_mediator.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import pytest
2+
3+
from patterns.behavioral.mediator import User
4+
5+
def test_mediated_comments():
6+
molly = User('Molly')
7+
mediated_comment = molly.say("Hi Team! Meeting at 3 PM today.")
8+
assert mediated_comment == "[Molly says]: Hi Team! Meeting at 3 PM today."
9+
10+
mark = User('Mark')
11+
mediated_comment = mark.say("Roger that!")
12+
assert mediated_comment == "[Mark says]: Roger that!"
13+
14+
ethan = User('Ethan')
15+
mediated_comment = ethan.say("Alright.")
16+
assert mediated_comment == "[Ethan says]: Alright."

tests/behavioral/test_memento.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import pytest
2+
3+
from patterns.behavioral.memento import NumObj, Transaction
4+
5+
def test_object_creation():
6+
num_obj = NumObj(-1)
7+
assert repr(num_obj) == '<NumObj: -1>', "Object representation not as expected"
8+
9+
def test_rollback_on_transaction():
10+
num_obj = NumObj(-1)
11+
a_transaction = Transaction(True, num_obj)
12+
for _i in range(3):
13+
num_obj.increment()
14+
a_transaction.commit()
15+
assert num_obj.value == 2
16+
17+
for _i in range(3):
18+
num_obj.increment()
19+
try:
20+
num_obj.value += 'x' # will fail
21+
except TypeError:
22+
a_transaction.rollback()
23+
assert num_obj.value == 2, "Transaction did not rollback as expected"
24+
25+
def test_rollback_with_transactional_annotation():
26+
num_obj = NumObj(2)
27+
with pytest.raises(TypeError):
28+
num_obj.do_stuff()
29+
assert num_obj.value == 2

tests/behavioral/test_visitor.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import pytest
2+
3+
from patterns.behavioral.visitor import A, B, C, Visitor
4+
5+
@pytest.fixture
6+
def visitor():
7+
return Visitor()
8+
9+
def test_visiting_generic_node(visitor):
10+
a = A()
11+
token = visitor.visit(a)
12+
assert token == 'generic_visit A', "The expected generic object was not called"
13+
14+
def test_visiting_specific_nodes(visitor):
15+
b = B()
16+
token = visitor.visit(b)
17+
assert token == 'visit_B B', "The expected specific object was not called"
18+
19+
def test_visiting_inherited_nodes(visitor):
20+
c = C()
21+
token = visitor.visit(c)
22+
assert token == 'visit_B C', "The expected inherited object was not called"

0 commit comments

Comments
 (0)