Test Fixtures

235 views
Skip to first unread message

mgemmill

unread,
May 24, 2009, 3:23:09 AM5/24/09
to nose-users
I seem to be have some trouble understanding how nose runs test
fixtures at the package and module level. So far I have been able to
set setup and teardown functions at the class level and nose runs them
no problem:

import something

class TestSomething(object):
def setup(self):
#do setup stuff
def teardown(self):
#do teardown stuff
def test_function(self):
assert_true(something)

However, if I move these out of the class and put them at the module
level, the fixtures do not run:

import something

def setup():
#do setup stuff
def teardown():
#do teardown stuff

class TestSomething(object):
def test_function(self):
assert_true(something)

Nor do they run if they are placed in the __init__.py module.

I am sure I am missing something obvious here. Any suggestions would
be greatly appreciated.

Giovanni Marco Dall'Olio

unread,
May 24, 2009, 5:33:33 AM5/24/09
to nose-...@googlegroups.com
On Sun, May 24, 2009 at 9:23 AM, mgemmill <mark.g...@gmail.com> wrote:
>
> I seem to be have some trouble understanding how nose runs test
> fixtures at the package and module level. So far I have been able to
> set setup and teardown functions at the class level and nose runs them
> no problem:

Hi,
I think I have asked the same question some months ago, maybe this
shuold be explained better in the documentation.

For the fixtures at the class level, you can use the @classmethod
decorator and call them 'setupclass/teardownclass':

class TestSomething(object):
@classmethod
def setUpClass(cls):
# methods executed only once when initializing test unit
# e.g. opening a file, importing a module, etc..
def setUp(self):
#methods executed before each test in the test unit
@classmethod
def tearDownClass(cls):
pass
def tearDown(cls):
pass

> I am sure I am missing something obvious here.  Any suggestions would
> be greatly appreciated.
>
>
> >
>



--
Giovanni Dall'Olio, phd student
Department of Biologia Evolutiva at CEXS-UPF (Barcelona, Spain)

My blog on bioinformatics: http://bioinfoblog.it

jason pellerin

unread,
May 24, 2009, 9:26:17 AM5/24/09
to nose-...@googlegroups.com
On Sun, May 24, 2009 at 3:23 AM, mgemmill <mark.g...@gmail.com> wrote:
>
> I seem to be have some trouble understanding how nose runs test
> fixtures at the package and module level. So far I have been able to
> set setup and teardown functions at the class level and nose runs them
> no problem:

Your example looks fine and ought to work. So we're going to need more
details: real code preferably, or the output of nosetests --debug=nose
on the test module that's failing to load fixtures.

JP

mgemmill

unread,
May 25, 2009, 2:55:07 AM5/25/09
to nose-users
I'm starting to think that maybe my package structure is to blame
here, but I'm not 100% sure. Certainly, when I setup a simple test
structure to verify, nose does everything right and runs the setup and
teardown fixtures exactly as would be expected.

My package is setup like:

/aedilis (root folder)
setup.py
__init__.py (+ other setup files, etc...)
/aedilis (namespace)
__init__.py
/ core
__init__.py
db.py
/tests
__init__.py (test fixtures here)
db_test.py

I'm running nose from within /aedilis, but its still not running the
test fixtures. I can run the fixture methods directly and they run
without a hitch. Essentially they are just command line calls to
create a postgres db and user. Nose doesn't run the fixtures and then
the tests throw an error because there is not user or db. Below is
the test code and the output from nosetests -v --debug=nose.

I am wondering if perhaps the problem stems from the fact the root
folder is the same as the namespace? I.e. the folders run like /
aedilis/aedilis/core but I'm just working with aedilis.core. I've
noticed that nose does seem to be confused with the imports statements
and doesn't recognize aedilis.core, despite that fact that its on the
python path. This failure to import doesn't seem to be consistant.


==============================================================
__init__.py

import pexpect


def pg_createdb_cmd():
child = pexpect.spawn('createdb -h localhost -U mark wwat_temp')
child.expect('Password:')
child.sendline('mark')

def pg_dropdb_cmd():
child = pexpect.spawn('dropdb -h localhost -U mark wwat_temp')
child.expect('Password:')
child.sendline('mark')

