Skip to content

Commit fec1e05

Browse files
committed
test: add ok_and and ok_or tests
1 parent 1f8c22b commit fec1e05

File tree

1 file changed

+101
-236
lines changed

1 file changed

+101
-236
lines changed

tests/test_advanced.py

Lines changed: 101 additions & 236 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,55 @@ def test_result_ok_initialization():
1818
def test_result_err_initialization():
1919
error_message = "An error occurred"
2020
result = Result.as_Err(error_message)
21+
assert result.unwrap() == Err(error_message)
2122
assert result.is_Ok is False
2223
assert result.is_Err is True
2324

2425
with pytest.raises(ResultErr):
25-
result.expect()
26+
_ = result.Ok
2627

2728
with pytest.raises(ResultErr):
28-
result.raises()
29+
_ = result.expect()
30+
31+
with pytest.raises(ResultErr):
32+
_ = result.raises()
33+
34+
35+
def test_result_ok_operation():
36+
result = Ok(10)
37+
38+
# Arithmetic operations
39+
result2 = Ok(20)
40+
result_sum = result + result2
41+
assert result_sum.is_Ok
42+
assert result_sum.unwrap() == 30
43+
44+
# Chaining operations
45+
mapped_result = result.map(lambda x: x * 2)
46+
assert mapped_result.unwrap() == 20
47+
48+
applied_result = result.apply(lambda x: x + 5)
49+
assert applied_result.unwrap() == 15
50+
51+
52+
def test_result_err_operation():
53+
error = Err("Initial error")
54+
55+
# Adding messages
56+
error.add_Err_msg("Additional context")
57+
assert "Additional context" in error.Err_msg
58+
59+
# Checking tracebacks
60+
assert error.Err_traceback is not None
61+
62+
# apply_Err method
63+
result = error.apply_Err(lambda e: e.append("Another error msg", False))
64+
65+
assert result.Err_msg_contains("Initial error")
66+
assert result.Err_msg_contains("Additional context")
67+
assert result.Err_msg_contains("Another error msg")
68+
69+
assert result.unwrap().msg == ["Initial error", "Additional context", "Another error msg"]
2970

3071

3172
# Basic Initialization Tests
@@ -39,23 +80,6 @@ def test_result_ok_attribute():
3980
_ = result.Err
4081

4182

42-
def test_result_err_initialization():
43-
error_message = "An error occurred"
44-
result = Result.as_Err(error_message)
45-
assert result.unwrap() == Err(error_message)
46-
assert result.is_Ok is False
47-
assert result.is_Err is True
48-
49-
with pytest.raises(ResultErr):
50-
_ = result.Ok
51-
52-
with pytest.raises(ResultErr):
53-
result.expect()
54-
55-
with pytest.raises(ResultErr):
56-
result.raises()
57-
58-
5983
# Edge Case Initialization
6084
def test_result_ok_with_none():
6185
result = Result.as_Ok(None)
@@ -76,6 +100,33 @@ def test_result_err_with_empty_string():
76100
result.raises()
77101

78102

103+
# Ok_and and Ok_or
104+
def test_result_Ok_and():
105+
ok2 = Ok(2)
106+
ok4 = Ok(4)
107+
er6 = Err(6)
108+
er8 = Err(8)
109+
110+
assert ok2.Ok_and(ok4) == ok4
111+
assert ok2.Ok_and(er8) == er8
112+
113+
assert er6.Ok_and(ok4) == er6
114+
assert er6.Ok_and(er8) == er6
115+
116+
117+
def test_result_Ok_or():
118+
ok2 = Ok(2)
119+
ok4 = Ok(4)
120+
er6 = Err(6)
121+
er8 = Err(8)
122+
123+
assert ok2.Ok_or(ok4) == ok2
124+
assert ok2.Ok_or(er8) == ok2
125+
126+
assert er6.Ok_or(ok4) == ok4
127+
assert er6.Ok_or(er8) == er8
128+
129+
79130
# Iter Tests
80131
def test_iter_err():
81132
result = Err(10)
@@ -94,6 +145,23 @@ def test_iter_scalar():
94145
assert enter_loop
95146

