Two related pytest
questions:
I have a fixture which is an iterable and which is tested in a certain test. This works. However, I also have a test which wants to test the individual values - I don't know how to do this.
For example, how can I write the student
fixture such that it returns each of the elements of klass
?
@pytest.fixture
def klass() -> list[str]:
return ['alice', 'bob', 'claire']
@pytest.fixture
def student(klass) -> str: # HERE IS THE QUESTION
#code that returns each student in the klass individually
def test_klass(klass): # ran once
assert len(klass) > 0
def test_student(student): # ran 3 times
assert isinstance(student, str)
The inverse problem occurs if I want to specify the students and combine them into a klass (the same test functions apply as above):
@pytest.fixture(params = ['alice', 'bob', 'claire'])
def student(request) -> str:
return request.param
@pytest.fixture
def klass(student) -> list[str]: # HERE IS THE QUESTION
#code that returns the list with all values for student
Testing individual values of an iterable in pytest
is done by parametrizing the test.
An easy way to adapt your test is to use a function that returns the parameters, which is used both in the fixture, and by pytest.mark.parametrize
(or by the parametrized fixture, whichever you prefer):
import pytest
def students() -> list[str]:
return ['alice', 'bob', 'claire']
@pytest.fixture
def klass() -> list[str]:
return students()
@pytest.fixture(params=students())
def student(request) -> str:
return request.param
def test_klass(klass): # runs once
assert len(klass) > 0
@pytest.mark.parametrize('s', students())
def test_student(s): # runs 3 times
assert isinstance(s, str)
def test_student2(student): # runs 3 times
assert isinstance(student, str)
Note that you cannot use a fixture in parametrize
(or in params
in the parametrized fixture) out of the box, so the iterable has to be defined in a function. As long as the function doesn't do extensive calculations, which would be run twice, this should be fine (otherwise the iterable may be cached).