Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

self.attr resets between tests in unittest.TestCase

I'd like to use a self.attr of a unittest.TestCase class, however it seems it is not persistent between tests:

import unittest

class TestNightlife(unittest.TestCase):
    _my_param = 0

    def test_a(self):
        print 'test A = %d' % self._my_param
        self._my_param = 1

    def test_b(self):
        print 'test B = %d' % self._my_param
        self._my_param = 2

if __name__ == "__main__":
    unittest.main()

This gives the following output:

test A = 0
test B = 0

Does the instance of unittest.TestCase change between test runs? Why?

like image 771
Jonathan Livni Avatar asked May 13 '12 08:05

Jonathan Livni


People also ask

What is unittest and how does it work?

Unittest supports skipping individual test methods and even whole classes of tests. In addition, it supports marking a test as an “expected failure,” a test that is broken and will fail, but shouldn’t be counted as a failure on a TestResult.

How do you test a test case in unittest?

Note that in order to test something, we use one of the assert*() methods provided by the TestCase base class. If the test fails, an exception will be raised with an explanatory message, and unittest will identify the test case as a failure. Any other exceptions will be treated as errors.

How do I use unittest discover with testloader?

Test discovery is implemented in TestLoader.discover (), but can also be used from the command line. The basic command-line usage is: As a shortcut, python -m unittest is the equivalent of python -m unittest discover. If you want to pass arguments to test discovery the discover sub-command must be used explicitly.

What is the difference between setup and teardown in unittest?

The setUp() and tearDown() methods allow you to define instructions that will be executed before and after each test method. They are covered in more detail in the section Organizing test code. The final block shows a simple way to run the tests. unittest.main() provides a command-line interface to the test script.


1 Answers

It works that way because unittest.main() create separate object for every test (in this case two objects are created).

About your motivation: test should not change global state. You should revert global state to state before test in tearDown or test itself. It's very problematic if tests are changing global state, you will fall in scenarios you can't predict sooner or later.

import unittest

class TestNightlife(unittest.TestCase):
    _my_param = 0

    def test_a(self):
        print 'object id: %d' % id(self)
        print 'test A = %d' % self._my_param
        self._my_param = 1

    def test_b(self):
        print 'object id: %d' % id(self)
        print 'test B = %d' % self._my_param
        self._my_param = 2

if __name__ == "__main__":
    unittest.main()

output:

object id: 10969360
test A = 0
.object id: 10969424
test B = 0
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK
like image 139
Tomasz Wysocki Avatar answered Oct 06 '22 00:10

Tomasz Wysocki