Skip to content

Commit a8cd04e

Browse files
committed
add some testing goodies
1 parent 826cbc5 commit a8cd04e

File tree

2 files changed

+93
-2
lines changed

2 files changed

+93
-2
lines changed

effect/test_testing.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
EQDispatcher,
2828
EQFDispatcher,
2929
SequenceDispatcher,
30+
const,
31+
conste,
3032
fail_effect,
33+
intent_func,
3134
parallel_sequence,
3235
perform_sequence,
3336
resolve_effect,
@@ -462,3 +465,30 @@ def test_parallel_sequence_must_be_parallel():
462465
with pytest.raises(FoldError) as excinfo:
463466
perform_sequence(seq, p)
464467
assert excinfo.value.wrapped_exception[0] is AssertionError
468+
469+
470+
def test_const():
471+
"""
472+
:func:`const` takes an argument but returns fixed value
473+
"""
474+
assert const(2)(MyIntent("whatever")) == 2
475+
assert const("text")(OtherIntent("else")) == "text"
476+
477+
478+
def test_conste():
479+
"""
480+
:func:`conste` takes an argument but always raises given exception
481+
"""
482+
func = conste(ValueError("boo"))
483+
with pytest.raises(ValueError):
484+
func(MyIntent("yo"))
485+
486+
487+
def test_intent_func():
488+
"""
489+
:func:`intent_func` returns function that returns Effect of tuple of passed arg
490+
and its args.
491+
"""
492+
func = intent_func("myfunc")
493+
assert func(2, 3) == Effect(("myfunc", 2, 3))
494+
assert func("text", 3, None) == Effect(("myfunc", "text", 3, None))

effect/testing.py

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import attr
1414

15-
from ._base import Effect, guard, _Box, NoPerformerFoundError
15+
from ._base import Effect, guard, _Box, NoPerformerFoundError, raise_
1616
from ._sync import NotSynchronousError, sync_perform, sync_performer
1717
from ._intents import Constant, Error, Func, ParallelEffects, base_dispatcher
1818

@@ -30,6 +30,9 @@
3030
'ESConstant', 'ESError', 'ESFunc',
3131
'resolve_stubs',
3232
'resolve_stub',
33+
'const',
34+
'conste',
35+
'intent_func',
3336
]
3437

3538

@@ -465,7 +468,6 @@ def consume(self):
465468

466469
def noop(intent):
467470
"""
468-
469471
Return None. This is just a handy way to make your intent sequences (as
470472
used by :func:`perform_sequence`) more concise when the effects you're
471473
expecting in a test don't return a result (and are instead only performed
@@ -478,3 +480,62 @@ def noop(intent):
478480
479481
"""
480482
return None
483+
484+
485+
def const(value):
486+
"""
487+
Return function that takes an argument but always return given `value`.
488+
Useful when creating sequence used by :func:`perform_sequence`. For example,
489+
490+
>>> dt = datetime(1970, 1, 1)
491+
>>> seq = [(Func(datetime.now), const(dt))]
492+
493+
:param value: This will be returned when called by returned function
494+
:return: ``callable`` that takes an arg and always returns ``value``
495+
"""
496+
return lambda intent: value
497+
498+
499+
def conste(excp):
500+
"""
501+
Like :func:`const` but takes and exception and returns function that raises
502+
the exception
503+
504+
:param excp: Exception that will be raised
505+
:type: :obj:`Exception`
506+
:return: ``callable`` that will raise given exception
507+
"""
508+
return lambda intent: raise_(excp)
509+
510+
511+
def intent_func(fname):
512+
"""
513+
Return function that returns Effect of tuple of fname and its args. Useful
514+
in writing tests that expect intent based on args. For example, if you are
515+
testing following function::
516+
517+
@do
518+
def code_under_test(arg1, arg2, eff_returning_func=eff_returning_func):
519+
r = yield Effect(MyIntent('a'))
520+
r2 = yield eff_returning_func(arg1, arg2)
521+
yield do_return((r, r2))
522+
523+
you will need to know the intents which ``eff_returning_func`` generates
524+
to test this using :func:`perform_sequence`. You can avoid that by doing::
525+
526+
def test_code():
527+
test_eff_func = intent_func("erf")
528+
seq = [
529+
(MyIntent('a'), const('result1')),
530+
(("erf", 'a1', 'a2'), const('result2'))
531+
]
532+
eff = code_under_test('a1', 'a2', eff_returning_func=test_eff_func)
533+
assert perform_sequence(seq, eff) == ('result1', 'result2')
534+
535+
Here, the ``seq`` ensures that ``eff_returning_func`` is called with arguments
536+
``a1`` and ``a2``.
537+
538+
:param str fname: First member of intent tuple returned
539+
:return: ``callable`` with multiple positional arguments
540+
"""
541+
return lambda *a: Effect((fname,) + a)

0 commit comments

Comments
 (0)