Parametrized fixtures in pytest
While most of my pytest fixtures don't react to the dynamically-passed values of function parameters, there have been situations where I've definitely felt the need for that. Consider this example:
Here, in the create_file fixture, I've created a file named foo.md in the tmp folder. Notice that the name of the file foo.md is hardcoded inside the body of the fixture function. The fixture yields the path of the directory and the created file.
Later on, the test_file_creation function just checks whether the fixture is working as expected. This snippet will pass successfully if you execute it with the pytest command.
Now, if you needed to create three files - foo.md, bar.md, baz.md - how'd you do that in the fixture? You could hardcode the names of the three files in the fixture as follows:
I had to change the name of the fixture from create_file to create_files because the output signature of the fixture was changed to yield the directory path and a list of the paths of the three newly created files.
While this works, it's cumbersome and inflexible. What if one of your tests needs one file and another one demands two files to be created? How'd you tackle that?
It'd be much better if we could just pass the filename to the fixture as a parameter and the fixture would then create the corresponding file in the temporary folder. Also, if we need n files to be created, then we'll just have to execute the fixture n times. There's a way to do so by leveraging fixture parameters and @pytest.mark.parameterize decorator. This is how you can do it:
In this case, the fixture create_file takes an additional parameter called filename and then yields the directory path and the file path; just as the first snippet. Later on, in the test_file_creation function, the desired values of the filename parameter is injected into the fixture via the @pytest.mark.parametrize decorator. In the above snippet, pytest runs the fixture 3 times and creates the desired files in 3 passes - just like how a normal function call would behave.
Further reading
Discussion in the ATmosphere