Nose2 has this awesome Such DSL that works similar to RSpec. I used to use unittests directly and decorated the function with something like mock.patch. I am wondering how the should
decorated functions differ from regular unittest functions, and how can I use other decorators as for unittest functions.
I can get it to work like this, but it seems like losing the ability of passing in the unittest instance in the arguments. Any advise will be super appreciated. Thanks!
@it.should('do something')
@mock.patch('my.package.lib.b')
@mock.patch('my.package.lib.a')
def test(a, b):
pass
So we know that decorator order matters and none of these work:
@it.should('do something')
@mock.patch('datetime.date')
@mock.patch('datetime.time')
def test_1(date, time, case):
pass
@mock.patch('datetime.time')
@mock.patch('datetime.date')
@it.should('do something')
def test_2(case, date, time):
pass
because of the way patch
and should
are implemented. Both libraries make some assumptions about what the resulting decorated function will be so it's not possible to directly pass a result of decoration from one to the other.
But we can make a fix for that from the outside using an "adapter" decorator:
import mock
import nose2.tools
def fix_case(f):
def test(case):
f(case=case)
return test
with nose2.tools.such.A('system') as it:
@it.should('do something')
@fix_case
@mock.patch('datetime.time')
@mock.patch('datetime.date')
def test_3(date, time, case=None):
print(date, time, case)
it.createTests(globals())
Now this works and results in:
$ nose2 -v
test 0000: should do something (tests.test_nose2_such.A system) ...
(<MagicMock name='date' id='4334752592'>, <MagicMock name='time' id='4334762000'>,
<tests.test_nose2_such.A system testMethod=test 0000: should do something>)
ok
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
This is rather quick and dirty but get's the job done. I'll see if I can improve upon this and make it nicer.