["python","pytest"]
Pytest where to store expected data

Testing function I need to pass parameters and see the output matches the expected output. It is easy when function's response is just a small array or a one-line string which can be defined inside the test function, but suppose function I test modifies a config file which can be huge. Or the resulting array is something 4 lines long if I define it explicitly. Where do I store that so my tests remain clean and easy to maintain? Right now if that is string I just put a file near the .py test and do open() it inside the test: def test_if_it_works(): with open('expected_answer_from_some_function.txt') as res_file: expected_data = res_file.read() input_data = ... # Maybe loaded from a file as well assert expected_data == if_it_works(input_data) I see many problems with such approach, like the problem of maintaining this file up to date. It looks bad as well. I can make things probably better moving this to a fixture: @pytest.fixture def expected_data() with open('expected_answer_from_some_function.txt') as res_file: expected_data = res_file.read() return expected_data @pytest.fixture def input_data() return '1,2,3,4' def test_if_it_works(input_data, expected_data): assert expected_data == if_it_works(input_data) That just moves the problem to another place and usually I need to test if function works in case of empty input, input with a single item or multiple items, so I should create one big fixture including all three cases or multiple fixtures. In the end code gets quite messy. If a function expects a complicated dictionary as an input or gives back the dictionary of the same huge size test code becomes ugly: @pytest.fixture def input_data(): # It's just an example return {['one_value': 3, 'one_value': 3, 'one_value': 3, 'anotherky': 3, 'somedata': 'somestring'], ['login': 3, 'ip_address': 32, 'value': 53, 'one_value': 3], ['one_vae': 3, 'password': 13, 'lue': 3]} It's quite hard to read tests with such fixtures and keep them up to date. Update After searching a while I found a library which solved a part of a problem when instead of big config files I had large HTML responses. It's betamax. For easier usage I created a fixture: from betamax import Betamax @pytest.fixture def session(request): session = requests.Session() recorder = Betamax(session) recorder.use_cassette(os.path.join(os.path.dirname(__file__), 'fixtures', request.function.__name__) recorder.start() request.addfinalizer(recorder.stop) return session So now in my tests I just use the session fixture and every request I make is being serialized automatically to the fixtures/test_name.json file so the next time I execute the test instead of doing a real HTTP request library loads it from the filesystem: def test_if_response_is_ok(session): r = session.get("http://google.com") It's quite handy because in order to keep these fixtures up to date I just need to clean the fixtures folder and rerun my tests.
I had a similar problem once, where I have to test configuration file against an expected file. That's how I fixed it: Create a folder with the same name of your test module and at the same location. Put all your expected files inside that folder. test_foo/ expected_config_1.ini expected_config_2.ini test_foo.py Create a fixture responsible for moving the contents of this folder to a temporary file. I did use of tmpdir fixture for this matter. from __future__ import unicode_literals from distutils import dir_util from pytest import fixture import os @fixture def datadir(tmpdir, request): ''' Fixture responsible for searching a folder with the same name of test module and, if available, moving all contents to a temporary directory so tests can use them freely. ''' filename = request.module.__file__ test_dir, _ = os.path.splitext(filename) if os.path.isdir(test_dir): dir_util.copy_tree(test_dir, bytes(tmpdir)) return tmpdir Important: If you are using Python 3, replace dir_util.copy_tree(test_dir, bytes(tmpdir)) with dir_util.copy_tree(test_dir, str(tmpdir)). Use your new fixture. def test_foo(datadir): expected_config_1 = datadir.join('expected_config_1.ini') expected_config_2 = datadir.join('expected_config_2.ini') Remember: datadir is just the same as tmpdir fixture, plus the ability of working with your expected files placed into the a folder with the very name of test module.