Search code examples
pythonnose

How can I access variables set in the Python nosetests setup function


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.


Solution

  • 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)