HomeContact
Python
Understanding fixtures in pytest
Karthikeya
October 12, 2021
1 min

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.

1. what are fixtures?

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.

  1. Pytest knows about the existence of all the fixtures written.
  2. Pytest manages the lifecycle of all the fixtures.
  3. Since pytest knows about the existence of the fixtures, they can be bound with additional capabilities.

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.

Code Example : 1


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.

  1. generate_random_user_details is marked as a fixture.
  2. test_user_registration takes generate_random_user_details as an argument.
  3. We are directly passing the 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


Related Posts

Deep comparison of JSON in python
November 18, 2021
1 min
© 2021, All Rights Reserved.

Quick Links

About UsContact UsSite Map

Social Media