pytest
python
testing
test automation
disabling tests

How do I disable a test using pytest?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

pytest provides several ways to disable (skip) tests: @pytest.mark.skip unconditionally skips a test, @pytest.mark.skipif skips based on a condition, pytest.importorskip skips if a module is missing, and @pytest.mark.xfail marks a test as expected to fail without blocking the test suite. Skipped tests appear as s in the output and are counted separately from passes and failures. These markers are essential for handling platform-specific tests, optional dependencies, and known bugs.

Unconditional Skip

python
1import pytest
2
3@pytest.mark.skip(reason="Not implemented yet")
4def test_future_feature():
5    assert some_function() == expected_value
6
7# Skip an entire class
8@pytest.mark.skip(reason="Refactoring in progress")
9class TestOldModule:
10    def test_one(self):
11        pass
12
13    def test_two(self):
14        pass

@pytest.mark.skip permanently disables the test. Always provide a reason so teammates know why it was skipped. The reason appears in the output with -v or -rs flags.

Conditional Skip

python
1import sys
2import pytest
3
4# Skip on specific Python version
5@pytest.mark.skipif(sys.version_info < (3, 10), reason="Requires Python 3.10+")
6def test_match_statement():
7    match value:
8        case 1:
9            assert True
10
11# Skip on specific platform
12@pytest.mark.skipif(sys.platform == "win32", reason="Unix-only test")
13def test_unix_permissions():
14    import os
15    assert os.access("/tmp", os.W_OK)
16
17# Skip based on environment variable
18import os
19@pytest.mark.skipif(
20    os.environ.get("CI") != "true",
21    reason="Only runs in CI environment"
22)
23def test_integration():
24    pass
25
26# Multiple conditions
27@pytest.mark.skipif(
28    sys.platform == "darwin" and sys.version_info < (3, 9),
29    reason="Known issue on macOS with Python < 3.9"
30)
31def test_macos_specific():
32    pass

skipif evaluates the condition at collection time. If true, the test is skipped with the given reason.

Skip if Module Not Available

python
1import pytest
2
3# Skip if the optional dependency is not installed
4np = pytest.importorskip("numpy")
5pd = pytest.importorskip("pandas", minversion="1.5.0")
6
7def test_numpy_calculation():
8    arr = np.array([1, 2, 3])
9    assert np.sum(arr) == 6
10
11def test_pandas_dataframe():
12    df = pd.DataFrame({"a": [1, 2, 3]})
13    assert len(df) == 3
14
15# Module-level skip — skips the entire file
16pytest.importorskip("some_optional_lib")

importorskip attempts to import the module and skips all tests in the file (or test) if it fails. The minversion parameter checks the module's __version__.

Expected Failure (xfail)

python
1import pytest
2
3@pytest.mark.xfail(reason="Known bug #1234")
4def test_known_bug():
5    assert broken_function() == expected  # Test runs but failure is expected
6
7# xfail with condition
8@pytest.mark.xfail(
9    sys.platform == "win32",
10    reason="Windows file locking issue"
11)
12def test_file_operation():
13    pass
14
15# Strict xfail — fails if the test unexpectedly passes
16@pytest.mark.xfail(strict=True, reason="Should not pass until bug #1234 is fixed")
17def test_strict_xfail():
18    assert broken_function() == expected

xfail lets the test run. If it fails, it is reported as xfail (expected). If it unexpectedly passes, it is reported as xpass. With strict=True, an unexpected pass counts as a test failure.

Skip at Runtime

python
1import pytest
2
3def test_database_connection():
4    db = connect_to_database()
5    if db is None:
6        pytest.skip("Database not available")
7    assert db.is_connected()
8
9def test_with_external_service():
10    try:
11        response = requests.get("https://api.example.com/health", timeout=2)
12    except requests.ConnectionError:
13        pytest.skip("External service unreachable")
14    assert response.status_code == 200

pytest.skip() called inside a test body skips at runtime after the test has already started. Use this when the skip condition can only be determined during execution.

Skipping in Fixtures

python
1import pytest
2
3@pytest.fixture
4def database():
5    try:
6        db = connect_to_database()
7    except ConnectionError:
8        pytest.skip("Database not available")
9    yield db
10    db.close()
11
12def test_query(database):
13    # Skipped if the database fixture calls pytest.skip()
14    result = database.execute("SELECT 1")
15    assert result == 1

When a fixture calls pytest.skip(), all tests that use that fixture are skipped.

Custom Skip Markers

python
1# conftest.py
2import pytest
3
4# Register custom markers
5def pytest_configure(config):
6    config.addinivalue_line("markers", "slow: marks tests as slow")
7    config.addinivalue_line("markers", "integration: marks integration tests")
8
9# pytest.ini or pyproject.toml
10# [tool.pytest.ini_options]
11# markers = [
12#     "slow: marks tests as slow",
13#     "integration: marks integration tests",
14# ]
python
1# test_example.py
2import pytest
3
4@pytest.mark.slow
5def test_heavy_computation():
6    pass
7
8@pytest.mark.integration
9def test_api_call():
10    pass
bash
1# Run only fast tests (exclude slow)
2pytest -m "not slow"
3
4# Run only integration tests
5pytest -m integration
6
7# Exclude multiple markers
8pytest -m "not slow and not integration"

Custom markers combined with -m let you selectively run or skip categories of tests without modifying the test code.

Common Pitfalls

  • Skipping without a reason: @pytest.mark.skip without reason makes it unclear why the test was disabled. Always provide a reason so the skip can be revisited later.
  • Using skip instead of xfail for known bugs: skip hides the test entirely. xfail runs the test and alerts you when the bug is fixed (the test unexpectedly passes). Use xfail for known bugs.
  • Forgetting to re-enable skipped tests: Skipped tests accumulate over time. Regularly audit tests marked with skip and skipif to check whether the conditions still apply.
  • skipif condition evaluated at import time: The condition in @pytest.mark.skipif runs when the module is imported. Side effects in the condition (like network calls) slow down test collection for all tests.
  • Commenting out tests instead of using skip: Commented-out tests are invisible in test reports. Use @pytest.mark.skip so the test appears in the output and can be tracked.

Summary

  • @pytest.mark.skip(reason="...") unconditionally skips a test
  • @pytest.mark.skipif(condition, reason="...") skips based on runtime conditions
  • pytest.importorskip("module") skips if an optional dependency is missing
  • @pytest.mark.xfail(reason="...") lets the test run but expects it to fail
  • pytest.skip("reason") skips at runtime from inside a test body or fixture
  • Use custom markers with pytest -m "not slow" to exclude test categories from the command line

Course illustration
Course illustration

All Rights Reserved.