pytest
python
testing
test automation
disabling tests

How do I disable a test using pytest?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

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

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.