How to pytest parametrize's parameter pass to parametrize fixture

100 views Asked by At

I have a dictionary with program name as a keys and tuple with options as a value, i want to start my test functions with options as parameters, but i can't to do this, maybe there is any hack?

my test functions and how i start them:

import pytest
import argparse


def docstring_setup(dockstring):
    def docstring_decorator(function):
        function.__doc__ = dockstring
        return function
    return docstring_decorator

reruns_count = 1
reruns_delay = 2

USERS = ("regular_user", "administrator")

###         Descriptions

INSTALLATION_DESCRIPTION = "Installing {} with option {}"
REMOVING_DESCRIPTION = "Removing {} with option {} by {}"

###         Variables

parser = argparse.ArgumentParser()
parser.add_argument("--program-versions", type=str, action="store", help="Program name and version to install")
args, _ = parser.parse_known_args()

# programs and its version can be pass through comma like: awesome_program-1.0.1,good_program-1.0
PROGRAM_VERSIONS = args.program_versions.replace(" ", "").split(",")

OPTIONS = dict(awesome_program=(<awesome_program_option0>, <awesome_program_option1>, ... <awesome_program_optionN>),
               good_program=(<good_program_option0>, <good_program_option1>, ... <good_program_optionN>))

PROGRAM_OPTIONS = {program_version: dict(install=(OPTIONS.get(program_version.split("-")[0], ())),
                                         remove=(OPTIONS.get(program_version.split("-")[0], ())))
                                         for program_version in PROGRAM_VERSIONS}


@pytest.fixture(autouse=True)
def setup_teardown():
    yield
    assert is_program_exists() # not neccesary
    return


@pytest.fixture(scope="function")
def check_program_already_installed():
    assert not is_program_exists() # not neccesary
    return


class Installation(object):

    @staticmethod
    def check_installation(self, logger, option, program_version):
        """
        some installation checking stuff
        """
        return
    
    
    @staticmethod
    def check_deinstallation(self, logger, option, program_version, user):
        """
        some deinstallation checking stuff
        """
        return


@pytest.mark.flaky(reruns=reruns_count, reruns_delay=reruns_delay)
@pytest.mark.parametrize("program_version", PROGRAM_OPTIONS.keys())
@pytest.mark.parametrize("option", PROGRAM_OPTIONS[program_version]["install"])  # i need to use "program_version" parameter here
@pytest.mark.usefixtures("check_program_already_installed")
@docstring_setup(INSTALLATION_DESCRIPTION.format(program_version, option))  # i need to use "program_version", "option" parameters here
def test_installation(self, logger, program_version, option):
    self.Installation.check_installation(logger, program_version, option)
    return


@pytest.mark.flaky(reruns=reruns_count, reruns_delay=reruns_delay)
@pytest.mark.parametrize("program_version", PROGRAM_OPTIONS.keys())
@pytest.mark.parametrize("option,user", [(option, user)
                                         for option in OPTIONS[program_version]["remove"]
                                         for user in USERS])  # i need to use "program_version" parameter here
@docstring_setup(REMOVING_DESCRIPTION.format(program_version, option, user))  # i need to use "program_version", "option", "user" parameters here
def test_deinstallation(self, logger, program_version, option, user):
    self.Installation.check_deinstallation(logger, program_version, option, user)
    return

i start it with a command: python3 -m pytest -svv test_installation.py --program-versions=<program-version0>,<program-version1>, ...,<program-version2>

packages i installed:

pytest==5.3.0
pytest-ordering
pytest-reportportal==5.0.3
pytest-rerunfailures
pytest-html

i already tried to start it within loop:

for program_version in PROGRAM_OPTIONS.keys():
    @pytest.mark.flaky(reruns=reruns_count, reruns_delay=reruns_delay)
    @pytest.mark.parametrize("option", PROGRAM_OPTIONS[program_version]["install"])  # i need to use "program_version" parameter here
    @pytest.mark.usefixtures("check_program_already_installed")
    @docstring_setup(INSTALLATION_DESCRIPTION.format(program_version, option))  # i need to use "program_version", "option" parameters here
    def test_installation(self, logger, program_version, option):
        self.Installation.check_installation(logger, program_version, option)
        return


    @pytest.mark.flaky(reruns=reruns_count, reruns_delay=reruns_delay)
    @pytest.mark.parametrize("option,user", [(option, user) for option in OPTIONS[program_version]["remove"] for user in USERS])  # i need to use "program_version" parameter here
    @docstring_setup(REMOVING_DESCRIPTION.format(program_version, option, user))  # i need to use "program_version", "option", "user" parameters here
    def test_deinstallation(self, logger, program_version, option, user):
        self.Installation.check_deinstallation(logger, program_version, option, user)
        return

but it start only one item from dictionary's keys collection and still problem with option and user remain. I need something like this:

# for program_version in PROGRAM_OPTIONS.keys():
#     modes = PROGRAM_OPTIONS[program_version].values()
#     for installation_option in modes["install"]:
#         pass
#     for deinstallation_option in modes["remove"]:
#         for user in USERS:
#             pass
0

There are 0 answers