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.