Home > Software engineering >  How to pass different values to a pytest fixture (which calls a func. having arguments) using parame
How to pass different values to a pytest fixture (which calls a func. having arguments) using parame

Time:10-12

I am pretty new to Pytest and going through the pytest fixtures and parametrization for API tests.

I am trying to create a fixture that creates a POST method request using a predefined function (the arguments creates POST data) and then test out the POST request data by injecting different values to each argument of that function.

Following is a fixture that calls the function:

@pytest.fixture(scope='session')
def create_data_usage_dec():
    dec_resp = utils.data_usage_dec(dec_name="Test Dec", purpose="Test Purpose", ref_genome_ver=37, permit_imputed=False,
                                    require_phased=True, instructions="Test Instructions", use_opt_snps=True, use_req_snps=False,
                                    opt_snp_file="opt_snps.json", req_snp_file="req_snps.json")
    return dec_resp

In the above snippet, the the fixture is used to call a function which uses a couple of arguments whose values are assigned, and then returns the resp object.

Later if I try to use Pytest's mark.parametrize decorator with the fixture to test an argument's max and min limit, e.g.

@pytest.mark.parametrize('ref_genome_ver', [37, 100])
def test_ref_gen(create_data_usage_dec):
    assert create_data_usage_dec.status_code == 200

then the tests are not executed but the following stack trace is generated with Pytest being error out during the collection of tests:

Testing started at 5:20 PM ...
Launching pytest with arguments test_Genetic_Data_Distribution/test_Data_Usage_Declaration/test_GENDATA_128.py::test_ref_gen --no-header --no-summary -q in E:\gendata-tests\api-tests\tests

============================= test session starts =============================
collecting ... 
test_Genetic_Data_Distribution/test_Data_Usage_Declaration/test_GENDATA_128.py:None (test_Genetic_Data_Distribution/test_Data_Usage_Declaration/test_GENDATA_128.py)
In test_ref_gen: function uses no argument 'ref_genome_ver'








collected 0 items / 1 error
ERROR: not found: E:\gendata-tests\api-tests\tests\test_Genetic_Data_Distribution\test_Data_Usage_Declaration\test_GENDATA_128.py::test_ref_gen
(no name 'E:\\gendata-tests\\api-tests\\tests\\test_Genetic_Data_Distribution\\test_Data_Usage_Declaration\\test_GENDATA_128.py::test_ref_gen' in any of [<Module test_Genetic_Data_Distribution/test_Data_Usage_Declaration/test_GENDATA_128.py>])


============================== 1 error in 0.05s ===============================

Process finished with exit code 4

Can someone please suggest a way to resolve this issue?

I found that some people suggested the usage of fixture argument "Indirect=True" for some similar issues posted by other users, however I am confused in how to use that as well plus whether its actually suitable for my scenario or not.

Any help is highly appreciated!

CodePudding user response:

welcome to SO! :)

Your issue is a common use case and hence should be resolved easily.

But first, there is a tiny bug: If you define a parameter via pytest.mark.parameterize, you have to use the name of the parameter in the test function call (see below).

To parameterize the fixture, you need to add a request object to your fixture like so:

@pytest.fixture(scope='session')
def create_data_usage_dec(request):
    parameterized_version = request.param
    dec_resp = utils.data_usage_dec(dec_name="Test Dec", purpose="Test Purpose", ref_genome_ver=parameterized_version, permit_imputed=False,
                                    require_phased=True, instructions="Test Instructions", use_opt_snps=True, use_req_snps=False,
                                    opt_snp_file="opt_snps.json", req_snp_file="req_snps.json")
    return dec_resp

In your test, you can make use of this by using the indirect parameter.

@pytest.mark.parametrize('create_data_usage_dec', 
                         [37, 100], 
                         indirect=['create_data_usage_dec'])
def test_ref_gen(create_data_usage_dec):
    assert create_data_usage_dec.status_code == 200

When running the test, pytest will lookup a fixture named "ref_genome_ver" (as given in the parameterization), because you set indirect=['create_data_usage_dec']. If indiret=False (default), the parameter name ("create_data_usage_dec" in this case) would only be taken as parameter name.

The request object holds the test parameter (37 or 100, respectively) in the param variable. Then the fixture will run, using the given test parameter, and return its result. Assuming that the returned objects has a status_code variable, this will be checked for a 200 in the test.

  • Related