I want to set a value to a class attribute inside a test method and use the value with same class attribute in another test method. When I tried in normal way by executing test cases with run method, got error as AttributeError: 'Unit' object has no attribute 'b'. Anyway, I found other solutions by using global variable and one more by assigning the class to a variable. May I know the reason why I am not able to retrieve class attribute which I had set the same using another method? Also, could you help me explaining the actual process with run method... Thanks in advance.
Here is a sample code which I tried:
import unittest
class Unit(unittest.TestCase):
def test_i(self):
self.b=20
def test_j(self):
print self.b
suite=unittest.TestLoader().loadTestsFromTestCase(Unit)
unittest.TextTestRunner(verbosity=2).run(suite)
test_i (__main__.Unit) ... ok
test_j (__main__.Unit) ... ERROR
======================================================================
ERROR: test_j (__main__.Unit)
----------------------------------------------------------------------
Traceback (most recent call last):
File "<pyshell#52>", line 5, in test_j
AttributeError: 'Unit' object has no attribute 'b'
----------------------------------------------------------------------
Ran 2 tests in 0.078s
FAILED (errors=1)
<unittest.runner.TextTestResult run=2 errors=1 failures=0>
#The two ways which I solved...
#1.By Assinging class to a variable
import unittest
class Unit(unittest.TestCase):
def test_i(self):
Class=Unit
Class.b=20
def test_j(self):
print self.b
suite=unittest.TestLoader().loadTestsFromTestCase(Unit)
unittest.TextTestRunner(verbosity=2).run(suite)
test_i (__main__.Unit) ... ok
test_j (__main__.Unit) ... 20
ok
----------------------------------------------------------------------
Ran 2 tests in 0.094s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
#2.By using global attribute,but I need the class attribute value to be set and retrieved
import unittest
class Unit(unittest.TestCase):
def test_i(self):
global b,
b=20
def test_j(self):
print b
suite=unittest.TestLoader().loadTestsFromTestCase(Unit)
unittest.TextTestRunner(verbosity=2).run(suite)
test_i (__main__.Unit) ... ok
test_j (__main__.Unit) ... 20
ok
----------------------------------------------------------------------
Ran 2 tests in 0.063s
OK
<unittest.runner.TextTestResult run=2 errors=0 failures=0>
The attribute does not appear in the instance because each test is executed in its own instance, as you can see in this code:
import unittest
class Unit(unittest.TestCase):
def __init__(self, *args, **kwargs):
print('init!')
super(Unit, self).__init__(*args, **kwargs)
def test_i(self):
self.b = 20
def test_j(self):
print(self.b)
suite = unittest.TestLoader().loadTestsFromTestCase(Unit)
unittest.TextTestRunner(verbosity=2).run(suite)
Which prints:
init!
init!
test_i (__main__.Unit) ... ok
test_j (__main__.Unit) ... ERROR
======================================================================
ERROR: test_j (__main__.Unit)
----------------------------------------------------------------------
Traceback (most recent call last):
File "prova.py", line 10, in test_j
print(self.b)
AttributeError: 'Unit' object has no attribute 'b'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
FAILED (errors=1)
Notice the two "init!" at the beginning.
This is done because each test should not depend on the other tests. There is a specific setup method, you should use it to set up the correct environment for your test.
If you want different set-ups then maybe you should consider splitting those tests in separate test cases.
Using a class variable or a global variable obviously works because the class is not deleted, and the globals are not cleared for every test.
On a side note:
The fact that the class is instantiated more times is quite clear in the documentation. As you can see, when they create the TestSuite they add each new test instantiating the class and passing the test name as parameter.
The loadTestsFromTestCase is simply a shortcut for creating a TestSuite in that way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With