96147

148+
def test_iter_and_copy():
149+
"""Test iteration and copying functionality of Result."""
150+
result = Ok([1, 2, 3])
151+
152+
# Iteration
153+
iterated = [x for x in result.iter_wrap()]
154+
assert iterated == [1, 2, 3]
155+
156+
# Copy
157+
copied_result = result.copy()
158+
assert copied_result == result
159+
160+
# Clear
161+
result.unwrap().clear()
162+
assert len(result.unwrap()) == 0
163+
164+
97165
def test_iter_list():
98166
lst = [0, 1, 2, 3]
99167
result = Result.as_Ok(lst)
@@ -202,6 +270,20 @@ def test_result_apply():
202270
mapped_result.raises()
203271

204272

273+
def test_result_map_simple():
274+
"""Test mapping functions on Result."""
275+
result = Ok(5)
276+
277+
# Map
278+
mapped_result = result.map(lambda x: x * 2)
279+
assert mapped_result.unwrap() == 10
280+
281+
# Map with fallback
282+
result = Result.as_Err("Error")
283+
mapped_fallback = result.map_or(100, lambda x: x * 2)
284+
assert mapped_fallback == 100
285+
286+
205287
def test_result_map():
206288
result = Result.as_Ok(10)
207289
mapped_result = result.map(lambda x: x * 2)
@@ -252,217 +334,6 @@ def test_result_map_err():
252334
assert ok_result.expect() == 10
253335

254336