def pg_createuser_cmd():
child = pexpect.spawn('createuser -h localhost -U mark -s -l -P -E
testuser')
child.expect('Enter password for new role:')
child.sendline('test')
child.expect('Enter it again:')
child.sendline('test')
child.expect('Password:')
child.sendline('mark')

def pg_dropuser_cmd():
child = pexpect.spawn('dropuser -h localhost -U mark testuser')
child.expect('Password:')
child.sendline('mark')

def setup():
print 'executing setup...'
pg_createdb_cmd()
pg_createuser_cmd()


def teardown():
print 'executing teardown...'
pg_dropuser_cmd()
pg_dropdb_cmd()


if __name__ == "__main__":
#setup()
teardown()

==============================================================
db_test.py

from nose.tools import *
import aedilis
import aedilis.core
import aedilis.core.db
from aedilis.core.db import DatabaseSession


class BaseDatabaseSession(object):

def __init__(self):
print 'creating: %s' % self.__class__.__name__
self.db_name = 'wwat_temp'
self.user_name = 'testuser'
self.user_pw = 'test'
self.bad_user_name = 'bad_user'
self.dbtype = 'postgres'
self.dbfile = '%s:%s@localhost:5432/%s'
self.db = None

def get_session(self, user='', pw='', db_name=''):
if user == '': user = self.user_name
if pw == '': pw = self.user_pw
if db_name == '': db_name = self.db_name
try:
dbstring = self.dbfile % (user, pw, db_name)
self.db = DatabaseSession(self.dbtype, dbstring,
echo=False)
self.db.get_session()
except Exception, ex:
raise ex

def teardown(self):
self.db.close()

class TestSessionLogins(BaseDatabaseSession):

def __init__(self):
BaseDatabaseSession.__init__(self)
print 'creating: %s' % self.__class__.__name__

@raises(Exception)
def test_failing_login(self):
print 'test_failing_login....'
db = self.get_session(user=self.bad_user_name,
pw=self.user_pw)
db.close()

def test_session_creation(self):
print 'test_session_creation....'
db = self.get_session()
assert_true(db.session.is_active)
db.close()

class TestUser(BaseDatabaseSession):

def __init__(self):
BaseDatabaseSession.__init__(self)
print 'creating: %s' % self.__class__.__name__
self.get_session()

def test_user_retreival(self):
users = db.query(User).all()
assert_true(len(users) > 0)

def test_role_retreival(self):
pass


==============================================================
output from nosetests -v --debug=nose

... nosetests -v -debug=nose
/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-
packages/SQLAlchemy-0.4.8-py2.6.egg/sqlalchemy/util.py:7:
DeprecationWarning: the sets module is deprecated
import inspect, itertools, new, operator, sets, sys, warnings,
weakref
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/Current/bin/
nosetests", line 8, in <module>
load_entry_point('nose==0.11.0', 'console_scripts', 'nosetests')()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/core.py", line 113,
in __init__
argv=argv, testRunner=testRunner, testLoader=testLoader)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/unittest.py", line 816, in __init__
self.parseArgs(argv)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/core.py", line 164,
in parseArgs
self.createTests()
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/core.py", line 178,
in createTests
self.test = self.testLoader.loadTestsFromNames(self.testNames)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
442, in loadTestsFromNames
return unittest.TestLoader.loadTestsFromNames(self, names, module)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/unittest.py", line 613, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
394, in loadTestsFromName
discovered=discovered)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
316, in loadTestsFromModule
tests.extend(self.loadTestsFromDir(module_path))
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
165, in loadTestsFromDir
entry_path, discovered=True)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
394, in loadTestsFromName
discovered=discovered)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
316, in loadTestsFromModule
tests.extend(self.loadTestsFromDir(module_path))
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
157, in loadTestsFromDir
entry_path, discovered=True)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
394, in loadTestsFromName
discovered=discovered)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
305, in loadTestsFromModule
test_classes + test_funcs)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
304, in <lambda>
tests = map(lambda t: self.makeTest(t, parent=module),
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
511, in makeTest
return self.loadTestsFromTestClass(obj)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
475, in loadTestsFromTestClass
for case in filter(wanted, dir(cls))]
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/loader.py", line
521, in makeTest
return MethodTestCase(obj)
File "/Library/Frameworks/Python.framework/Versions/2.6/lib/
python2.6/site-packages/nose-0.11.0-py2.6.egg/nose/case.py", line 328,
in __init__
self.inst = self.cls()
File "/Users/mark/Documents/DEV/PYTHON/Production/aedilis/tests/
db_test.py", line 57, in __init__
self.get_session()
File "/Users/mark/Documents/DEV/PYTHON/Production/aedilis/tests/
db_test.py", line 29, in get_session
raise ex
sqlalchemy.exceptions.OperationalError: (OperationalError) FATAL:
password authentication failed for user "testuser"
None None



On May 24, 6:26 am, jason pellerin <jpelle...@gmail.com> wrote:

jason pellerin

unread,
May 25, 2009, 10:11:57 AM5/25/09
to nose-...@googlegroups.com
Something doesn't match up between the sample code and the debug
output. Here's what's in the sample code:

> class BaseDatabaseSession(object):
>
>    def __init__(self):
>        print 'creating: %s' % self.__class__.__name__
>        self.db_name = 'wwat_temp'
>        self.user_name = 'testuser'
>        self.user_pw = 'test'
>        self.bad_user_name = 'bad_user'
>        self.dbtype = 'postgres'
>        self.dbfile = '%s:%s@localhost:5432/%s'
>        self.db = None

No call to get_session(). But the test run is crashing in get_session
called from __init__, like this:

>  File "/Users/mark/Documents/DEV/PYTHON/Production/aedilis/tests/
> db_test.py", line 57, in __init__
>    self.get_session()
>  File "/Users/mark/Documents/DEV/PYTHON/Production/aedilis/tests/
> db_test.py", line 29, in get_session
>    raise ex
> sqlalchemy.exceptions.OperationalError: (OperationalError) FATAL:
> password authentication failed for user "testuser"
>  None None

My best guess for what's going on here is that the fixtures are never
getting a chance to run, because the test run is dying at load time,
because there's an attempt to connect to the db using
fixture-dependent state during the __init__ of a test class. That's
not going to work, because test classes are instantiated during
loading time, but fixtures don't execute until test running time. This
is why all setup code has to be in setup(), and __init__ for test
classes can't do any real work.

The fact that this sort of thing crashes the whole test run is
definitely a bug in nose, but even when that's fixed, it's not going
to work until the get_session() call is moved out of __init__. You'll
just get less confusing errors. ;)

JP

mgemmill

unread,
May 26, 2009, 5:30:03 PM5/26/09
to nose-users
Oiy! I knew it was going to be something simple like that. Indeed, put
the code in the class setup and all is well. Thanks for the clarity
Jason. mg
Reply all
Reply to author
Forward
0 new messages