Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest: test only one instance of parametrized fixture

Tags:

python

pytest

Setting

Suppose I have conftest.py where I defined resources for tests

class ClassifyRequest:
    pass

class OCRRequest:
    pass

@pytest.fixture(params=[ClassifyRequest, OCRRequest])
def api_request(request):
    return request.param()  # return one of the request instances

Then, in test_api.py I use the parametrized fixture to test a service:

def test_service(api_request):
    response = send_request(api_request)
    assert response.ok()

All good, but then I want to test specialized fixture api_request[ClassifyRequest]:

@pytest.mark.usefixture("api_request[ClassifyRequest]")
def test_classification():
    # do something with the api_request fixture

Question

What is the way to specialize a parametrized fixture for a test function? I have two ideas:

  1. Just use a non-parametrized fixture. This inevitably leads to boilerplate code.
  2. Remove explicit parametrization from the fixture decorator and use indirect parametrization like
    @pytest.mark.parametrize("response_class", ["classify", "ocr"])
    def test_api(api_request):
        # do smth
    
    Replacing class parameters with strings equals creating two sources of configuration. What if I want to add another parameter? Do I have to design a new string for it, as well as instantiate an object inside api_request fixture indirectly?
  3. The same, except keep class parametrization and move classes outside conftest.py as pytest can't import names from that module with import statements.

Additional info

pytest==6.0.1

like image 427
Ivan Kremnev Avatar asked Dec 03 '25 10:12

Ivan Kremnev


1 Answers

If all your fixture does is instantiation, I'd opt for parametrizing the test, not the fixture. But, well, if you have to and specialize it manually anyway, you could simply add a wrapper to make the fixture callable:

import pytest
import types

class ClassifyRequest:
    def __init__(self):
        print("ClassifyRequest ctor")

class OCRRequest:
    def __init__(self):
        print("OCRRequest ctor")

def api_request_wrapper(request):
    return request.param()  # return one of the request instances

@pytest.fixture(params=[ClassifyRequest, OCRRequest])
def api_request(request):
    return api_request_wrapper(request)

def test_classification():
    request = types.SimpleNamespace()
    request.param = ClassifyRequest
    instance = api_request_wrapper(request)

Seems a bit hacky, though.

like image 140
Marek Piotrowski Avatar answered Dec 05 '25 00:12

Marek Piotrowski



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!