I think what I'm trying to do is fairly simple. I want to initialize a couple of variables in a test setup function, and then use them in the test functions that are decorated with that setup. The following trivial example illustrates what I mean:
from nose.tools import *
def setup():
foo = 10
def teardown():
foo = None
@with_setup(setup, teardown)
def test_foo_value():
assert_equal(foo, 10)
This results in:
$ nosetests tests/test_foo.py
E
======================================================================
ERROR: test_foo.test_foo_value
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mtozzi/.virtualenvs/foo/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
self.test(*self.arg)
File "/home/mtozzi/code/foo/tests/test_foo.py", line 12, in test_foo_value
assert_equal(foo, 10)
NameError: global name 'foo' is not defined
----------------------------------------------------------------------
Ran 1 test in 0.006s
FAILED (errors=1)
With the old unittest style, I could set these as instance variables on the test class, but I thought nosetests didn't require you to use classes. I've also considered setting them as package global variables, but that doesn't seem like a terribly good practice. I hope there's something obvious I'm missing for doing this.
The nose. tools module provides a number of testing aids that you may find useful, including decorators for restricting test execution time and testing for exceptions, and all of the same assertX methods found in unittest.
nose can be integrated with DocTest by using with-doctest option in athe bove command line. The result will be true if the test run is successful, or false if it fails or raises an uncaught exception. nose supports fixtures (setup and teardown methods) at the package, module, class, and test level.
As the comments to your question already suggested, simply switch to classes and use instance variables like self.foo
. That's the way it should be done.
If you insist on not using classes, try global
variables. You didn't hear this from me, though.
from nose.tools import *
foo = None
def setup():
global foo # Ugly.
foo = 10
def teardown():
global foo # Ugly.
foo = None
@with_setup(setup, teardown)
def test_foo_value():
assert_equal(foo, 10)
A third variant might be to use a dictionary for your values. This is slightly less ugly but horribly clumsy:
from nose.tools import *
_globals = {'foo': None}
def setup():
_globals['foo'] = 10
def teardown():
_globals['foo'] = None
@with_setup(setup, teardown)
def test_foo_value():
foo = _globals['foo']
assert_equal(foo, 10)
I use a custom with_setup decorator that uses the poor man's nonlocal: https://gist.github.com/garyvdm/392ae20c673c7ee58d76
def setup():
foo = 10
return [foo], {}
def teardown(foo):
pass
@with_setup_args(setup, teardown)
def test_foo_value(foo):
nose.tools.assert_equal(foo, 10)
For projects that are Python 3 only, I use nonlocal rather than .extend/.update for arguments, kwargs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With