Pytest send post request with different headers using fixtures

Question:

I want to test my API. My test should add some user to database using post request with admin_headers (admin headers mean that user sending request is admin, therefore new user can be added to database), then delete it, and then try to add data using post request with normal_user_headers (which should not be possible, as only admin can add new user). This operation will be repeated many times. I wanted to close this into some kind of fixture called add_user with parameter. For this parameter I wanted to pass something like admin_headers or user_headers. I want fixture to return response of post request.

I tried to write fixture like this:

@pytest.fixture
def add_user(
        test_client, request
):
    response = test_client.post(f'permissions/users', headers=request[0], json=request[1])
    yield response

request[1] is headers
request[2] is data of user which should be added if admin_headers are passed into headers argument

test looked like this:

def test_add_user_as_user(
        test_client, add_user, user_headers
):
    response = add_user(test_client, (user_headers, test_user_permissions))
    assert response.status_code == 403

However I got "TypeError: ‘SubRequest’ object is not subscriptable"

I was also trying to user @pytest.mark.parametrized on my test but could not figure out how that exactly works.

Asked By: BoroBoro

||

Answers:

You are attempting to use the fixture as if it was a normal function. It is not and you cannot call it with the given arguments, neither with that tuple of user_headers and test_user_permissions.

You can either use add_user as a normal function that needs to be imported wherever you try to use it…

def add_user(client, headers, data):
    return client.post(f'permissions/users', headers=headers, json=data)

…or you if you want to keep using it as a fixture, you can make it return a function that would then perform the request when called:

@pytest.fixture
def add_user():
    def _(client, headers, data)
        return client.post(f'permissions/users', headers=headers, json=data)

    return _

…and some of the fixtures might be included in the fixture itself so that you don’t need to pass them when calling it from within the test function:

@pytest.fixture
def add_user(test_client):
    def _(headers, data)
        return test_client.post(f'permissions/users', headers=headers, json=data)

    return _

In either case, you’d call it within a test function as any other function in Python:

add_user(client=test_client, headers=user_headers, data=test_user_permissions)

Note: Your original attempt with request in the fixture would make sense if you were trying to use it in indirect parametrization of tests but I’m not sure that’s your case.

Answered By: tmt
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.