Alnitak
Alnitak

Reputation: 2499

pytest multiple command-line skip options

I have different suites of tests.

There are normal tests, there are slow tests, and there are backend tests (and arbitrarily more "special" tests that may need to be skipped unless specified).

I would like to always skip slow and backend tests, unless --run-slow and/or --run-backend CLI options are passed.

If only --run-slow is passed, I will run all normal tests plus "slow" tests (eg those tests marked @pytest.mark.slow). Same thing for --run-backend; and if both CLI options are passed then run all normal tests + slow tests + backend tests.

I followed the pytest Control skipping of tests according to command line option pattern from the docs, but find myself not yet knowledgeable enough of pytest to extend it to having multiple skip CLI options.

Can anyone help me out?

Reference code snippet:

def pytest_addoption(parser):
    parser.addoption("--run-slow",    action="store_true", default=False, help="run slow tests")
    parser.addoption("--run-backend", action="store_true", default=False, help="run backend tests")


def pytest_configure(config):
    config.addinivalue_line("markers", "slow: mark test to run slow")
    config.addinivalue_line("markers", "backend: mark test as backend")


def pytest_collection_modifyitems(config, items):
    if config.getoption("--run-slow") or config.getoption("--run-backend"): # <-- this line logic is bad!
        return
    skip = pytest.mark.skip(reason="need '--run-*' option to run")
    for item in items:
        if "slow" in item.keywords or "backend" in item.keywords:
            item.add_marker(skip)

Thank you!

Upvotes: 1

Views: 532

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16855

If I understand the question correctly, you are asking for the logic in pytest_collection_modifyitems. You could just change your code to something like:

conftest.py

def pytest_collection_modifyitems(config, items):
    run_slow = config.getoption("--run-slow")
    run_backend = config.getoption("--run-backend")
    skip = pytest.mark.skip(reason="need '--run-*' option to run")
    for item in items:
        if (not run_slow and "slow" in item.keywords or 
            not run_backend and "backend" in item.keywords):
            item.add_marker(skip)

This would skip all tests marked as slow or backend by default. If adding the command line options --run-slow and/or --run-backend, the respective tests would not be skipped.

Another option (as mentioned in the comments) would be filtering by markers. In this case, instead of adding your own command line options, you could just filter tests by markers, e.g. use pytest -m "not (slow or backend)" to not run tests with these markers, and use pytest -m "not slow" and pytest -m "not backend" if you want to skip tests only for one marker. In this case you don't have to implement pytest_collection_modifyitems, but the default behavior would be to run all tests.

Upvotes: 1

Related Questions