Search code examples
pythonpytestfixtures

How to run a single test in pytest using a complex custom id as a selector?


A similar question is being asked here: parametrize and running a single test in pytest.

My question is more complex, as I parametrize the test with custom ids:

LIST_OF_PARAMS = [('A', 1, 'data1'), ('B', 2, 'data2'), ('C', 3, 'data3')]
@pytest.fixture(scope="session",
                params=LIST_OF_PARAMS,
                ids=[f"{key1}, {key2}" for key1, key2, _ in LIST_OF_PARAMS])
def data(self, request):
    return request.param

def test_foo(data):
    pass

The tests invoked with the ids removed are identified like that:

____________________ test_foo[data0] ____________________
____________________ test_foo[data1] ____________________
____________________ test_foo[data2] ____________________

This allows me to run a single test using the -k key:

python -m pytest -k "test_foo[data1]"

When I run pytest with custom ids, the identificators change:

____________________ test_foo[A, 1] ____________________
____________________ test_foo[B, 2] ____________________
____________________ test_foo[C, 3] ____________________

This no longer allows me to invoke a single test using test_foo[data1] key (which is expected and desired), but the invocation below doesn't work either:

python -m pytest -k "test_foo[B, 2]"

Pytest returns an error:

ERROR: Wrong expression passed to '-k': test_foo[B, 2]

Putting the expression into quotes doesn't help:

python -m pytest -k "test_foo['B, 2']"

AttributeError: 'KeywordMapping' object has no attribute 'get'

This example is artificial, in practice I have complex tuples as a parameter, and ids cannot be experessed as simple Python identificators. Anyway, pytest accepts these ids, and displays tests using the strings I provide. How should I specify the -k parameter to let pytest select the test using a complex custom identificator?


Solution

  • Short answer is you can't achieve what you are looking for using a comma. Pytest uses a specific parsing pattern which can be found here. This patterns allows for the following characters:

    +
    .
    \\
    /
    -
    _
    

    Your ids must use one of the following otherwise it will not work. Take a look at how Pytest tests the parser here. Longer answer is you can modify that pattern within your environment to suit your needs, but it might have unintended consequences when running the code.