255-
def test_result_apply_chain():
256-
new_result = (
257-
Ok(10)
258-
.apply(lambda x: Ok(x * 2)) # Ok(20)
259-
.apply(lambda x: Ok(x * 2)) # Ok(40)
260-
.apply(lambda x: Ok(x * 2)) # Ok(80)
261-
.apply(lambda x: Ok(x * 2)) # Ok(160)
262-
)
263-
assert new_result.is_Ok is True
264-
assert new_result.expect() == 160
265-
266-
error_result = (
267-
Err("Error")
268-
.apply(lambda x: Ok(x * 2)) # Appends to error
269-
.apply(lambda x: Ok(x * 2)) # Appends to error
270-
.apply(lambda x: Ok(x * 2)) # Appends to error
271-
)
272-
assert error_result.is_Err is True
273-
with pytest.raises(ResultErr):
274-
error_result.expect()
275-
276-
result_error = Ok(10)
277-
# Separated
278-
new_result = result_error.apply(lambda x: Result.as_Ok(x * 2)).apply(lambda x: Result.as_Ok(x * 2))
279-
assert new_result.is_Err is False
280-
new_result = new_result.apply(lambda x: Result.as_Ok(x * 0)).apply(lambda x: Result.as_Ok(10 / x))
281-
assert new_result.is_Err is True
282-
283-
with pytest.raises(ResultErr):
284-
new_result = (
285-
Ok(10)
286-
.apply(lambda x: Ok(x * 2)) # Ok(20)
287-
.apply(lambda x: Ok(x * 2)) # Ok(40)
288-
.apply(lambda x: Ok(x * 0)) # Ok(40)
289-
.apply(lambda x: Ok(10 / x)) # Raises ZeroDiv Error
290-
.apply(lambda x: Ok(x + 1)) # Appends to error message
291-
.raises() # Raises Exception if in Err state
292-
)
293-
294-
295-
def test_result_method_chain():
296-
from math import sqrt
297-
298-
def div(numerator, denominator):
299-
return numerator / denominator
300-
301-
def plus11(x, *args):
302-
# *args not used, but needed because apply_or_else(efunc, ofunc) requires
303-
# both functions to have the same arg length, see `apply_or_else(plus11, div, 0)` or `.apply_or_else(plus11, div, 2)`
304-
return x + 11
305-
306-
def pow2(x):
307-
return x**2
308-
309-
def neg(x, *args):
310-
# *args not used, but needed because apply_or_else(efunc, ofunc) requires
311-
# both functions to have the same arg length, see `.apply_or_else(neg, div, 0)`
312-
return -x
313-
314-
a = Ok(5)
315-
316-
with pytest.raises(ValueError):
317-
fail1 = a.map(pow2).map(plus11).map(sqrt).map(neg).map(sqrt)
318-
# 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
319-
320-
with pytest.raises(ValueError):
321-
fail2 = a.map(pow2).map(plus11).map(sqrt).map(neg).map_or(None, sqrt)
322-
# 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
323-
324-
b = (
325-
a.apply(pow2) # Ok(5) -> Ok(25)
326-
.apply(plus11) # -> Ok(36)
327-
.apply(sqrt) # -> Ok(6)
328-
.apply(neg) # -> Ok(-6)
329-
.apply(sqrt) # -> Err("Result.apply exception | ValueError: math domain error")
330-
)
331-
332-
c = (
333-
a.apply(pow2) # Ok(5) -> Ok(25)
334-
.apply(plus11) # -> Ok(36)
335-
.apply(sqrt) # -> Ok(6)
336-
.apply(neg) # -> Ok(-6)
337-
.apply_or(None, sqrt) # -> Ok(None)
338-
)
339-
340-
d = (
341-
a.apply(pow2) # Ok(5) -> Ok(25)
342-
.apply(plus11) # -> Ok(36)
343-
.apply(sqrt) # -> Ok(6)
344-
.apply(neg) # -> Ok(3)
345-
.apply_or_else(plus11, sqrt) # -> Ok(5)
346-
)
347-
348-
e = (
349-
a.apply(pow2) # Ok(5) -> Ok(25)
350-
.apply(plus11) # -> Ok(36)
351-
.apply(sqrt) # -> Ok(6)
352-
.apply(div, 2) # -> Ok(3)
353-
.apply(div, 0) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
354-
)
355-
# 5 -> 25 -> 36 -> 6 -> 3 -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
356-
357-
f = (
358-
a.apply(pow2) # Ok(5) -> Ok(25)
359-
.apply(plus11) # -> Ok(36)
360-
.apply(sqrt) # -> Ok(6)
361-
.apply(div, 2) # -> Ok(3)
362-
.apply_or_else(plus11, div, 0) # -> Ok(14)
363-
)
364-
365-
g = (
366-
a.apply(pow2) # Ok(5) -> Ok(25)
367-
.apply(plus11) # -> Ok(36)
368-
.apply(sqrt) # -> Ok(6)
369-
.apply_or_else(neg, div, 0) # -> Ok(-6)
370-
.apply_or_else(plus11, div, 2) # -> Ok(-3)
371-
)
372-
373-
assert a.is_Ok and a == Ok(5)
374-
assert b.is_Err and b.Err_msg_contains("ValueError")
375-
assert c.is_Ok and c == Ok(None)
376-
assert d.is_Ok and d == Ok(5)
377-
assert e.is_Err and e.Err_msg_contains("ZeroDivisionError")
378-
assert f.is_Ok and f == Ok(14)
379-
assert g.is_Ok and g == Ok(-3)
380-
381-
382-
def test_result_method_chain_lambda():
383-
from math import sqrt
384-
# div = lambda x, y: x / y
385-
# plus11 = lambda x: x + 11
386-
# pow2 = lambda x: x**2
387-
# neg = lambda x: -x
388-
389-
a = Ok(5)
390-
391-
with pytest.raises(ValueError):
392-
fail1 = (
393-
a.map(lambda x: x**2) # Ok(5) -> Ok(25)
394-
.map(lambda x: x + 11) # -> Ok(36)
395-
.map(sqrt) # -> Ok(6)
396-
.map(lambda x: -x) # -> Ok(-6)
397-
.map(sqrt) # -> raise ValueError
398-
)
399-
400-
with pytest.raises(ValueError):
401-
fail2 = (
402-
a.map(lambda x: x**2) # Ok(5) -> Ok(25)
403-
.map(lambda x: x + 11) # -> Ok(36)
404-
.map(sqrt) # -> Ok(6)
405-
.map(lambda x: -x) # -> Ok(-6)
406-
.map_or(None, sqrt) # -> raise ValueError
407-
)
408-
409-
b = (
410-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
411-
.apply(lambda x: x + 11) # -> Ok(36)
412-
.apply(sqrt) # -> Ok(6)
413-
.apply(lambda x: -x) # -> Ok(-6)
414-
.apply(sqrt) # -> Err("Result.apply exception | ValueError: math domain error")
415-
)
416-
417-
c = (
418-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
419-
.apply(lambda x: x + 11) # -> Ok(36)
420-
.apply(sqrt) # -> Ok(6)
421-
.apply(lambda x: -x) # -> Ok(-6)
422-
.apply_or(None, sqrt) # -> Ok(None)
423-
)
424-
425-
d = (
426-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
427-
.apply(lambda x: x + 11) # -> Ok(36)
428-
.apply(sqrt) # -> Ok(6)
429-
.apply(lambda x: -x) # -> Ok(-6)
430-
.apply_or_else(lambda x: x + 11, sqrt) # -> Ok(5)
431-
)
432-
433-
e = (
434-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
435-
.apply(lambda x: x + 11) # -> Ok(36)
436-
.apply(sqrt) # -> Ok(6)
437-
.apply(lambda x, y: x / y, 2) # -> Ok(3)
438-
.apply(lambda x, y: x / y, 0) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
439-
)
440-
441-
f = (
442-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
443-
.apply(lambda x: x + 11) # -> Ok(36)
444-
.apply(sqrt) # -> Ok(6)
445-
.apply(lambda x, y: x / y, 2) # -> Ok(3)
446-
.apply_or_else(lambda x, y: x + 11, lambda x, y: x / y, 0) # -> Ok(14)
447-
)
448-
449-
g = (
450-
a.apply(lambda x: x**2) # Ok(5) -> Ok(25)
451-
.apply(lambda x: x + 11) # -> Ok(36)
452-
.apply(sqrt) # -> Ok(6)
453-
.apply_or_else(lambda x, y: -x, lambda x, y: x / y, 0) # -> Ok(-6)
454-
.apply_or_else(lambda x, y: x + 11, lambda x, y: x / y, 2) # -> Ok(-3)
455-
)
456-
457-
assert a.is_Ok and a == Ok(5)
458-
assert b.is_Err and b.Err_msg_contains("ValueError")
459-
assert c.is_Ok and c == Ok(None)
460-
assert d.is_Ok and d == Ok(5)
461-
assert e.is_Err and e.Err_msg_contains("ZeroDivisionError")
462-
assert f.is_Ok and f == Ok(14)
463-
assert g.is_Ok and g == Ok(-3)
464-
465-
466337
# Arithmetic Operator Overloading
467338
def test_addition():
468339
result1 = Ok(10)
@@ -556,12 +427,6 @@ def test_error_message_integrity():
556427
result.raises()
557428

558429

559-
def test_error_chaining_integrity():
560-
error_result = Err("Initial Error")
561-
chained_result = error_result.map(lambda x: x * 2).map_Err(lambda e: f"{e.str()} - chained")
562-
assert chained_result.is_Err is False # map_Err returns Ok(f(e))
563-
564-
565430
# Integration Tests
566431
def test_real_world_scenario():
567432
def divide(a, b):

0 commit comments

Comments
 (0)