Automated testing Pytest Python

Build test suite with pytest

Pytest is a framework for running tests written in Python. It is easy to customize the launch of the tests. Let’s see what Pytest has to make it possible.

  • possibility to create you own fixtures
  • built-in fixtures
  • tests parametrization for running same tests with different test data
  • third-party plugins allow you to extend your tests capabilities:
    • add graphical reporting
    • empower API testing
    • parallel tests launching
    • and much more…

Pytest names requirements

You can organize the structure of the tests the way you want with almost no limitations. The only thing you should take care of, is the names of the directories, files, classes and methods/functions.

Directory name

All the directories that you want to include into the suite should have a name starting with “test”

File name

File name in the suite should start or end with “test”. So the wildcard for this name is “test_*.py” or “*”

Class name

The class name should start with “Test”

Method or function name

Every function and method that is supposed to test something should have a name that starts with “test”

Example of the suite is:



You can define your tests as class methods on as a separate functions in a file

Here is the example of the execution of the tests located in a class. Simple pytest run will not give you this picture. Use “pytest -v” to see more results like this:

Example of the tests run by Pytest

How to run Pytest

In most cases locally you will run pytest from the Python virtual environment. You can read about virtual environment in this blog post how to create a virtual environment.

All tests

from the root directory of the project just run:


All tests from a file

pytest test_dir/

All tests from a class

from a root directory of the project:

pytest test_dir/

One specific test

from a root directory of the project:

pytest test_dir/

Run Pytest without virtual environment

All the possibilities listed above are suitable. The difference is that you need to run pytest as a python module. In that case your machine’s Python environment will be used.

python -m pytest

Before / After blocks

There are no separate before / after blocks in pytest. This functionality can be implemented by fixtures. You can specify before / after what structural part of the tests it should be applied. This is configured using “scope” parameter. The options are “function”, “class”, “module”, “session”.

Here is the example of this before / after fixture on simple test:

import pytest

def demo():
    print('\nthis part will work before every test')
    yield None
    print('\nthis part will work after every test')

def test_one(demo):
    assert 2 == 2

def test_two(demo):
    assert 3 == 3

Note: to be able to see the text that you are printing during the test, run pytest with “-s” argument. 
this part will work before every test
this part will work after every test 
this part will work before every test
this part will work after every test

If you need the fixture to be applied to the test, you should specify its name in the test’s parameters. Here you see that fixture yields None but in most cases it will yield something that test needs. For example, connection:

import pytest

def db_cursor():
    db = mysql.connect(
    yield db.cursor(dictionary=True)

def test_one(db_cursor):
    db_cursor.execute('SELECT * FROM students')
    students = db_cursor.fetchall()
    assert len(students) > 0

def test_two(db_cursor):
    db_cursor.execute('SELECT * FROM students WHERE id = 1')
    student = db_cursor.fetchone()
    assert student['name'] == ‘John’

def test_three():
    assert 3 == 3

In this example you can see that I used “scope=’session’” for the fixture. So the connection will be established only once and it will happen before the testing session start. Database cursor will be yielded to each test that requires it. As you can see, the test_three doesn’t need the connection – so it doesn’t request it in the parameters. When the testing is finished, connection will be closed by the “db.close()” statement.

Pytest marks

To simplify the selection of the tests that should be run there is a possibility to mark them differently. So, later you will be able to specify what type of tests you want to run now. Do to that you can use this syntax:

import pytest

def test_one():
    assert 2 == 2

def test_two():
    assert 3 == 3

And now you can run only the smoke tests from the suite:

pytest -v -s -m smoke

But before you run this you need to register these new marks so that pytest understand what these marks are. Otherwise you will see warnings at each run. On this page you can see all the options how to register your marks. Here is the example of one of them.

Create a file called “pytest.ini” with the following content:

markers =
    smoke: smoke tests
    regression: regression tests

And now you are ready to run any smoke and regression tests from you test suite.

Run same tests with different data

There are many situations when you need to run to test the same scenario but with different data. For example, testing login with different usernames/passwrods. To do that you can use pytest parametrize function. Here is the example:

import pytest

    [2, 3, 4]
def test_one(num):
    assert num == 2

This test_one will be executed three times for each data in the list. Of course, two of these three tests will fail.[2] PASSED[3] FAILED[4] FAILED

By Eugene Okulik