Skipping tests and expected failures

unittest · Practical · 7 min

Platform-specific code and optional dependencies need tests that skip cleanly instead of failing.

Some tests can't run everywhere: a Windows-only path, a test needing a network service or an optional package. unittest offers decorators, usable on methods or whole classes:

  • @unittest.skip("reason"): always skip.
  • @unittest.skipIf(condition, "reason"): skip when the condition is true, e.g. sys.platform == "win32".
  • @unittest.skipUnless(condition, "reason"): skip unless it's true, e.g. an environment variable is set.
  • Inside a test or setUp: self.skipTest("reason") decides at runtime.

Skipped tests show as s and in the summary as OK (skipped=2). Always give a reason; -v prints it.

For optional imports, a common pattern is:

try:
    import numpy
except ImportError:
    numpy = None
@unittest.skipIf(numpy is None, "numpy not installed")

@unittest.expectedFailure marks a test that currently fails because of a known bug. It's reported as x (expected failure). If it starts passing, it's reported as an unexpected success and the run fails, which reminds you to remove the marker once the bug is fixed.

Example

import sys, unittest

class TestPlatform(unittest.TestCase):
    @unittest.skipIf(sys.platform == "win32", "uses POSIX paths")
    def test_posix_path(self):
        self.assertTrue("/tmp".startswith("/"))

    @unittest.skipUnless(sys.version_info >= (4, 0), "needs Python 4")
    def test_future(self):
        pass

    @unittest.expectedFailure
    def test_known_bug(self):
        self.assertEqual(round(2.675, 2), 2.68)   # float repr: gives 2.67

    def test_runtime_skip(self):
        self.skipTest("service not reachable")

unittest.main(exit=False, argv=["x"])
# sx.s  (alphabetical: future, known_bug, posix_path, runtime_skip)
# Ran 4 tests ... OK (skipped=2, expected failures=1)

Remember

  • skip, skipIf, skipUnless decorate methods or classes
  • self.skipTest() skips from inside a test
  • expectedFailure turns an unexpected pass into a failing run

Watch out for

  • Skipping without a reason, leaving future readers guessing why.

Check yourself

  1. A test marked @expectedFailure starts passing. What is the overall result?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/unittest.html#skipping-tests-and-expected-failures