Use only some parameterization parameters in different tests in pytest

I have a binding called n_groups that I would like to parameterize in some cases, but not in others. The reason for this is that the structure of my data model, like MVC, I test as much as possible in the "model" classes, but the classes of the "controller" do not need such extensive testing, because I already did this in the "model". Therefore, running tests with all parameters is redundant in the controller, and I would like to limit the number of tests and, therefore, the testing time. Currently, over 18,000 tests are being performed to test the initialization of my controller, and it takes 42 minutes to complete! See the output of Travis-CI .

Currently I need to do a workaround,

 # Contents of conftest.py import pytest import pandas as pd import numpy as np @pytest.fixture(scope='module', params=[2, 3], ids=['2_groups', '3_groups']) def n_groups(request): """Number of phenotype groups. For testing that functions work when there only 2 groups """ return request.param @pytest.fixture(scope='module') def n_groups_fixed(): """Fixed number of phenotype groups (3)""" return 3 

Then I pass either n_groups or n_groups_fixed to the next chain of devices that create data for testing. The elements outliers , pooled , samples , n_samples and metadata_phenotype_col also parameterized, but are not included in the scope of this question.

 # Contents of conftest.py @pytest.fixture(scope='module') def groups(n_groups): """Phenotype group names""" return ['group{}'.format(i + 1) for i in np.arange(n_groups)] @pytest.fixture(scope='module') def groups_fixed(n_groups_fixed): """Phenotype group names""" return ['group{}'.format(i + 1) for i in np.arange(n_groups_fixed)] @pytest.fixture(scope='module') def groupby(groups, samples): return dict((sample, np.random.choice(groups)) for sample in samples) @pytest.fixture(scope='module') def groupby_fixed(groups_fixed, samples): return dict((sample, np.random.choice(groups_fixed)) for sample in samples) @pytest.fixture(scope='module') def metadata_data(groupby, outliers, pooled, samples, n_samples, metadata_phenotype_col): df = pd.DataFrame(index=samples) if outliers is not None: df['outlier'] = df.index.isin(outliers) if pooled is not None: df['pooled'] = df.index.isin(pooled) df[metadata_phenotype_col] = groupby df['subset1'] = np.random.choice([True, False], size=n_samples) return df @pytest.fixture(scope='module') def metadata_data_groups_fixed(groupby_fixed, outliers, pooled, samples, n_samples, metadata_phenotype_col): df = pd.DataFrame(index=samples) if outliers is not None: df['outlier'] = df.index.isin(outliers) if pooled is not None: df['pooled'] = df.index.isin(pooled) df[metadata_phenotype_col] = groupby_fixed df['subset1'] = np.random.choice([True, False], size=n_samples) return df 

It seems rather cumbersome to have a *_fixed version for each of these fixtures.

The test examples are an extensive test in the data model that checks both the n_groups parameterization and a less extensive test in the controller that checks only one β€œparameterization” using groups_fixed (these are not real tests, just demo examples):

 # Contents of test_model.py class TestModel(object): def test__init(metadata_data, ...): ... def test_plot(metadata_data_fixed, ...); ... # Contents of test_controller.py class TestController(object): def test__init(metadata_data_fixed, ...): ... 

Is there any other way to do this? I read pytest parameterize documentation, but it only seems to set parameterization globally, and not based on each test.

I would like to do something like:

 # Contents of test_model.py class TestModel(object): def test__init(metadata_data, ...): ... @pytest.mark.parameterize(n_groups=3) def test_plot(metadata_data, ...); ... # Contents of test_controller.py class TestController(object): @pytest.mark.parameterize(n_groups=3) def test__init(metadata_data_fixed, ...): ... 

UPDATE: adding the n_groups element inside TestController does not help, i.e. this does not work:

 # Contents of test_controller.py class TestController(object): @pytest.fixture def n_groups(): return 3 def test__init(metadata_data_fixed, ...): ... 

I am not sure why, because it seems that this device should overwrite the global n_groups defined in conftest.py

+6
source share
1 answer

I'm not sure that you can do this with the built-in parametrize , I think you will have to implement your own parameterization scheme based on some information about the tested method (for example, if the class contains a Controller in its name, you will parameterize it differently) using pytest_generate_tests hook . Some examples can be found here .

0
source

Source: https://habr.com/ru/post/980414/


All Articles