Although unnittest ships with Python. Using Pytest is more Pythonic, which usually means easier to use. So, you hear that word, this, or that is Pythonic or more Pythonic. It just means easy.
- Install it in your virtual environment
(venv)$ pip install pytest
- In the root dir for the project::
(venv)$ mkdir tests && cd
- Then turn the tests folder into a package.
(venv)$ touch __init__.py
- Prefix all the files in the test dir with test_
(venv)$ touch test_arthmetic_operations.py
- Let’s define the functions that perform the arithmetic operations first.
- In the test file, add the following. (In the test file to get a handle on how pytest works). Typically, you would import that code under test. Create an object. Call the instance methods in the test method, but this is a simple example. If you were testing class-level methods, you would not need to create the object, you would call the class methods, and if the module was just a group of functions, you would import that module and call the function in the test method.
- This is the example for simplicity::
def add(a: int, b: int) -> int:
return a + b
def subtract(a: int, b: int) -> int:
return b - a
def multiply(a: int, b: int) -> int:
return a * b
def divide(a: int, b: int) -> int:
return b // a
- Now that the operations to be tested are defined. We will create functions that will create these tests.
- In the test functions, the operation to be executed is defined.
- The assert keyword is used to verify that the output on the left-hand side corresponds to the operation's output on the right-hand side. In our case, we will test that the arithmetic operations equal their respective results.
- Now add the following to the test_ file.
def test_add() -> None:
assert add(1, 1) == 2
def test_subtract() -> None:
assert subtract(2, 5) == 3
def test_multiply() -> None:
assert multiply(10, 10) == 100
def test_divide() -> None:
assert divide(25, 100) == 4
#asert key words tests if the expression being used above
#is true
-
Fixtures
- Fixtures are reusable functions defined to return the data needed in test functions.
- Fixtures are decorated with the pytest.fixture decorator
- An example use case of a fixture is returning an application instance to execute tests for the API endpoints.
- A fixture can define the application client returned and used in test functions, eliminating the need to redefine the application instance in every test.
- It makes these resources available to every test, and they don’t get redefined in every test; hence it’s a FIXTURE.
import pytest
from models.events import EventUpdate
#Fixture is defined.
@pytest.fixture
def event() -> EventUpdate:
return EventUpdate(
title="FastAPI Book Launch",
image="<https://packt.com/fastapi.png>",
description="We will be discussing the contents of the FastAPI book."
tags = ["python", "fastapi", "book", "launch"]
location = "Google Meet"
)
def test_event_name(event: EventUpdate) -> None:
assert event.title == "FastAPI Book Launch"
- The fixture decorator can optionally take arguments. One of these arguments is scope - the scope of a fixture tells pytest what the duration of the fixture function will be. This chapter, we’ll make use of two scopes.
- session:: This scope tells pytest to instantiate the function once for the whole testing session. (set up)
- module:: This scope instructs pytest. to execute the affixed function only once the test file is executed. (clean up)