Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically register a fixture in a pytest plugin

I am looking for a way run some pytest unit tests from Python and register a pytest fixture dynamically. As explained in in the Pytest documentation, when running tests programmatically their behaviour can be altered with a custom plugin. I have the following setup

validation.py (contains the tests to run)

def test_valid(new_fixture):
    assert new_fixture > 0

which is launched with,

import pytest

new_fixture_value = 36

class FixtureRegPlugin(object):
    def pytest_sessionstart(self):
        print('Test session start')

        @pytest.fixture
        def new_fixture():
            return new_fixture_value

pytest.main(['-sv', './validation.py'], plugins=[FixtureRegPlugin()])

here we run tests in validation.py with a custom plugin that registers a hook for pytest_sessionstart. This hook is executed at the beginning of the test session, and I can see the printed output as expected. However, the new_fixture is not registered, and so the test fails with a "fixture not found" error.

The goal is to modify the result of the fixture at runtime and so I cannot just place its definition inside validation.py.

like image 842
rth Avatar asked Sep 11 '26 12:09

rth


1 Answers

Is there any reason you don't want to use @pytest.fixture(scope='session') in a conftest.py file rather than writing your own plugin? Could that achieve the functionality of altering the fixture at runtime that you're looking for?

In any case, if you change your indentation and add self to new_fixture's arguments it should work.

        @pytest.fixture
        def new_fixture():
            return new_fixture_value

to

    @pytest.fixture(scope='session')
    def new_fixture(self):
        return new_fixture_value

You can view setup and teardown with --setup-show on the command line.

Contents of "script.py":

import pytest


class FixtureRegPlugin(object):

    @pytest.fixture(scope='session')
    def session_fixture(self):
        pass

    @pytest.fixture(scope='module')
    def module_fixture(self):
        pass

    @pytest.fixture(scope='function')
    def function_fixture(self):
        pass


pytest.main(['--setup-show', './validation.py'], plugins=[FixtureRegPlugin()])

Contents of validation.py:

def test_A(session_fixture, module_fixture, function_fixture):
    pass

def test_B(session_fixture, module_fixture, function_fixture):
    pass

Running python script.py:

Test session start
=================================== test session starts
platform linux -- Python 3.6.2, pytest-3.2.2, py-1.4.34, pluggy-0.4.0
rootdir: /home/stackoverflow, inifile:
collected 2 items                                                                                                                                                                                     

validation.py 
SETUP    S session_fixture
  SETUP    M module_fixture
      SETUP    F function_fixture
        validation.py::test_A (fixtures used: function_fixture, module_fixture, session_fixture).
      TEARDOWN F function_fixture
      SETUP    F function_fixture
        validation.py::test_B (fixtures used: function_fixture, module_fixture, session_fixture).
      TEARDOWN F function_fixture
  TEARDOWN M module_fixture
TEARDOWN S session_fixture

=================================== 2 passed in 0.00 seconds
like image 147
rjsberry Avatar answered Sep 13 '26 01:09

rjsberry



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!