Setting up and tearing down identical fixtures with very minor changes leads to code repetition and maintenance nightmare.

It’s all possible, and the answer lies in Pytest fixtures with arguments.

Parameterized Fixture

# Define a fixture with parameters  
@pytest.fixture(params=[0, 1, 2])  
def param_data(request):  
    return request.param  
  
# Test parametrized fixture  
def test_param_data(param_data):  
    assert param_data in [0, 1, 2]

In the above code, we pass the @pytest.fixture(params=[0, 1, 2]) marker to our param_datafixture and made use of the request argument within our fixture.

Fixture With Argument (Indirect parametrization)

What if you don’t want to define the parameters in the fixture but rather in the test?

Use indirect parametrization to pass arguments to the fixture

@pytest.mark.parametrize("square", [1, 2, 3], indirect=True)
 
def test_square(square):
 
assert square in [2, 4, 6]

In our test, we use the indirect=True argument to tell Pytest to pass this parameter to the square fixture.

Factories As Fixtures

Factories, in the context of Pytest fixtures, are functions that are used to create and return instances of objects that are needed for testing.

# tests/test_basic_example.py
 
@pytest.fixture  
def user_creds():  
    def _user_creds(name: str, email: str):  
        return {"name": name, "email": email}  
  
    return _user_creds  
  
  
def test_user_creds(user_creds):  
    assert user_creds("John", "abc@xyz.com") == {  
        "name": "John",  
        "email": "abc@xyz.com",  
    }

Simulating User Actions:

For UI testing or user interaction testing, you may want to pass arguments to fixtures to simulate different user actions or scenarios.

@pytest.fixture  
def user_actions():  
    def perform_user_action(action_type):  
        if action_type == "login":  
            # Simulate user login  
        elif action_type == "logout":  
            # Simulate user logout  
        else:  
            raise ValueError("Invalid action type")  
    return perform_user_action  
  
def test_user_login(user_actions):  
    user_actions("login")  
    # Test user login behavior  
    # Additional assertions and test logic here