Reference: aspectlib.test¶
This module aims to be a lightweight and flexible alternative to the popular mock framework and more.
aspectlib.test.record
Factory or decorator (depending if func is initially given).
aspectlib.test.mock
Factory for a decorator that makes the function return a given return_value.
aspectlib.test.Story
This a simple yet flexible tool that can do "capture-replay mocking" or "test doubles" [1].
aspectlib.test.Replay
Object implementing the replay transaction.
-
aspectlib.test.record(func=None, recurse_lock_factory=<function allocate_lock>, **options)[source] ¶ Factory or decorator (depending if func is initially given).
Parameters: - callback (list) – An a callable that is to be called with
instance, function, args, kwargs. - calls (list) – An object where the Call objects are appended. If not given and
callbackis not specified then a new list object will be created. - iscalled (bool) – If
Truethe func will be called. (default:False) - extended (bool) – If
Truethe func’s__name__will also be included in the call list. (default:False) - results (bool) – If
Truethe results (and exceptions) will also be included in the call list. (default:False)
Returns: A wrapper that records all calls made to func. The history is available as a
callproperty. If access to the function is too hard then you need to specify the history manually.Example
>>> @record ... def a(x, y, a, b): ... pass >>> a(1, 2, 3, b='c') >>> a.calls [Call(self=None, args=(1, 2, 3), kwargs={'b': 'c'})]
Or, with your own history list:
>>> calls = [] >>> @record(calls=calls) ... def a(x, y, a, b): ... pass >>> a(1, 2, 3, b='c') >>> a.calls [Call(self=None, args=(1, 2, 3), kwargs={'b': 'c'})] >>> calls is a.calls True
Changed in version 0.9.0: Renamed history option to calls. Renamed call option to iscalled. Added callback option. Added extended option.
- callback (list) – An a callable that is to be called with
-
aspectlib.test.mock(return_value, call=False)[source] ¶ Factory for a decorator that makes the function return a given return_value.
Parameters: - return_value – Value to return from the wrapper.
- call (bool) – If
True, call the decorated function. (default:False)
Returns: A decorator.
-
class
aspectlib.test.Story(*args, **kwargs)[source] ¶ This a simple yet flexible tool that can do "capture-replay mocking" or "test doubles" [1]. It leverages
aspectlib’s powerfulweaver.Parameters: - target (same as for
aspectlib.weave) – Targets to weave in the story/replay transactions. - subclasses (bool) – If
True, subclasses of target are weaved. Only available for classes - aliases (bool) – If
True, aliases of target are replaced. - lazy (bool) – If
Trueonly target’s__init__method is patched, the rest of the methods are patched after__init__is called. Only available for classes. - methods (list or regex or string) – Methods from target to patch. Only available for classes
The
Storyallows some testing patterns that are hard to do with other tools:- Proxied mocks: partially mock objects and modules so they are called normally if the request is unknown.
- Stubs: completely mock objects and modules. Raise errors if the request is unknown.
The
Storyworks in two of transactions:The story: You describe what calls you want to mocked. Initially you don’t need to write this. Example:
>>> import mymod >>> with Story(mymod) as story: ... mymod.func('some arg') == 'some result' ... mymod.func('bad arg') ** ValueError("can't use this")
The replay: You run the code uses the interfaces mocked in the story. The
replayalways starts from a story instance.
Changed in version 0.9.0: Added in.
-
replay(**options)[source] ¶ Parameters: - proxy (bool) – If
Truethen unexpected uses are allowed (will use the real functions) but they are collected for later use. Default:True. - strict (bool) – If
Truethen anAssertionErroris raised when there were unexpected calls or there were missing calls (specified in the story but not called). Default:True. - dump (bool) – If
Truethen the unexpected/missing calls will be printed (tosys.stdout). Default:True.
Returns: A
aspectlib.test.Replayobject.Example
>>> import mymod >>> with Story(mymod) as story: ... mymod.func('some arg') == 'some result' ... mymod.func('other arg') == 'other result' >>> with story.replay(strict=False): ... print(mymod.func('some arg')) ... mymod.func('bogus arg') some result Got bogus arg in the real code! STORY/REPLAY DIFF: --- expected... +++ actual... @@ -1,2 +1,2 @@ mymod.func('some arg') == 'some result' # returns -mymod.func('other arg') == 'other result' # returns +mymod.func('bogus arg') == None # returns ACTUAL: mymod.func('some arg') == 'some result' # returns mymod.func('bogus arg') == None # returns
- proxy (bool) – If
- target (same as for
-
class
aspectlib.test.Replay(?)[source] ¶ Object implementing the replay transaction.
This object should be created by
Story’sreplaymethod.-
diff¶ Returns a pretty text representation of the unexpected and missing calls.
Most of the time you don’t need to directly use this. This is useful when you run the replay in
strict=Falsemode and want to do custom assertions.
-
missing¶ Returns a pretty text representation of just the missing calls.
-
unexpected¶ Returns a pretty text representation of just the unexpected calls.
The output should be usable directly in the story (just copy-paste it). Example:
>>> import mymod >>> with Story(mymod) as story: ... pass >>> with story.replay(strict=False, dump=False) as replay: ... mymod.func('some arg') ... try: ... mymod.badfunc() ... except ValueError as exc: ... print(exc) Got some arg in the real code! boom! >>> print(replay.unexpected) mymod.func('some arg') == None # returns mymod.badfunc() ** ValueError('boom!',) # raises
We can just take the output and paste in the story:
>>> import mymod >>> with Story(mymod) as story: ... mymod.func('some arg') == None # returns ... mymod.badfunc() ** ValueError('boom!') # raises >>> with story.replay(): ... mymod.func('some arg') ... try: ... mymod.badfunc() ... except ValueError as exc: ... print(exc) boom!
-