Reputation: 39
I am creating tests inpytest
for a custom sub-class of a pandas DataFrame
. I would like to test that my class constructor is working for both a list and a pandas DataFrame
. How can I parameterize my test so test_constructor
can accept both samp_list
and samp_df
rather than having duplicate test_constructor_with_df
and test_constructor_with_list
test functions?
@pytest.fixture(scope='module')
def sample():
samp_list = [{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'c', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 90},
{'timestamp': '2020-01-01', 'group': 'd', 'dollar_gains': 100}]
samp_df = pd.DataFrame(samp_list)
return samp_list, samp_df
def test_constructor(sample):
print('hi')
hist_dg = HistDollarGains(sample, 'group', 'timestamp')
assert hist_dg.group == 'group'
assert hist_dg.timestamp_col == 'timestamp'
Upvotes: 3
Views: 3638
Reputation: 86
This is probably too late to help you, but I ran into a similar question today. Seems like there's an option to pass parameters to the fixture, and that it will run for each value passed.
Martin Winkel did a good article on it here: https://levelup.gitconnected.com/advanced-pytest-techniques-i-learned-while-contributing-to-pandas-7ba1465b65eb
For your case, I think you'd do something like:
import pandas as pd
import pytest
opt_dict = {'samp_list': [{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'c', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 90},
{'timestamp': '2020-01-01', 'group': 'd', 'dollar_gains': 100}],
'samp_df':pd.DataFrame([{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 100},
{'timestamp': '2020-01-01', 'group': 'c', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'a', 'dollar_gains': 110},
{'timestamp': '2020-01-01', 'group': 'b', 'dollar_gains': 90},
{'timestamp': '2020-01-01', 'group': 'd', 'dollar_gains': 100}]),
'samp_bad_input':'this should result in a failed test'}
@pytest.fixture(params=opt_dict.keys())
def df_opt(request):
'''
I haven't looked into why request works without a definition; it is some kind of pytest built-in for use with fixtures
'''
return opt_dict[request.param]
def test_sample(df_opt):
if isinstance(df_opt,list):
sample_df = pd.DataFrame(df_opt)
else:
sample_df = df_opt
assert isinstance(sample_df,pd.DataFrame), "somehow, we didn't end up with a dataframe"
Upvotes: 3