How to Run Pytest Tests from a List of Test Paths

How can I select which pytest tests to run from a file?

For example, if I have a file foo.txt containing a list of tests to be executed:

tests_directory/foo.py::test_001 tests_directory/bar.py::test_some_other_test

Is there a way to select multiple tests that do not share a common pattern in their names, from different directories using pytest? While pytest -k allows for a single pattern, I need to run different combinations of tests from various files.

Is there a way to specify multiple patterns and a test file name for each pattern? Can I specify exact test paths in a file and feed that file as input to pytest? Alternatively, is there a hook function that can be used to achieve this?

I’m looking for a method to pytest run specific test based on a list of test paths provided in a file.

Ofcourse! To achieve what you’re asking, you can use pytest with the --ignore and --maxfail options. This is one way to manually control which tests to run by specifying the paths you want to include.

First, create a file tests_to_run.txt containing the list of test paths like this:


tests_directory/foo.py::test_001

tests_directory/bar.py::test_some_other_test

Then, use the following command to feed the test paths from the file directly into pytest:


pytest $(cat tests_to_run.txt)

This simple method allows you to pytest run specific test cases listed in tests_to_run.txt. It’s straightforward and avoids the need for complex pattern matching.

if you want something more customizable, you can create a custom pytest plugin to automatically read from your file and filter the tests to run.

Here’s how to do it. Create a file called pytest_plugins.py with the following code:

import pytest

def pytest_addoption(parser):
    parser.addoption("--testlist", action="store", default=None, help="Path to file with list of tests to run")

@pytest.hookimpl(tryfirst=True)
def pytest_collection_modifyitems(config, items):
    testlist_path = config.getoption("--testlist")
    if testlist_path:
        with open(testlist_path, 'r') as f:
            tests_to_run = set(line.strip() for line in f)
        
        items[:] = [item for item in items if f"{item.nodeid}" in tests_to_run]

Now, when running pytest, you simply pass the file like this:

pytest --testlist=tests_to_run.txt

This plugin will dynamically filter the collected tests based on the content of tests_to_run.txt, ensuring only those specific test cases are run. A very flexible way to pytest run specific test cases, especially if you have more complex test suite structures.

Another approach would be to use pytest markers to group your tests in a more structured way, especially if you plan to reuse test sets frequently.

You can mark your tests in the code like this:

import pytest

@pytest.mark.test_001
def test_001():
    assert True

@pytest.mark.test_some_other_test
def test_some_other_test():
    assert True

Next, create a file called markers.txt containing the list of markers you want to run:

test_001
test_some_other_test

Then, you can use a loop to run pytest for each marker:

for marker in $(cat markers.txt); do
    pytest -m $marker
done

This way, you leverage pytest’s marker feature to pytest run specific test cases associated with each marker, giving you even more control and flexibility.