Reputation: 9912
I am writing a pytest test for a library similar to this
from mylibrary use do_some_calculation
def test_df_against_angle():
df=load_some_df()
angle=30
result=do_some_calculation(df,angle)
assertTrue(result)
Now as you can see that test only works for a particular dataframe and for an angle(30)
I have to do this tests for several dataframes and several angles To complicate matters,the angles I should use are different for each dataset
So I have to test that
So I am guessing that I have to use pytest's parameters for that. I know how to put simple values as parameters, (So for example I know how to put parameters so as to use those three csv files and even how to put these in a json file and read it to enter the test) but I am at lost as how to put several types of parameters and that these parameters depend on the other
Ideally also I would like to put this in the conftest.py
Can someone give me some pointers on how to do this?
Upvotes: 0
Views: 82
Reputation: 40723
We can write a function to generate all the test cases:
import pytest
def load_df(filename):
# TODO: Implement this
return f"df_{filename}"
def do_some_calculation(df, angle):
# TODO: Implement this
return True
def generate_test_data():
test_combinations = [
("data_set1.csv", [0, 30, 60]),
("data_set2.csv", [90, 120, 150]),
("data_set3.csv", [180, 210, 240]),
]
for filename, angles in test_combinations:
df = load_df(filename)
for angle in angles:
yield df, angle
@pytest.mark.parametrize("df,angle", generate_test_data())
def test_df_against_angle(df, angle):
result = do_some_calculation(df, angle)
assert result
test_combinations.py::test_df_against_angle[df_data_set1.csv-0] PASSED
test_combinations.py::test_df_against_angle[df_data_set1.csv-30] PASSED
test_combinations.py::test_df_against_angle[df_data_set1.csv-60] PASSED
test_combinations.py::test_df_against_angle[df_data_set2.csv-90] PASSED
test_combinations.py::test_df_against_angle[df_data_set2.csv-120] PASSED
test_combinations.py::test_df_against_angle[df_data_set2.csv-150] PASSED
test_combinations.py::test_df_against_angle[df_data_set3.csv-180] PASSED
test_combinations.py::test_df_against_angle[df_data_set3.csv-210] PASSED
test_combinations.py::test_df_against_angle[df_data_set3.csv-240] PASSED
generate_test_data
function only load the df once and it is shared among the angles. Take care not to alter the df
between tests.df
within the generate_test_data
function, freeing the test from doing the setup part.If you want to control the names of the tests, use pytest.param
. Replace yield df, angle
with
yield pytest.param(df, angle, id=f"df={filename}, angle={angle:>3}")
and you get the following output (note the names of the tests):
test_combinations.py::test_df_against_angle[df=data_set1.csv, angle= 0] PASSED
test_combinations.py::test_df_against_angle[df=data_set1.csv, angle= 30] PASSED
test_combinations.py::test_df_against_angle[df=data_set1.csv, angle= 60] PASSED
test_combinations.py::test_df_against_angle[df=data_set2.csv, angle= 90] PASSED
test_combinations.py::test_df_against_angle[df=data_set2.csv, angle=120] PASSED
test_combinations.py::test_df_against_angle[df=data_set2.csv, angle=150] PASSED
test_combinations.py::test_df_against_angle[df=data_set3.csv, angle=180] PASSED
test_combinations.py::test_df_against_angle[df=data_set3.csv, angle=210] PASSED
test_combinations.py::test_df_against_angle[df=data_set3.csv, angle=240] PASSED
Upvotes: 0
Reputation: 311586
You can use the pytest.mark.parametrize
decorator to parametrize multiple parameters. For example, if your test function takes as input a filename (the path to a CSV file) and a list of angles, you could write something like:
@pytest.mark.parametrize("filename,angles", (
("data_set1.csv", (0, 30, 60)),
("data_set2.csv", (90, 120, 150)),
("data_set3.csv", (180, 210, 240)),
))
def test_df_against_angle(filename, angles):
df = load_some_df(filename)
...
Given the new information you've left in your comments, you could write your test like this to get the desired nine parametrized tests:
import pytest
from itertools import product
@pytest.mark.parametrize(
"filename,angle",
(
*product(("data_set1.csv",), (0, 30, 60)),
*product(("data_set2.csv",), (90, 120, 150)),
*product(("data_set3.csv",), (180, 210, 240)),
),
)
def test_angles(filename, angle):
assert True
This will run the following tests:
$ pytest -v
========================================== test session starts ==========================================
platform linux -- Python 3.11.1, pytest-7.2.0, pluggy-1.0.0 -- /home/lars/.local/share/virtualenvs/python-LD_ZK5QN/bin/python
cachedir: .pytest_cache
rootdir: /home/lars/tmp/python
collected 9 items
test_angles.py::test_angles[data_set1.csv-0] PASSED [ 11%]
test_angles.py::test_angles[data_set1.csv-30] PASSED [ 22%]
test_angles.py::test_angles[data_set1.csv-60] PASSED [ 33%]
test_angles.py::test_angles[data_set2.csv-90] PASSED [ 44%]
test_angles.py::test_angles[data_set2.csv-120] PASSED [ 55%]
test_angles.py::test_angles[data_set2.csv-150] PASSED [ 66%]
test_angles.py::test_angles[data_set3.csv-180] PASSED [ 77%]
test_angles.py::test_angles[data_set3.csv-210] PASSED [ 88%]
test_angles.py::test_angles[data_set3.csv-240] PASSED [100%]
=========================================== 9 passed in 0.01s ===========================================
Upvotes: 1