0

I am writing a test, using @pytest.mark.parametrize. The test looks like this:

@pytest.mark.parametrize(
    "device_type,first_command,second_command",
    [
        pytest.param(
            <device_type>,
            <first_command>,
            <second_command>,
            id=str(<first_command>) + "," + str(<second_command>),
        ),
....
    ]
)

Actually <first_command> and <second_command> are commands from a list of commands, defined in an enumeration, and i have to check all possible combinations whether they are executed successfully. Is it possible to create automatically this param list instead of explicitly mentioning every possible combination of 2 commands?

Ivajlo Iliev
  • 303
  • 1
  • 3
  • 19

3 Answers3

1

This can be achived by creating a method for generating the test cases and call it in the @pytest.mark.parametrize decorator.

from typing import List

import pytest


device_types = ['cpu', 'gpu']
first_commands = ['ls', 'pwd']
second_commands = ['ls', 'pwd']


def generate_test_cases() -> List[pytest.param]:
    return [
        pytest.param(device_type, first_command, second_command, id=",".join([device_type, first_command, second_command]))
        for device_type, first_command, second_command
        in zip(device_types, first_commands, second_commands)
    ]


@pytest.mark.parametrize(
    "device_type,first_command,second_command",
    generate_test_cases()
)
def test_device_type(device_type, first_command, second_command):
    pass
Ilya
  • 730
  • 4
  • 16
1

To do that you can create a generator function that creates all the possible combinations and use it as an iterable argument of the parametrize decorator:

import pytest


device_types = ['device1', 'device2']
first_commands = ['first_one', 'first_two']
second_commands = ['first_one', 'first_two']


def generate_test_params():
    for device in device_types:
        for first in first_commands:
            for second in second_commands:
                yield pytest.param(device, first, second, id=",".join([device, first, second]))


@pytest.mark.parametrize(
    "device_type,first_command,second_command",
    generate_test_params()
)
def test_commands(device_type, first_command, second_command):
    pass

The result is:

test.py::test_commands[device1,first_one,first_one] PASSED        [ 12%]
test.py::test_commands[device1,first_one,first_two] PASSED        [ 25%]
test.py::test_commands[device1,first_two,first_one] PASSED        [ 37%]
test.py::test_commands[device1,first_two,first_two] PASSED        [ 50%]
test.py::test_commands[device2,first_one,first_one] PASSED        [ 62%]
test.py::test_commands[device2,first_one,first_two] PASSED        [ 75%]
test.py::test_commands[device2,first_two,first_one] PASSED        [ 87%]
test.py::test_commands[device2,first_two,first_two] PASSED        [100%]
Eugeny Okulik
  • 1,331
  • 1
  • 5
  • 16
0

One of possible solutions is to use several parametrize decorators.

import pytest

devices = ['dev1', 'dev2']
first = ['fcommand1', 'fcommand2']
second = ['scommand1', 'scommand2']
ids = ['id1', 'id2']


@pytest.mark.parametrize("second_command", second)
@pytest.mark.parametrize("first_command", first)
@pytest.mark.parametrize("device_type", devices)
def test_1(device_type, first_command, second_command):
    pass

Output:

test_1[dev1-fcommand1-scommand1] PASSED               [ 12%]
test_1[dev1-fcommand1-scommand2] PASSED               [ 25%]
test_1[dev1-fcommand2-scommand1] PASSED               [ 37%]
test_1[dev1-fcommand2-scommand2] PASSED               [ 50%]
test_1[dev2-fcommand1-scommand1] PASSED               [ 62%]
test_1[dev2-fcommand1-scommand2] PASSED               [ 75%]
test_1[dev2-fcommand2-scommand1] PASSED               [ 87%]
test_1[dev2-fcommand2-scommand2] PASSED               [100%]

An obvious con of this implementation is that you can not specify ids for these parameters sets

pL3b
  • 1,155
  • 1
  • 3
  • 18