Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 484
Mark Tozzi Avatar asked May 12 '12 16:05

Mark Tozzi


People also ask

What is nose tools in Python?

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.

Which command is used to run nose tests?

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.


2 Answers

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)
like image 169
roskakori Avatar answered Oct 19 '22 13:10

roskakori


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.

like image 43
Gary van der Merwe Avatar answered Oct 19 '22 15:10

Gary van der Merwe