How can I properly test 2 parameters function using Pytest?

Viewed 66

I' trying to properly test this simple function:

def get_content_from_header(request, header_name):
    try:
        content = request.headers[header_name]
    except KeyError:
        logging.error(f"BAD REQUEST: '{header_name}' header is missing from the request.")
    except AttributeError:
        logging.error(f"BAD REQUEST: request has no attributes 'headers'.")
    else:
        return content

    return None

So this is my code so far, I'm using parametrize along with fixture to achieve my goal:

import main
import pytest


class ValidRequest:
    def __init__(self):
        self.headers = {
            'Authorization': 'test_auth'
        }


@pytest.fixture
def mocked_request():
    request = ValidRequest()
    return request


@pytest.mark.parametrize("possible_input, expected_output",
                         [('Authorization', 'test_auth'),
                          ('InvalidHeader', None)])
def test_get_content_from_header(mocked_request, possible_input, expected_output):
    # Run the function with mocked request
    assert main.get_content_from_header(mocked_request, possible_input) == expected_output

Here's my problem: I only test the second parameter of the function get_content_from_header, not request which is the first one. How could I properly do that ?

  • Should I create a new class InvalidRequest and test my function with this new class in a new testing function just below test_get_content_from_header ?
  • Or should I add this new parameter trough parametrize in the existing testing function ?

What is the cleanest (more pythonic) way to do it ?

1 Answers

I would suggest a little change here, lets simplify that function a bit. Since that we are getting a certain header from the headers dict of the request we can just pass just the headers dict instead of the whole request.

def get_content_from_header(headers: dict, header_name: str):
    if header_name in headers.keys():
         return headers[header_name]
    return None

This works the same way as your function, and you do not have to test your request parameter. Now you can test that in a very simple manner:

def test_get_content_from_header_returning_header_value():
    headers = {"Authorization": "test_auth"}
    assert get_content_from_header(headers, "Authorization") == "test_auth"


def test_get_content_from_header_returning_none():
    headers = {"Authorization": None}
    assert get_content_from_header(headers, "Authorization") == None 

Now you don't need to test your request in that test, you can refer to https://flask.palletsprojects.com/en/2.0.x/testing/ and more specifically the client usage and test your endpoints, to test your request param.

Now about the loggers, I will usually place those in the place where you actually call the get_content_from_header function.

Related