Introduction:
Pytest is one of the best open source, simple, scalable and Python based Test Automation Framework. Pytest powers you to test anything including Databases, UI and is more popular among testers for API Testing. Pytest can either be run as an individual tool for testing or it can be attached with Python web development frameworks like Django or Flask, enhancing their unit test capabilities and reliability. Tests in pytest are basically python functions and we can run tests as whole, or specifically based on tags or names. Also, parallel test running is an inbuilt feature to Pytest and you can access that by simply specifying an extra argument to CLI pytest run.
Now let’s dig deep into the pytest features.
- Test Creation
Creating tests in pytest is simple as writing a Python Function, except the function name should start with ‘test_’. We can use statements like assert to verify whether the expected output is same as actual output. We can also write test classes. But in this blog we will stick with writing functions.
Example:
Here we are going to test a simple function which returns an Integer 10. In our test we will verify whether we got the expected output.
Program test_fun.py
def my_func():
return 10
def test_my_func():
expected_out = 10
assert my_func() == expected_out
We can execute this test using pytest cli and verify whether everything works fine.
Out Put:
Inorder to use pytest, we need python in our PC and then ‘pip install pytest’.In the below example we can see that, we ran the by only specifying command pytest, not even the file name
Example.1
- Auto Test Discovery
In the example.1, we ran a test without specifying anything, by utilizing the pytest inbuilt intelligent test auto discovery feature. Pytest can automatically identify test functions name starting with ‘test_’ and files names starting with ‘test’ or ending with ‘_test’ from the directory and the sub-directories. We can introduce other name patterns to be included in this test auto discovery by configuring pytest.ini.
- Command Line Execution
Pytest has so many awesome features under the hood which are available as command line arguments. You can see all of the by typing ‘pytest –help’. I’ll explain some basic ones here.
- pytest <file_name>
Run tests in the specified file
e.g:pytest test_demo.py
- pytest filename::testName
Runs the specified function in the speciied file, we can specify multiple files in same format
e.g:pytest test_demo::test_addition
- pytest –m <marker tag>
Runs all the tests with specified markers, user for grouping
- Parameterization of Test
In test automation, there will be some scenarios where we need to automate similar test cases with minute differences. For example, we may need to verify some site is accessible via http and https and do some more similar steps. So if there are 15 steps 13 will be similar, instead of writing two different test cases, pytest provides a functionality called Parameterization, where we can club them as one and parameterize them with the changing variables.
Example:
Program test_parameterization.py
from pytest import mark
@mark.parametrize(“http_method”,[‘http’, ‘https’])
def test_my_func(http_method):
# Some steps
print(http_method)
# Some more steps
Output:
Here we can see that, both of the parameters where executes as different tests.
- Fixtures
Fixtures are special type of functions which will run before test function, module or the whole session based on their configuration and returns any intended values. They will help us to execute a piece of code. Like we may need to create a database object or so on and then return them if necessary. A fixture can be session scoped, module scoped or function scoped and that defines their lifetime.
Example:
We are returning a string to test functions as an example. We can do a lot more using these fixtures.
Program test_db.py
import pytest
@pytest.fixture
def input_value():
database = ‘my_sql’
return database
def test_div_3(input_value):
print(input_value)
def test_div_5(input_value):
print(input_value)
Output :
- Hooks
Hooks are a great way to modify the behavior of the pytest like test identification, logging. It also helps to setup something on startup and so on. We generally write hooks and fixtures in a file in the main directory which contains the test.
- Markers
Markers help us to easily categories our test. We can do any number of marking and choose which one to run at the test run starting time. Also some markers have some special behavior. For example we can mark a test as skip and that test won’t be executed as part of the run
Example:
import pytest
@pytest.mark.runthis
def test_div_3():
print(“Marked Test”) +
@pytest.mark.skip
def test_div_5():
print(“Skipped Test”)
Output :
In the output, only the markers given behind the –m is run. If you don’t specify any markers in CLI command every test marked as skip will be avoided.
- Plug-ins
Plug-in is a great way to extend the functionality of pytest. Some of the commonly used plugins are
- Pytest-sugar – Gives a more beautiful cli ui for pytest including a progress bar.
- Pytest-cov – Checks the test code coverage of the scripts
- Pytest-picked – Runs the test which are modified and not committed to git.
- Pytest-instafail – Shows failures and warning instantly
- Pytest-xdist – Helps to run multiple tests parellely
- Reporting
Apart from showing a log in the cli, pytest has inbuilt feature to write the logs to a file. For example you can use pytest –junitxml=<path> to store the logs in the specified path. Pytest is still gaining in popularity and the community is also developing more and more plugins and features for pytest. Hope you can take advantage of pytest and its features in automation testing API’s or any other kind of testing.
Author Bio:
Anandhu Devaraj: Anandhu works as a Software Engineer in ETG. His hobbies include cycling, reading and googling.