Registering Custom Markers in PyTest

When using custom markers in PyTest we need to register them before using. Let’s see how.

New to Pytest check this out New to Markers check this out

In the below example file test_custom_markers.py we have a custom marker @pytest.mark.regression


test_custom_markers.py

import pytest

@pytest.mark.regression
def test_database_insert_record(database_connection):
    if (database_connection):
        print("Insertion Successful. ")
        assert True

def test_ui_view_details(ui_open):
    if (ui_open):
        print("View details Successful")
        assert True

Let’s execute the test file.

C:\Users\PyTest_Project\UserApp>pytest test_custom_markers.py -v
==================================================================== test session starts ====================================================================
platform win32 -- Python 3.7.7, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- c:\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.7', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '5.4.3', 'py': '1.8.2', 'pluggy': '0.13.1'}, 'Plugins': {'django': '3.9.0', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.10.0', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Pr
ogram Files\\Java\\jdk1.8.0_191'}
rootdir: C:\Users\PyTest_Project\UserApp, inifile: pytest.ini
plugins: django-3.9.0, forked-1.1.3, html-2.1.1, metadata-1.10.0, xdist-1.32.0
collected 2 items
test_custom_markers.py::test_database_insert_record PASSED                                                                                                                                                                                                           [ 50%]
test_custom_markers.py::test_ui_view_details PASSED                                                                                                                                                                                                                  [100%]
==================================================================== warnings summary ====================================================================
test_custom_markers.py:3
  C:\Users\PyTest_Project\UserApp\test_custom_markers.py:3: PytestUnknownMarkWarning: Unknown pytest.mark.regression - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.
html
    @pytest.mark.regression
    -- Docs: https://docs.pytest.org/en/latest/warnings.html
==================================================================== 2 passed, 1 warning in 0.04s ====================================================================

It collected 2 tests executed them but threw a warning.

PytestUnknownMarkWarning: Unknown pytest.mark.regression - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/latest/mark.
html
    @pytest.mark.regression
    -- Docs: https://docs.pytest.org/en/latest/warnings.html

If you go into that link it provides different ways to register a custom marker. Here we will go through one way.

  1. Create a pytest.ini file at the root directory.

  2. Add these lines of code which will register a custom marker in PyTest. Here anything after the colon(:) is the description of the marker and its optional.

pytest.ini

[pytest]
markers =
    regression:Run the regression tests

Now let’s execute again

C:\Users\UserApp>pytest test_custom_markers.py -v
====================================================================test session starts ====================================================================
platform win32 -- Python 3.7.7, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- c:\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.7', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '5.4.3', 'py': '1.8.2', 'pluggy': '0.13.1'}, 'Plugins': {'django': '3.9.0', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.10.0', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Pr
ogram Files\\Java\\jdk1.8.0_191'}
rootdir: C:\Users\PyTest_Project\UserApp, inifile: pytest.ini
plugins: django-3.9.0, forked-1.1.3, html-2.1.1, metadata-1.10.0, xdist-1.32.0
collected 2 items
test_custom_markers.py::test_database_insert_record PASSED                                                                                                                                                                                                           [ 50%]
test_custom_markers.py::test_ui_view_details PASSED                                                                                                                                                                                                                  [100%]
====================================================================
2 passed in 0.03s ====================================================================

Voila! it executed without any warning.

Try adding another custom marker @pytest.mark.sanity without description.


test_custom_markers.py

import pytest

@pytest.mark.regression
def test_database_insert_record(database_connection):
    if (database_connection):
        print("Insertion Successful. ")
        assert True
        
@pytest.mark.sanity
def test_ui_view_details(ui_open):
    if (ui_open):
        print("View details Successful")
        assert True

pytest.ini

[pytest]
markers =
    regression:Run the regression tests
    sanity

Let’s run…

C:\Users\PyTest_Project\UserApp>pytest test_custom_markers.py -v
====================================================================
test session starts ====================================================================
platform win32 -- Python 3.7.7, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- c:\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.7', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '5.4.3', 'py': '1.8.2', 'pluggy': '0.13.1'}, 'Plugins': {'django': '3.9.0', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.10.0', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Pr
ogram Files\\Java\\jdk1.8.0_191'}
rootdir: C:\Users\PyTest_Project\UserApp, inifile: pytest.ini
plugins: django-3.9.0, forked-1.1.3, html-2.1.1, metadata-1.10.0, xdist-1.32.0
collected 2 items
test_custom_markers.py::test_database_insert_record PASSED                                                                                                                                                                                                           [ 50%]
test_custom_markers.py::test_ui_view_details PASSED                                                                                                                                                                                                                  [100%]
====================================================================
2 passed in 0.11s ====================================================================

Executed without any warnings.


