Python: Unit test with Pytest- Part-5

In Part-5 we are going to see @pytest.fixture features of pytest . Fixtures define the steps and data that constitute arrange phase of a test. Fixtures are functions, which will run before each test function to which it is applied. Fixtures help us to avoid running the same code for each test, instead, we can attach a fixture to the tests and it will run and return the data to the test before running tests.
You can mark a function as a fixture by decorating it with @pytest.fixture
Example:
@pytest.fixture
def foo():
passScopes of fixtures
Fixtures can have the following types of scopes they are first requested by a test, and then destroyed based on their scope:
function: thedefaultscope, the fixture is destroyed at the end of the test.class: the fixture is destroyed after the last test in the class is executed.module: the fixture is destroyed after the last test in the module is executed.package: the fixture is destroyed after the last test in the package is executed.session: the fixture is destroyed at the end of the test session.
let's see with a working example.
let’s create a sample employee.py Here we have an Employee class and its methods.
from datetime import datetimeclass Employee:def __init__(self, fname:str,lname:str,salary:float):
self.fname = fname
self.lname = lname
self.salary = salarydef get_name(self):
return f"{self.fname} {self.lname}"def get_salary(self):
return self.salary
def get_salary_after_tax(self):
return (self.salary - self.salary*0.25)Now let’s create the test_employee_without_fixture.py to write the test for the employee.py. Here as you can see we are creating instance of Employee class for each test.
from calendar import c
from datetime import datetimeimport pytestfrom src.employee import Employeedef test_employee_get_name():
dummy_employee = Employee("Sunil", "Kumar", 100000.00)
assert dummy_employee.get_name() == f"{dummy_employee.fname} {dummy_employee.lname}"def test_get_salary():
dummy_employee = Employee("Sunil", "Kumar", 100000.00)
assert dummy_employee.get_salary() == 100000.00def test_get_salary_after_tax():
dummy_employee = Employee("Sunil", "Kumar", 100000.00)
assert dummy_employee.get_salary_after_tax(0.25) == (dummy_employee.salary - dummy_employee.salary*0.25)let's run and see the output:

Now let’s create the test_employee_with_fixture.py to write the test for the employee.py. Here you can see we have created fixture dummy_employee with function scope and attached it to each test case. Here we don’t have to create an instance of an Employee for each test instead we are using the same fixture for each test.
from calendar import c
from datetime import datetimeimport pytestfrom src.employee import Employee# Arrange
@pytest.fixture(scope="function")
def dummy_employee():
print("making dummy employee")
return Employee("Sunil", "Kumar", 100000.00)def test_employee_get_name(dummy_employee):
assert dummy_employee.get_name() == f"{dummy_employee.fname} {dummy_employee.lname}"def test_student_add_credits(dummy_employee):
assert dummy_employee.get_salary() == 100000.00def test_get_salary_after_tax(dummy_employee):
assert dummy_employee.get_salary_after_tax(0.25) == (dummy_employee.salary - dummy_employee.salary*0.25)let’s run and see the output:

Sharing fixtures across with multiple test defined in different modules
In pytest we can use conftest.py file to define fixtures with scope=”module” that can be used/accessed in multiple test modules in the directory.
lets create conftest.py
# conftest.pyimport pytestfrom src.employee import Employee@pytest.fixture(scope="module" )
def dummy_employee():
return Employee("Sunil", "Kumar", 100000.00)@pytest.fixture(scope="module" )
def tax():
return 0.25Now lets defines tests in two different module files and use the fixtures defined in conftest.py file.
# test_employee_with_fixture1.pydef test_employee_get_name(dummy_employee):
assert dummy_employee.get_name() == f"{dummy_employee.fname}{dummy_employee.lname}"# test_employee_with_fixture2.py
def test_student_add_credits(dummy_employee):
assert dummy_employee.get_salary() == 100000.00def test_get_salary_after_tax(dummy_employee,tax):
assert dummy_employee.get_salary_after_tax(tax) == (dummy_employee.salary - dummy_employee.salary*tax)Screen shot from IDE

let’s run and see the output:

here we can see the test defined in different module are passed.
Conclusion:
pytest fixtures are a generalized way to set up/tear down a test case or a test suite. We can share fixtures via conftest, adding multiple fixtures to tests and scoping fixtures.
Reference :
