Search code examples
pythonpython-3.xpytestpytest-fixtures

pytest 5.x+ upgrade and use a command line flag to run/skip decorated tests


I'm trying to upgrade from pytest 4.x to something newer. However, I'm running into issues where pytest.config was removed and I'm not sure how to accommodate the new syntax. Specifically, I'm trying to specify a command line flag that can run or skip specific decorated tests depending on whether or not the flag is present.

This is how it works in pytest 4.x.

# common.py
integration = pytest.mark.skipif(
    not pytest.config.getoption('--integration', False),
)

Then, elsewhere in the tests..

# test_something.py 
from .common import integration 

@integration
def test_mytest():
    1 == 1

@integration
def test_other_mytest():
    2 == 2

In newer versions of pytest, the above fails with:

AttributeError: module 'pytest' has no attribute 'config'

In pytest 5.x+, how can I achieve the same result as above - how can I pass in flag to pytest and run/skip certain tests based on that flag? Preferably, it would be nice to decorate them as in the example, as I have a lot of tests using the decorator syntax and it could be difficult to update them all. Any advice is much appreciated.


Solution

  • One option is to use a custom marker and the existing -m command line option. If you redefine your integration decorator like this:

    import pytest
    
    integration = pytest.mark.integration
    
    @integration
    def test1():
        pass
    
    def test2():
        pass
    

    And define the integration marker in pytest.ini:

    [pytest]
    markers =
      integration
    

    Then you can run all tests:

    $ pytest -v
    ========================================= test session starts =========================================
    platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3
    cachedir: .pytest_cache
    rootdir: /home/lars/tmp/python, configfile: pytest.ini
    collected 2 items
    
    test_skip.py::test1 PASSED                                                                      [ 50%]
    test_skip.py::test2 PASSED                                                                      [100%]
    
    ========================================== 2 passed in 0.00s ==========================================
    

    Or only integration tests:

    $ pytest -v -m integration
    ========================================= test session starts =========================================
    platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3
    cachedir: .pytest_cache
    rootdir: /home/lars/tmp/python, configfile: pytest.ini
    collected 2 items / 1 deselected / 1 selected
    
    test_skip.py::test1 PASSED                                                                      [100%]
    
    =================================== 1 passed, 1 deselected in 0.00s ===================================
    

    Or only non-integration tests:

    $ pytest -v -m 'not integration'
    ========================================= test session starts =========================================
    platform linux -- Python 3.11.6, pytest-7.2.2, pluggy-1.0.0 -- /usr/bin/python3
    cachedir: .pytest_cache
    rootdir: /home/lars/tmp/python, configfile: pytest.ini
    collected 2 items / 1 deselected / 1 selected
    
    test_skip.py::test2 PASSED                                                                      [100%]
    
    =================================== 1 passed, 1 deselected in 0.00s ===================================
    

    This meets your goal of not having to update all your tests.