I am writing a unit test and trying to set up the test data to use for the test cases in the same python script.
However, When I run the script, it does create the test data, but prints an error message that the data do not exist, leading to the test failure. It's only when I run the script again that the test succeeds.
Below is a simplified script that I wrote to figure out what's going on.
import unittest
from ddt import ddt, file_data
import pandas
@ddt
class TestWhatever(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.setup_test_data()
print("setUpClass is running")
@classmethod
def tearDownClass(cls):
print("tearDownClass is running")
@classmethod
def setup_test_data(cls):
data = pandas.DataFrame({'msg':["testing"]})
data = data.transpose()
with open("practice_test.json", "w") as file:
file.write(data.to_json())
print("setup_test_data is running")
@file_data("practice_test.json")
def test_whatever_possible(self, msg):
print("test_whatever_possible is running :", msg)
self.assertEqual('q', 'q')
def test_whatever_impossible(self):
print("test_whatever_impossible is running")
self.assertEqual('n', 'n')
When I run the script above, it prints :
setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.EtearDownClass is running
======================================================================
ERROR: test_whatever_possible_00001_error (main.TestWhatever)
Error!
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\ddt.py", line 145, in wrapper
return func(self, *args, **kwargs)
File "C:\ddt.py", line 187, in func
raise ValueError(message % file_attr)
ValueError: practice_test.json does not exist
----------------------------------------------------------------------
Ran 2 tests in 0.006s
FAILED (errors=1)
Then on the second run :
setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.test_whatever_possible is running : testing
.tearDownClass is running
----------------------------------------------------------------------
Ran 2 tests in 0.005s
OK
I'm pretty much lost at this point... Does anyone have a clue on this?
As a workaround you could write your own decorator to create the data file e.g.
def create_data(name):
def decorator(fn):
def decorated(*args, **kwargs):
data = pandas.DataFrame({"msg": ["testing"]})
data = data.transpose()
with open(name, "w") as file:
file.write(data.to_json())
res = fn(*args, **kwargs)
os.unlink(name)
return res
return decorated
return decorator
and then stack this for your test (and remove the setup_test_data
step):
@ddt
class TestWhatever(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("setUpClass is running")
@classmethod
def tearDownClass(cls):
print("tearDownClass is running")
@create_data("practice_test.json")
@file_data("practice_test.json")
def test_whatever_possible(self):
print("test_whatever_possible is running :")
self.assertEqual("q", "q")
The following example preserves the ddt behaviour of passing the parameter value into the test function:
import json
import unittest
from ddt import ddt, FILE_ATTR
def create_file_data(value, data):
def wrapper(func):
with open(value, "w") as file:
file.write(json.dumps(data))
# this is what the file_data decorator does
setattr(func, FILE_ATTR, value)
return func
return wrapper
@ddt
class TestWhatever(unittest.TestCase):
@create_file_data("practice_test.json", {"msg": ["testing"]})
def test_file_data(self, msg):
print("test_file_data msg:", msg)
unittest.main()
When this is run the output is:
test_file_data msg: ['testing']
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
Using the two examples above you should be able to derive an appropriate solution for your problem.