To view, all the available markers (custom and built-in) use the following command:

pytest --markers

Here @pytest.mark.regression marker is shown with description and for @pytest.mark.sanity is shown with no description as we didn’t mention in pytest.ini. You can add a description in pytest.ini to be shown here. 

C:\Users\prade\PycharmProjects\PyTest_Project\UserApp>pytest --markers
@pytest.mark.regression:Run the regression tests
@pytest.mark.sanity:
@pytest.mark.forked: Always fork for this test.
@pytest.mark.django_db(transaction=False): Mark the test as using the Django test database.  The *transaction* argument marks will allow you to use real transactions in the test like Django's TransactionTestCase.
@pytest.mark.urls(modstr): Use a different URLconf for this test, similar to the `urls` attribute of Django's `TestCase` objects.  *modstr* is a string specifying the module of a URL config, e.g. "my_app.test_urls".
@pytest.mark.ignore_template_errors(): ignore errors from invalid template variables (if --fail-on-template-vars is used).
@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value.  Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see https://docs.p
ytest.org/en/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the tes
t function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/latest/skipping.html
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple
 names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see https://docs.pytest.org/en/latest/parametrize.html for more info and examples.
 @pytest .mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see https://docs.pytest.org/en/latest/fixture.html#usefixtures
 @pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
 @pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.

Strict markers

There is an option to add in pytest.ini that only the registered markers are to be used. If unregistered are used then an error occurs and the tests are not executed.

For that use addopts set to strict markers like below.


pytest.ini (observe the sanity marker is removed here) 

[pytest]

addopts = --strict-markers
markers =
    regression:Run the regression tests

For example, below we used the marker @pytest.mark.sanity without registering in pytest.ini file.

import pytest

@pytest.mark.regression
def test_database_insert_record(database_connection):
    if (database_connection):
        print("Insertion Successful. ")
        assert True

@pytest.mark.sanity
def test_ui_view_details(ui_open):
    if (ui_open):
        print("View details Successful")
        assert True

Lets’s run and see,

C:\Users\PyTest_Project\UserApp>pytest test_custom_markers.py -v
====================================================================test session starts ====================================================================
platform win32 -- Python 3.7.7, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- c:\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.7', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '5.4.3', 'py': '1.8.2', 'pluggy': '0.13.1'}, 'Plugins': {'django': '3.9.0', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.10.0', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Pr
ogram Files\\Java\\jdk1.8.0_191'}
rootdir: C:\Users\PyTest_Project\UserApp, inifile: pytest.ini
plugins: django-3.9.0, forked-1.1.3, html-2.1.1, metadata-1.10.0, xdist-1.32.0
collected 0 items / 1 error
====================================================================
ERRORS 
====================================================================
____________________________________________________________________ ERROR collecting test_custom_markers.py ____________________________________________________________________
'sanity' not found in `markers` configuration option
==================================================================== short test summary info ====================================================================
ERROR test_custom_markers.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
==================================================================== 
1 error in 0.26s ====================================================================

It encountered an error that ‘sanity’ not found in `markers` configuration option and none of the tests are collected.


Now, register the marker.

[pytest]

addopts = --strict-markers
markers =
    regression:Run the regression tests
    sanity: Run the sanity tests

Run again,

C:\Users\prade\UserApp>pytest test_custom_markers.py -v
==================================================================== test session starts ====================================================================
platform win32 -- Python 3.7.7, pytest-5.4.3, py-1.8.2, pluggy-0.13.1 -- c:\\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.7', 'Platform': 'Windows-10-10.0.19041-SP0', 'Packages': {'pytest': '5.4.3', 'py': '1.8.2', 'pluggy': '0.13.1'}, 'Plugins': {'django': '3.9.0', 'forked': '1.1.3', 'html': '2.1.1', 'metadata': '1.10.0', 'xdist': '1.32.0'}, 'JAVA_HOME': 'C:\\Pr
ogram Files\\Java\\jdk1.8.0_191'}
rootdir: C:\Users\PyTest_Project\UserApp, inifile: pytest.ini
plugins: django-3.9.0, forked-1.1.3, html-2.1.1, metadata-1.10.0, xdist-1.32.0
collected 2 items
test_custom_markers.py::test_database_insert_record PASSED                                                                                                                                                                                                           [ 50%]
test_custom_markers.py::test_ui_view_details PASSED                                                                                                                                                                                                                  [100%]
==================================================================== 2 passed in 0.05s ====================================================================

All tests executed without any errors.

So, while using custom markers in PyTest don’t forget to register.



1,139 views0 comments

Recent Posts

See All

Headless Browser in Python

What is a headless browser? A headless browser can access any website but unlike normal browsers (which you currently use) nothing will appear on the screen. Everything is done on the backend side inv