4

I have parameterized my fixture to call APIs, with different input data to POST request on each call with scope as class. Since I need to check API response with sent data. I need to read request params of the fixtures into tests.

class Test_create_fixture():

@pytest.fixture(scope="class", params=[0, 1])
def my_fixture(self, request):
    "Call incident creation api."

    # POST request to API using params value in request data, get data from API      
    my_data = {'abc': 123, 'severity': 0} # this data is from API

    self.data = {'severity': request.param}

    return my_data

def test_incident_severity(self, my_fixture, request):
    print("self.data", self.data) # 'Test_create_fixture' object has no attribute 'data'
    assert my_fixture.get('severity', False) == request.param # AttributeError: 'FixtureRequest' object has no attribute 'param'

But when I run this I am not able to read request params passed to fixture into tests. Also tried to save in instance variable but didn't worked. I have observed that id() property of self in fixture and self in tests is different. Why is so? Is there way to achieve this?

Amit K.
  • 549
  • 2
  • 5
  • 11

1 Answers1

3

You can pass on the request.param from the fixture to the test functions. You can add it to the my_data object itself.

class Test_create_fixture():

    @pytest.fixture(scope="class", params=[0, 1])
    def my_fixture(self, request):
        "Call incident creation api."

        # POST request to API using params value in request data, get data from API      
        my_data = {'abc': 123, 'severity': 0, 'req_param': request.param} # this data is from API

        return my_data

    def test_incident_severity(self, my_fixture):
        assert my_fixture.get('severity', False) == my_fixture.get('req_param')

Update:

Since you are parametrizing the fixture, request.param is available only in the fixture function where the parametrization is defined.

Another possibility is to introduce another fixture which is parameterized and returns the parameter. The current fixture and the test functions use this new fixture to get the param.

class Test_create_fixture():

    @pytest.fixture(scope="class", params=[0,1])
    def req_param(self, request):
        return request.param

    @pytest.fixture(scope="class")
    def my_fixture(self, req_param):
        "Call incident creation api."

        # POST request to API using req_param in request data, get data from API      
        my_data = {'abc': 123, 'severity': 0} # this data is from API

        return my_data

    def test_incident_severity(self, my_fixture, req_param):
        assert my_fixture.get('severity', False) == req_param
yeniv
  • 1,589
  • 11
  • 25
  • That is actually updating the API response, which I differed doing. Returning multiple values or updating the returning value can be solution but it is a work around. – Amit K. Oct 11 '19 at 05:26
  • I have updated the answer for another alternative where the API response stays intact. – yeniv Oct 11 '19 at 06:56
  • Your comment *"Since you are parametrizing the fixture, request.param is available only in the fixture function where the parametrization is defined"* is not True at all, request object is maintained for the complete test run can be accessed in other tests where you need params. Here issue is pytest instantiate class fixture at start and create another instance while running the tests, So the instance do not share the values. – Amit K. Oct 11 '19 at 07:18
  • 1
    _request object is maintained for the complete test run can be accessed in other tests where you need params._ But I said, `request.param` is not available in the test function (with parameterized fixtures) and that's the reason you get the AttributeError when trying to use it in the test function. – yeniv Oct 11 '19 at 11:54