pytest two level of parametrization when one parameter is generated by the other one
Asked Answered
Y

1

7

I have a scenario where I have a parameter list. Each of this parameter can generate another parameter list and I want to paramererize my test based on both parameter.

Something similar to what I is being done with for loop below but using parameterization. Also test_1 and test_2 should be executed together for any set of parameters

Any help??

param1 = [<some_list>]
#param2 = [<some_list_Generated_based_on_Param1>]

for arg1 in param1:
    param2 = get_param2(arg1)
    for arg2 in param2
        def test_1():
            ...
            pass
        def test_2():
            ...
            pass
Yeargain answered 24/6, 2016 at 17:57 Comment(0)
N
2

I doubt if there is a direct way to achieve that. But by extend pytest plugin pytest_generate_tests, we may do it.

This is my answer about another parametrize question. using fixture return value as value in mark.parametrize()

Here is my solution.

  1. Mark the tests you want to do two level parametrization.
  2. Get the tests you want to do two level parametrization, and get the first level parametrization.
  3. Based on first level parametrization, generate the second level.
  4. Assigned the test case use only second level parametrization or use both according to your requirement.

Example test:

import pytest

@pytest.mark.two_level_parametrization
@pytest.mark.parametrize("first_level", [1, 2, 3])
def test_two_level_parametrization(second_level):
    print(second_level)

Conftest.py:

import pytest

def pytest_generate_tests(metafunc):
    if hasattr(metafunc.function, 'two_level_parametrization'):
        # You may need more marker or add if statement based on the arg of parametrize if you want to implement multiple two-level paremetrize
        first_parametrize = metafunc.function.parametrize
        metafunc.function.parametrize = [calculate_second_parametrize(first_parametrize)]

        # # If you want to keep first level parametrization:
        # metafunc.function.parametrize = [first_parametrize, calculate_second_parametrize(first_parametrize)]

def calculate_second_parametrize(first_parametrize):
    # Define your own method here to generate the parametrize object you need.

    input_params = first_parametrize.args[1]
    output_params = input_params + [-1 * num for num in input_params]
    return pytest.mark.parametrize('second_level', output_params)

Output:

test_01.py::test_two_level_parametrization[1] 1
PASSED
test_01.py::test_two_level_parametrization[2] 2
PASSED
test_01.py::test_two_level_parametrization[3] 3
PASSED
test_01.py::test_two_level_parametrization[-1] -1
PASSED
test_01.py::test_two_level_parametrization[-2] -2
PASSED
test_01.py::test_two_level_parametrization[-3] -3
PASSED
Neurocoele answered 25/6, 2016 at 18:36 Comment(1)
I get "In test_two_level_parametrization: function uses no argument 'first_level'"Carrasco

© 2022 - 2024 — McMap. All rights reserved.