Skip to content

Commit fbfb6d6

Browse files
committed
convert test_do.py to use pytest API
1 parent d0e39c5 commit fbfb6d6

File tree

1 file changed

+125
-122
lines changed

1 file changed

+125
-122
lines changed

effect/test_do.py

Lines changed: 125 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66

77
import six
88

9-
from testtools import TestCase
10-
from testtools.matchers import raises as match_raises, MatchesException
11-
129
from . import (
1310
ComposedDispatcher, Constant, Effect, Error, TypeDispatcher,
1411
base_dispatcher, sync_perform, sync_performer)
@@ -19,125 +16,131 @@ def perf(e):
1916
return sync_perform(base_dispatcher, e)
2017

2118

22-
class DoTests(TestCase):
23-
24-
def test_do_non_gf(self):
25-
"""When do is passed a non-generator function, it raises an error."""
26-
f = lambda: None
27-
self.assertThat(
28-
lambda: perf(do(f)()),
29-
match_raises(TypeError(
30-
"%r is not a generator function. It returned None." % (f,)
31-
)))
32-
33-
def test_do_return(self):
34-
"""
35-
When a @do function yields a do_return, the given value becomes the
36-
eventual result.
37-
"""
38-
@do
39-
def f():
40-
yield do_return("hello")
41-
self.assertEqual(perf(f()), "hello")
42-
43-
def test_yield_effect(self):
44-
"""Yielding an effect in @do results in the Effect's result."""
45-
@do
46-
def f():
47-
x = yield Effect(Constant(3))
48-
yield do_return(x)
49-
self.assertEqual(perf(f()), 3)
50-
51-
def test_fall_off_the_end(self):
52-
"""Falling off the end results in None."""
53-
@do
54-
def f():
55-
yield Effect(Constant(3))
56-
self.assertEqual(perf(f()), None)
57-
58-
def test_yield_non_effect(self):
59-
"""Yielding a non-Effect results in a TypeError."""
60-
@do
61-
def f():
62-
yield 1
63-
result = f()
64-
e = self.assertRaises(TypeError, lambda: perf(result))
65-
self.assertTrue(
66-
str(e).startswith(
67-
'@do functions must only yield Effects or results of '
68-
'do_return. Got 1 from <generator object f at'))
69-
70-
def test_raise_from_effect(self):
71-
"""
72-
If an Effect results in an error, it will be raised as a synchronous
73-
exception in the generator.
74-
"""
75-
@do
76-
def f():
77-
try:
78-
yield Effect(Error(ZeroDivisionError('foo')))
79-
except:
80-
got_error = sys.exc_info()
81-
yield do_return(got_error)
82-
83-
self.assertThat(
84-
perf(f()),
85-
MatchesException(ZeroDivisionError('foo')))
86-
87-
def test_works_with_sync_perform(self):
88-
"""@sync_performer and @do cooperate fine."""
89-
@sync_performer
90-
@do
91-
def perform_myintent(dispatcher, myintent):
92-
result = yield Effect(Constant(1))
93-
yield do_return(result + 1)
94-
95-
class MyIntent(object):
96-
pass
97-
98-
disp = ComposedDispatcher([
99-
TypeDispatcher({MyIntent: perform_myintent}),
100-
base_dispatcher])
101-
self.assertEqual(sync_perform(disp, Effect(MyIntent())), 2)
102-
103-
def test_promote_metadata(self):
104-
"""
105-
The decorator copies metadata from the wrapped function onto the
106-
wrapper.
107-
"""
108-
def original(dispatcher, intent):
109-
"""Original!"""
110-
yield do_return(1)
111-
original.attr = 1
112-
wrapped = do(original)
113-
self.assertEqual(wrapped.__name__, 'original')
114-
self.assertEqual(wrapped.attr, 1)
115-
self.assertEqual(wrapped.__doc__, 'Original!')
116-
117-
def test_ignore_lack_of_metadata(self):
118-
"""
119-
When the original callable is not a function, a new function is still
120-
returned.
121-
"""
122-
def original(something, dispatcher, intent):
123-
"""Original!"""
124-
pass
125-
new_func = partial(original, 'something')
126-
original.attr = 1
127-
wrapped = do(new_func)
128-
self.assertEqual(wrapped.__name__, 'do_wrapper')
129-
130-
def test_repeatable_effect(self):
131-
"""
132-
The Effect returned by the call to the @do function is repeatable.
133-
"""
134-
@do
135-
def f():
136-
x = yield Effect(Constant('foo'))
137-
yield do_return(x)
138-
eff = f()
139-
self.assertEqual(perf(eff), 'foo')
140-
self.assertEqual(perf(eff), 'foo')
19+
def test_do_non_gf():
20+
"""When do is passed a non-generator function, it raises an error."""
21+
f = lambda: None
22+
with raises(TypeError) as err_info:
23+
perf(do(f)())
24+
assert (str(err_info.value)
25+
== "%r is not a generator function. It returned None." % (f,))
26+
27+
28+
def test_do_return():
29+
"""
30+
When a @do function yields a do_return, the given value becomes the
31+
eventual result.
32+
"""
33+
@do
34+
def f():
35+
yield do_return("hello")
36+
assert perf(f()) == "hello"
37+
38+
39+
def test_yield_effect():
40+
"""Yielding an effect in @do results in the Effect's result."""
41+
@do
42+
def f():
43+
x = yield Effect(Constant(3))
44+
yield do_return(x)
45+
perf(f()) == 3
46+
47+
48+
def test_fall_off_the_end():
49+
"""Falling off the end results in None."""
50+
@do
51+
def f():
52+
yield Effect(Constant(3))
53+
assert perf(f()) is None
54+
55+
56+
def test_yield_non_effect():
57+
"""Yielding a non-Effect results in a TypeError."""
58+
@do
59+
def f():
60+
yield 1
61+
result = f()
62+
with raises(TypeError) as err_info:
63+
perf(result)
64+
assert str(err_info.value).startswith(
65+
'@do functions must only yield Effects or results of '
66+
'do_return. Got 1 from <generator object f at')
67+
68+
69+
def test_raise_from_effect():
70+
"""
71+
If an Effect results in an error, it will be raised as a synchronous
72+
exception in the generator.
73+
"""
74+
@do
75+
def f():
76+
try:
77+
yield Effect(Error(ZeroDivisionError('foo')))
78+
except:
79+
got_error = sys.exc_info()
80+
yield do_return(got_error)
81+
82+
exc_type, exc, _ = perf(f())
83+
assert exc_type is ZeroDivisionError
84+
assert str(exc) == 'foo'
85+
86+
87+
def test_works_with_sync_perform():
88+
"""@sync_performer and @do cooperate fine."""
89+
@sync_performer
90+
@do
91+
def perform_myintent(dispatcher, myintent):
92+
result = yield Effect(Constant(1))
93+
yield do_return(result + 1)
94+
95+
class MyIntent(object):
96+
pass
97+
98+
disp = ComposedDispatcher([
99+
TypeDispatcher({MyIntent: perform_myintent}),
100+
base_dispatcher])
101+
assert sync_perform(disp, Effect(MyIntent())) == 2
102+
103+
104+
def test_promote_metadata():
105+
"""
106+
The decorator copies metadata from the wrapped function onto the
107+
wrapper.
108+
"""
109+
def original(dispatcher, intent):
110+
"""Original!"""
111+
yield do_return(1)
112+
original.attr = 1
113+
wrapped = do(original)
114+
assert wrapped.__name__ == 'original'
115+
assert wrapped.attr == 1
116+
assert wrapped.__doc__ == 'Original!'
117+
118+
119+
def test_ignore_lack_of_metadata():
120+
"""
121+
When the original callable is not a function, a new function is still
122+
returned.
123+
"""
124+
def original(something, dispatcher, intent):
125+
"""Original!"""
126+
pass
127+
new_func = partial(original, 'something')
128+
original.attr = 1
129+
wrapped = do(new_func)
130+
assert wrapped.__name__ == 'do_wrapper'
131+
132+
133+
def test_repeatable_effect():
134+
"""
135+
The Effect returned by the call to the @do function is repeatable.
136+
"""
137+
@do
138+
def f():
139+
x = yield Effect(Constant('foo'))
140+
yield do_return(x)
141+
eff = f()
142+
assert perf(eff) == 'foo'
143+
perf(eff) == 'foo'
141144

142145

143146
def test_stop_iteration_only_local():

0 commit comments

Comments
 (0)