In this post, let us try to dive into the world of fixtures. We will cover the basics here and work our way to advanced use cases and patterns with fixtures in upcoming posts.
Think of fixtures as special functions in pytest, any python function decorated as @pytest.fixture
is a fixture.
When I say fixtures are special functions, I mean the following.
This forms the baseline for understanding the fixtures. Everything we do with fixtures will have to revolve around the factors mentioned above.
First, let us look at a test written without fixtures and then refactor it to introduce fixtures. This will solidify your understanding further.
def generate_random_user_details(): data = { "email" : f"tester.{random.randint(1000,9999)}@myaccount.com", "password" : f"{random.randint(10000000,99999999)}" } return data def test_user_registration(): user_details = generate_random_user_details() response = user_api.register(user_details) assert response['statusCode'] == 201, response.json()
Above is a simple code that is testing for user registration flow. Notice that the user details are obtained by explicitly calling the generate_random_user_details
method in the test.
Now, let us look at the code sample for the same test using fixtures.
@pytest.fixture def generate_random_user_details(): data = { "email" : f"tester.{random.randint(1000,9999)}@myaccount.com", "password" : f"{random.randint(10000000,99999999)}" } return data def test_user_registration(generate_random_user_details): response = user_api.register(generate_random_user_details) assert response['statusCode'] == 201, response.json()
If we see the refactored code, we can notice the following.
generate_random_user_details
is marked as a fixture.test_user_registration
takes generate_random_user_details
as an argument.generate_random_user_details
to the register API (we are not invoking the method).The reason we are passing the generate_random_user_details
directly to the register API is that pytest has already handled the method invocation for us.
Before starting the test, pytest collects all the fixtures required to run the tests, invokes them based on their scope (more on scopes later), and passes the result of the fixture invocation down to the test. This way, pytest is responsible for managing the fixture functions and not the maintainer of the test project. One less thing to worry about for the programmer!.
We can simply mention the fixtures we need to use as test arguments and pytest will handle the invocation behind the scenes. More on advanced use of fixtures here
Quick Links
Legal Information
Social Media