This rule raises an issue when a collected test function calls request.getfixturevalue() with a string literal fixture name instead of
declaring that fixture as a function parameter.
In Python’s pytest framework, this specifically refers to the request.getfixturevalue() method.
In testing frameworks, dependency injection is a powerful mechanism for managing test dependencies and setup code. These frameworks are designed to automatically discover and inject dependencies based on function signatures, creating a clear dependency graph.
When a test function uses request.getfixturevalue() with a string literal to load a fixture whose name is already known at write time,
it bypasses the framework’s built-in dependency tracking. This creates several problems:
This issue applies when the fixture name is fixed as a string literal in the test. When the name comes from parametrization, configuration, or another runtime source, dynamic lookup is intentional and not reported.
Dynamic dependency loading with getfixturevalue() remains appropriate inside fixture functions when setup must load another fixture
conditionally. In collected test functions, dependencies with known names should be declared through the framework’s static declaration mechanism.
By declaring known fixture dependencies as parameters, you make your tests more explicit, easier to understand, and better integrated with the framework’s dependency management system.
In pytest specifically, this anti-pattern manifests when a collected test function calls request.getfixturevalue() with a string
literal fixture name. When the fixture name is known at write time, declare it as a test parameter so dependencies stay visible to readers and static
analysis.
request.getfixturevalue() remains appropriate inside @pytest.fixture functions for fixture chains, and in tests that
resolve fixture names from parametrization or configuration when the name is not fixed at write time.
Using request.getfixturevalue() inside @pytest.fixture functions is acceptable when one fixture must load another
conditionally.
When the fixture name comes from a variable, for example via @pytest.mark.parametrize, dynamic lookup is intentional and out of scope
for this rule.
Fixture and hook definitions in conftest.py are not collected test functions and are not reported.
Tests that exercise pytest plugins or the fixture request API itself may legitimately call getfixturevalue with a runtime name. Review
manually and suppress only when the test’s purpose requires dynamic fixture resolution.
Refactoring fixture names leaves no static trace in test signatures, so broken dependencies surface only when tests execute.
Replace string-literal request.getfixturevalue() calls in test functions with explicit parameter declaration. Convert the call into a
function parameter with the same name as the fixture being requested.
Keep request.getfixturevalue() inside fixture functions when setup must load another fixture conditionally. When a test must exercise
multiple fixtures from a parametrized name matrix, keep the variable lookup and treat it as an accepted pattern rather than a violation.
import pytest
@pytest.fixture
def database():
class DB:
def query(self, sql):
return 1
return DB()
def test_database_query(request):
# Noncompliant: known fixture name loaded dynamically
db = request.getfixturevalue('database')
result = db.query('SELECT 1')
assert result == 1
import pytest
@pytest.fixture
def database():
class DB:
def query(self, sql):
return 1
return DB()
def test_database_query(database):
# Fixture dependency is now explicit
result = database.query('SELECT 1')
assert result == 1
Parametrized fixture-name resolution and fixture chains are acceptable and not reported:
import pytest
@pytest.fixture
def database():
return object()
@pytest.fixture
def cache():
return object()
@pytest.fixture
def combined(request):
# Compliant: fixture-to-fixture lookup
return request.getfixturevalue('database')
@pytest.mark.parametrize('fixture_name', ['database', 'cache'])
def test_matrix(request, fixture_name):
# Compliant: fixture name comes from parametrization
fixture = request.getfixturevalue(fixture_name)
assert fixture is not None