Skip to content

Commit 891d1c9

Browse files
committed
test: add test_method_chaining.py
1 parent fec1e05 commit 891d1c9

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed

tests/test_method_chaining.py

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
import pytest
2+
from ResultContainer import Result, Ok, Err, ResultErr
3+
4+
5+
def test_error_chaining_integrity():
6+
error_result = Err("Initial Error")
7+
chained_result = error_result.map(lambda x: x * 2).map_Err(lambda e: f"{e.str()} - chained")
8+
assert chained_result.is_Err is False # map_Err returns Ok(f(e))
9+
10+
11+
def test_result_repeated_ok_chain():
12+
new_result = (
13+
Ok(10)
14+
.apply(lambda x: Ok(x * 2)) # Ok(20)
15+
.apply(lambda x: Ok(x * 2)) # Ok(40)
16+
.apply(lambda x: Ok(x * 2)) # Ok(80)
17+
.apply(lambda x: Ok(x * 2)) # Ok(160)
18+
)
19+
assert new_result.is_Ok is True
20+
assert new_result.expect() == 160
21+
22+
result = Ok(10)
23+
new_result = result.apply(lambda x: Result.as_Ok(x * 2)).apply(lambda x: Result.as_Ok(x * 2))
24+
25+
assert new_result.is_Err is False
26+
assert new_result.is_Ok is True
27+
assert new_result == 40
28+
29+
30+
def test_result_repeated_err_chain():
31+
error_result = (
32+
Err("Error")
33+
.apply(lambda x: Ok(x * 2)) # Appends to error
34+
.apply(lambda x: Ok(x * 2)) # Appends to error
35+
.apply(lambda x: Ok(x * 2)) # Appends to error
36+
)
37+
assert error_result.is_Err is True
38+
39+
with pytest.raises(ResultErr):
40+
error_result.expect()
41+
42+
with pytest.raises(ResultErr):
43+
error_result.raises()
44+
45+
46+
def test_result_repeated_ok_err_chain():
47+
result = Ok(10)
48+
49+
new_result = result.apply(lambda x: Result.as_Ok(x * 2)).apply(lambda x: Result.as_Ok(x * 2))
50+
51+
assert new_result.is_Err is False
52+
53+
new_result = new_result.apply(lambda x: Result.as_Ok(x * 0)).apply(lambda x: Result.as_Ok(10 / x))
54+
55+
assert new_result.is_Err is True
56+
57+
with pytest.raises(ResultErr):
58+
new_result = (
59+
Ok(10)
60+
.apply(lambda x: Ok(x * 2)) # Ok(20)
61+
.apply(lambda x: Ok(x * 2)) # Ok(40)
62+
.apply(lambda x: Ok(x * 0)) # Ok(40)
63+
.apply(lambda x: Ok(10 / x)) # Raises ZeroDiv Error
64+
.apply(lambda x: Ok(x + 1)) # Appends to error message
65+
.expect() # Raises Exception if in Err state
66+
)
67+
68+
with pytest.raises(ResultErr):
69+
new_result = (
70+
Ok(10)
71+
.apply(lambda x: Ok(x * 2)) # Ok(20)
72+
.apply(lambda x: Ok(x * 2)) # Ok(40)
73+
.apply(lambda x: Ok(x * 0)) # Ok(40)
74+
.apply(lambda x: Ok(10 / x)) # Raises ZeroDiv Error
75+
.apply(lambda x: Ok(x + 1)) # Appends to error message
76+
.raises() # Raises Exception if in Err state
77+
)
78+
79+
80+
def test_result_method_map_chain():
81+
from math import sqrt
82+
83+
def plus11(x):
84+
return x + 11
85+
86+
def pow2(x):
87+
return x**2
88+
89+
def neg(x):
90+
return -x
91+
92+
a = Ok(5)
93+
b = None
94+
95+
with pytest.raises(ValueError):
96+
b = a.map(pow2).map(plus11).map(sqrt).map(neg).map(sqrt)
97+
# 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
98+
99+
with pytest.raises(ValueError):
100+
b = a.map(pow2).map(plus11).map(sqrt).map(neg).map_or(None, sqrt)
101+
# 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
102+
103+
assert b is None
104+
105+
106+
def test_result_method_map_chain_lambda():
107+
from math import sqrt
108+
# plus11 = lambda x: x + 11
109+
# pow2 = lambda x: x**2
110+
# neg = lambda x: -x
111+
112+
a = Ok(5)
113+
b = None
114+
115+
with pytest.raises(ValueError):
116+
b = (
117+
a.map(lambda x: x**2) # Ok(5) -> Ok(25)
118+
.map(lambda x: x + 11) # -> Ok(36)
119+
.map(sqrt) # -> Ok(6)
120+
.map(lambda x: -x) # -> Ok(-6)
121+
.map(sqrt) # -> raise ValueError
122+
)
123+
124+
with pytest.raises(ValueError):
125+
b = (
126+
a.map(lambda x: x**2) # Ok(5) -> Ok(25)
127+
.map(lambda x: x + 11) # -> Ok(36)
128+
.map(sqrt) # -> Ok(6)
129+
.map(lambda x: -x) # -> Ok(-6)
130+
.map_or(None, sqrt) # -> raise ValueError
131+
)
132+
133+
assert b is None
134+
135+
136+
def test_result_method_apply_chain():
137+
from math import sqrt
138+
139+
def div(numerator, denominator):
140+
return numerator / denominator
141+
142+
def plus11(x, *args):
143+
# *args not used, but needed because apply_or_else(efunc, ofunc) requires
144+
# both functions to have the same arg length, see `apply_or_else(plus11, div, 0)` or `.apply_or_else(plus11, div, 2)`
145+
return x + 11
146+
147+
def pow2(x):
148+
return x**2
149+
150+
def neg(x, *args):
151+
# *args not used, but needed because apply_or_else(efunc, ofunc) requires
152+
# both functions to have the same arg length, see `.apply_or_else(neg, div, 0)`
153+
return -x
154+
155+
a = Ok(5)
156+
157+
b = (
158+
a.apply(pow2) # Ok(5) -> Ok(25)
159+
.apply(plus11) # -> Ok(36)
160+
.apply(sqrt) # -> Ok(6)
161+
.apply(neg) # -> Ok(-6)
162+
.apply(sqrt) # -> Err("Result.apply exception | ValueError: math domain error")
163+
)
164+
165+
c = (
166+
a.apply(pow2) # Ok(5) -> Ok(25)
167+
.apply(plus11) # -> Ok(36)
168+
.apply(sqrt) # -> Ok(6)
169+
.apply(neg) # -> Ok(-6)
170+
.apply_or(None, sqrt) # -> Ok(None)
171+
)
172+
173+
d = (
174+
a.apply(pow2) # Ok(5) -> Ok(25)
175+
.apply(plus11) # -> Ok(36)
176+
.apply(sqrt) # -> Ok(6)
177+
.apply(neg) # -> Ok(3)
178+
.apply_or_else(plus11, sqrt) # -> Ok(5)
179+
)
180+
181+
e = (
182+
a.apply(pow2) # Ok(5) -> Ok(25)
183+
.apply(plus11) # -> Ok(36)
184+
.apply(sqrt) # -> Ok(6)
185+
.apply(div, 2) # -> Ok(3)
186+
.apply(div, 0) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
187+
)
188+
# 5 -> 25 -> 36 -> 6 -> 3 -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
189+
190+
f = (
191+
a.apply(pow2) # Ok(5) -> Ok(25)
192+
.apply(plus11) # -> Ok(36)
193+
.apply(sqrt) # -> Ok(6)
194+
.apply(div, 2) # -> Ok(3)
195+
.apply_or_else(plus11, div, 0) # -> Ok(14)
196+
)
197+
198+
g = (
199+
a.apply(pow2) # Ok(5) -> Ok(25)
200+
.apply(plus11) # -> Ok(36)
201+
.apply(sqrt) # -> Ok(6)
202+
.apply_or_else(neg, div, 0) # -> Ok(-6)
203+
.apply_or_else(plus11, div, 2) # -> Ok(-3)
204+
)
205+
206+
assert a.is_Ok and a == Ok(5)
207+
assert b.is_Err and b.Err_msg_contains("ValueError")
208+
assert c.is_Ok and c == Ok(None)
209+
assert d.is_Ok and d == Ok(5)
210+
assert e.is_Err and e.Err_msg_contains("ZeroDivisionError")
211+
assert f.is_Ok and f == Ok(14)
212+
assert g.is_Ok and g == Ok(-3)
213+
214+
215+
def test_result_method_apply_chain_lambda():
216+
from math import sqrt
217+
# div = lambda x, y: x / y
218+
# plus11 = lambda x: x + 11
219+
# pow2 = lambda x: x**2
220+
# neg = lambda x: -x
221+
222+
a = Ok(5)
223+
224+
b = (
225+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
226+
.apply(lambda x: x + 11) # -> Ok(36)
227+
.apply(sqrt) # -> Ok(6)
228+
.apply(lambda x: -x) # -> Ok(-6)
229+
.apply(sqrt) # -> Err("Result.apply exception | ValueError: math domain error")
230+
)
231+
232+
c = (
233+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
234+
.apply(lambda x: x + 11) # -> Ok(36)
235+
.apply(sqrt) # -> Ok(6)
236+
.apply(lambda x: -x) # -> Ok(-6)
237+
.apply_or(None, sqrt) # -> Ok(None)
238+
)
239+
240+
d = (
241+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
242+
.apply(lambda x: x + 11) # -> Ok(36)
243+
.apply(sqrt) # -> Ok(6)
244+
.apply(lambda x: -x) # -> Ok(-6)
245+
.apply_or_else(lambda x: x + 11, sqrt) # -> Ok(5)
246+
)
247+
248+
e = (
249+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
250+
.apply(lambda x: x + 11) # -> Ok(36)
251+
.apply(sqrt) # -> Ok(6)
252+
.apply(lambda x, y: x / y, 2) # -> Ok(3)
253+
.apply(lambda x, y: x / y, 0) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
254+
)
255+
256+
f = (
257+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
258+
.apply(lambda x: x + 11) # -> Ok(36)
259+
.apply(sqrt) # -> Ok(6)
260+
.apply(lambda x, y: x / y, 2) # -> Ok(3)
261+
.apply_or_else(lambda x, y: x + 11, lambda x, y: x / y, 0) # -> Ok(14)
262+
)
263+
264+
g = (
265+
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
266+
.apply(lambda x: x + 11) # -> Ok(36)
267+
.apply(sqrt) # -> Ok(6)
268+
.apply_or_else(lambda x, y: -x, lambda x, y: x / y, 0) # -> Ok(-6)
269+
.apply_or_else(lambda x, y: x + 11, lambda x, y: x / y, 2) # -> Ok(-3)
270+
)
271+
272+
assert a.is_Ok and a == Ok(5)
273+
assert b.is_Err and b.Err_msg_contains("ValueError")
274+
assert c.is_Ok and c == Ok(None)
275+
assert d.is_Ok and d == Ok(5)
276+
assert e.is_Err and e.Err_msg_contains("ZeroDivisionError")
277+
assert f.is_Ok and f == Ok(14)
278+
assert g.is_Ok and g == Ok(-3)

0 commit comments

Comments
 (0)