3

I'm trying to implement an integration test framework using nose. At the core, I'd like a base class that all test classes inherit. I'd like to have a class setup function that is called as well as the per test setup function. When I use nosetests a_file.py -vs where a_file.py looks like this:

 from nose import tools class BaseClass(object): def __init__(self): print 'Initialize Base Class' def setup(self): print "\nBase Setup" def teardown(self): print "Base Teardown" @tools.nottest def a_test(self): return 'This is a test.' @tools.nottest def another_test(self): return 'This is another test' class TestSomeStuff(BaseClass): def __init__(self): BaseClass.__init__(self) print 'Initialize Inherited Class' def setup(self): BaseClass.setup(self) print "Inherited Setup" def teardown(self): BaseClass.teardown(self) print 'Inherited Teardown' def test1(self): print self.a_test() def test2(self): print self.another_test() 

Outputs this:

Initialize Base Class Initialize Inherited Class Initialize Base Class Initialize Inherited Class cases.nose.class_super.TestSomeStuff.test1 ... Base Setup Inherited Setup This is a test. Base Teardown Inherited Teardown ok cases.nose.class_super.TestSomeStuff.test2 ... Base Setup Inherited Setup This is another test Base Teardown Inherited Teardown ok ---------------------------------------------------------------------- Ran 2 tests in 0.001s OK 

How do I make the __init__, setup, and teardown functions class methods? When I attempt this:

from nose import tools class BaseClass(object): def __init__(self): print 'Initialize Base Class' @classmethod def setup_class(self): print "\nBase Setup" @classmethod def teardown_class(self): print "Base Teardown" @tools.nottest def a_test(self): return 'This is a test.' @tools.nottest def another_test(self): return 'This is another test' class TestSomeStuff(BaseClass): def __init__(self): BaseClass.__init__(self) print 'Initialize Inherited Class' @classmethod def setup_class(self): BaseClass.setup_class(self) print "Inherited Setup" @classmethod def teardown_class(self): BaseClass.teardown_class(self) print 'Inherited Teardown' def test1(self): print self.a_test() def test2(self): print self.another_test() 

I get this:

Initialize Base Class Initialize Inherited Class Initialize Base Class Initialize Inherited Class ERROR ====================================================================== ERROR: test suite for <class 'cases.nose.class_super.TestSomeStuff'> ---------------------------------------------------------------------- Traceback (most recent call last): File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 208, in run self.setUp() File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 291, in setUp self.setupContext(ancestor) File "/usr/lib/python2.7/dist-packages/nose/suite.py", line 314, in setupContext try_run(context, names) File "/usr/lib/python2.7/dist-packages/nose/util.py", line 478, in try_run return func() File "/home/ryan/project/python_testbed/cases/nose/class_super.py", line 30, in setup_class BaseClass.setup_class(self) TypeError: setup_class() takes exactly 1 argument (2 given) ---------------------------------------------------------------------- Ran 0 tests in 0.001s FAILED (errors=1) 

Removing the self from the super class calls (BaseClass.setup_class(self) -> BaseClass.setup_class()) seems to fix it...which I don't understand:

Initialize Base Class Initialize Inherited Class Initialize Base Class Initialize Inherited Class Base Setup Inherited Setup cases.nose.class_super.TestSomeStuff.test1 ... This is a test. ok cases.nose.class_super.TestSomeStuff.test2 ... This is another test ok Base Teardown Inherited Teardown ---------------------------------------------------------------------- Ran 2 tests in 0.001s OK 

However, this doesn't help with the __init__ function. How can I make this a class method? Why does passing in self to the super class fail?

Does anyone have some info on this?

2 Answers 2

2

Class methods take a single implicit argument, (called cls by convention, although you have called it self too), like instance methods take self.

When you call

BaseClass.setup_class(self) 

It's really more like

BaseClass.setup_class(BaseClass, self) 

hence the warning over two arguments. Therefore it's fixed when you ditch self; as a reminder, change the definitions:

@classmethod def setup_class(cls): 

Oh, and __init__ makes no sense as a @classmethod; it's for setting up instances.

Sign up to request clarification or add additional context in comments.

5 Comments

You might find this question useful: stackoverflow.com/questions/1269217/…
I understand that init makes no sense as a class method, but it is the init function for the object...the fact that it is ran 2 times tells me that nose is creating a new object for each test...is this true?
Yes, it appears to be creating two instances of the TestSomeStuff class
I guess I'll go with it...I don't really understand why it creates an object for each test, or why it doesn't just pass self instead of this cls argument. Is there any documentation on this I can read up on? Am I missing something in the nose docs?
For information on classes, instances, class methods, see here. There is more information on what happens internally to nosetest here.
1

Looks like @Jonrsharpe already beat me, but yeah. I'll post it anyway.

This one might explain the setup_class() error. It is passing in an instance of BaseClass as well as 'self' (or TestSomeStuff) when you include the self. Nose must be hard coded to not allow more then 1 parameter in that function (or Unittest, not sure which one has that requirement).

As for the init part, after reading through the Unittest documentation, it appears that the code would be better printed as:

def __init__(self): print 'Initialize Base Class Object' 

And:

def __init__(self): BaseClass.__init__(self) print 'Initialize Inherited Class Object' 

Since it's basically creating an object for every test case and running that init function to make sure the test case is ready.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.