Sometimes tests should not run or are expected to fail. Built-in markers help control this easily.
Built-in markers (skip, skipif, xfail) in PyTest
import pytest @pytest.mark.skip(reason="reason text") def test_example(): assert True @pytest.mark.skipif(condition, reason="reason text") def test_conditional(): assert True @pytest.mark.xfail(condition=None, reason="reason text", strict=False) def test_expected_fail(): assert False
skip always skips the test with a reason.
skipif skips the test only if the condition is True.
xfail marks a test as expected to fail; it won't fail the test suite if it does.
import pytest @pytest.mark.skip(reason="Not ready yet") def test_skip(): assert 1 == 1
import sys import pytest @pytest.mark.skipif(sys.platform == "win32", reason="Does not run on Windows") def test_skipif(): assert True
import pytest @pytest.mark.xfail(reason="Bug #123") def test_xfail(): assert False
import pytest @pytest.mark.xfail(strict=True, reason="Fix soon") def test_xfail_strict(): assert True
This script shows all three markers:
test_always_skipis always skipped.test_skipif_versionruns only if Python version is 3.8 or higher.test_expected_failureis expected to fail and won't break the test suite.test_xfail_strictis expected to fail but passes, so pytest will report an error because of strict=True.
import sys import pytest @pytest.mark.skip(reason="Skipping this test always") def test_always_skip(): assert False @pytest.mark.skipif(sys.version_info < (3, 8), reason="Needs Python 3.8+") def test_skipif_version(): assert True @pytest.mark.xfail(reason="Known bug in feature") def test_expected_failure(): assert False @pytest.mark.xfail(strict=True, reason="Should fix soon") def test_xfail_strict(): assert True
Always provide a clear reason to explain why a test is skipped or expected to fail.
Use skipif for conditions like OS, Python version, or missing dependencies.
With xfail(strict=True), a passing test will cause pytest to fail, helping track bug fixes.
Built-in markers help control test execution flow simply.
skip always skips, skipif skips conditionally, xfail marks expected failures.
Use them to manage tests during development and known issues.
Practice
@pytest.mark.skip marker do in a test?Solution
Step 1: Understand the purpose of
This marker tells pytest to skip the test unconditionally, so the test is not executed at all.@pytest.mark.skipStep 2: Compare with other markers
skipifskips conditionally, andxfailmarks expected failures but runs the test. So onlyskipalways skips.Final Answer:
It always skips the test, so it does not run. -> Option DQuick Check:
@pytest.mark.skipalways skips = D [OK]
- Confusing skip with skipif (conditional skip)
- Thinking xfail skips the test
- Assuming skip reruns the test
Solution
Step 1: Check correct version tuple comparison syntax
Python version info is a tuple like (3, 7, 5). So comparisons must use tuples, e.g., (3, 8).Step 2: Verify correct use of
@pytest.mark.skipif(sys.version_info < (3, 8), reason='Python < 3.8')\ndef test_func(): pass uses tuple comparison and includes a reason string, which is best practice for clarity.skipifwith reasonFinal Answer:
@pytest.mark.skipif(sys.version_info < (3, 8), reason='Python < 3.8')\ndef test_func(): pass -> Option BQuick Check:
Use tuple and reason in skipif = C [OK]
- Using float instead of tuple for version
- Omitting reason argument
- Comparing version to string
import pytest
@pytest.mark.xfail
def test_example():
assert 1 == 2Solution
Step 1: Understand
This marker means the test is expected to fail. If it fails, pytest reports it as an expected failure, not a hard failure.@pytest.mark.xfailbehaviorStep 2: Analyze the assertion
The assertion1 == 2is false, so the test fails. Because ofxfail, this failure is expected and reported accordingly.Final Answer:
Test is marked as expected failure but does not fail the suite. -> Option AQuick Check:
xfail means expected failure = A [OK]
- Thinking xfail skips the test
- Assuming test passes despite assertion
- Confusing xfail with skipif
import pytest
@pytest.mark.skipif(sys.platform == 'win32')
def test_func():
assert TrueSolution
Step 1: Check imports used in condition
The condition usessys.platform, butsysis not imported, causing a NameError at runtime.Step 2: Verify other parts
The condition syntax is correct with ==, skipif is valid, and test functions do not need to return values.Final Answer:
Missing import of sys module causes NameError. -> Option AQuick Check:
Missing import sys = A [OK]
- Forgetting to import sys
- Confusing skipif with skip
- Expecting test functions to return values
skipif and xfail markers?Solution
Step 1: Understand marker order and logic
Tests should be skipped on Windows unconditionally, soskipiffor Windows must be applied first.Step 2: Apply xfail conditionally for Python versions below 3.7
Thexfailmarker is applied second to mark expected failures on old Python versions.Step 3: Verify option correctness
@pytest.mark.skipif(sys.platform == 'win32', reason='Skip on Windows')\n@pytest.mark.xfail(sys.version_info < (3,7), reason='Expected fail on old Python')\ndef test_func(): pass appliesskipiffirst, thenxfail, both with reasons. This is the correct and clear approach.Final Answer:
Use skipif for Windows, then xfail for Python version condition with reasons. -> Option CQuick Check:
Skip first, then xfail with reasons = B [OK]
- Reversing marker order causing unexpected runs
- Combining conditions incorrectly in one skipif
- Omitting reason strings for markers
Ready to prove it?
Pass the test and this pattern moves unknown
