Sevenless
Sevenless

Reputation: 2835

Parameterize pytest using fixture loaded from database

I'm trying to use pytest to take in an id for a suite to run, load the suite from a db, and then generate the test cases in a parameterized fashion. The code below shows the gist of what I want to do, but errors with fixture 'case' not found.

How can I parameterize case with the ids that get returned from the db lookup?

import os
from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_harness.settings")
application = get_wsgi_application()

from unitrunner.models import TestSuiteModel as SuiteModel


def pytest_addoption(parser):
    parser.addoption("--suite", action="append", default=[],
        help="Suite ID to evaluate")


def pytest_generate_tests(metafunc):
    if 'suite' in metafunc.fixturenames:
        suite_id = metafunc.fixturenames['suite']

        this_suite = SuiteModel.objects.get(id=suite_id)
        test_cases = this_suite.testCases.all()

        metafunc.parametrize(
            "case",
            [item.id for item in test_cases]
        )


def test_case(case):
    print(case)

    assert False

Upvotes: 0

Views: 913

Answers (1)

hoefling
hoefling

Reputation: 66171

fixture 'case' not found means that the parametrization did not happen: the line

metafunc.parametrize(
    "case",
    [item.id for item in test_cases]
)

was not executed. This is no suprise because you don't use the fixture suite in the test_case, thus if 'suite' in metafunc.fixturenames will return False. If you actually use the fixture in test_case, for example:

@pytest.fixture
def suite():
    pass

@pytest.mark.usefixtures('suite')
def test_case(case):
    print(case)

    assert False

the test will be correctly parametrized. Btw, the suite fixture in my example is working as a marker and should be better reworked to one:

def pytest_generate_tests(metafunc):
    try:
        suite_id = getattr(metafunc.function, 'suite')
    except AttributeError:  # no suite marker
        pass
    else:
        this_suite = SuiteModel.objects.get(id=suite_id)
        test_cases = this_suite.testCases.all()

        metafunc.parametrize(
            "case",
            [item.id for item in test_cases]
        )

Now simply mark the relevant tests:

@pytest.mark.suite(1)
def test_case(case):
    assert case == 1

Upvotes: 1

Related Questions