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. |
Factory or decorator (depending if func is initially given).
Parameters: |
|
---|---|
Returns: | A wrapper that records all calls made to func. The history is available as a call property. 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.
Factory for a decorator that makes the function return a given return_value.
Parameters: |
|
---|---|
Returns: | A decorator. |
This a simple yet flexible tool that can do “capture-replay mocking” or “test doubles” [1]. It leverages aspectlib‘s powerful weaver.
Parameters: |
|
---|
The Story allows some testing patterns that are hard to do with other tools:
The Story works 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 replay always starts from a story instance.
Changed in version 0.9.0: Added in.
[1] | (1, 2) http://www.martinfowler.com/bliki/TestDouble.html |
Parameters: |
|
---|---|
Returns: | obj:aspectlib.test.Replay object. |
Return type: | A |
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
Object implementing the replay transaction.
This object should be created by Story‘s replay method.
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=False mode and want to do custom assertions.
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!