I am trying to pass three different fixtures to my pytest.mark.parameterize
decorator, like this:
@pytest.mark.parametrize("credentials, return_code", [
(user1, 200),
#(user2, 200),
#(user3, 401)
])
def test_login():
assert True
# Actual test uses response.return_code == return_code
However, I get an error that reads:
NameError: name 'user1' is not defined
This isn't correct though, I have defined it in conftest.py
:
user1_info = [('user1', 'password')]
@pytest.fixture(params=user1_info)
def user1(request):
return request.param
The fixture works if I change my test to be like this:
def test_login(user1):
assert True
# Actual test uses response.return_code == return_code
The problem is that if I do it this way, I have to write three separate tests, one for each fixture, and for each status_code check. If I could use parameterize
, I could use one function and check the user/expected return code.
How can I utilize my fixtures are part of the pytest.mark.parameterize
decorator?
To pass fixtures as parametrized arguments, reference them as strings and use the keyword arguments indirect=['arg_name', ...]
.
Then use the parameter names credentials
and return_code
as arguments to your test function.
@pytest.mark.parametrize(
"credentials, return_code",
[
("user1", 200),
("user2", 200),
("user3", 401),
],
# Only the `credentials` parameter is a reference to the
# fixture. The `return_code` should be passed as is.
indirect=["credentials"],
)
def test_login(credentials, return_code):
return True
The documentation for pytest's parametrize
magic with indirect
can be found here:
https://docs.pytest.org/en/stable/example/parametrize.html#apply-indirect-on-particular-arguments