Ignoring broken tests

Sometimes, a test is known to fail, but we don't want the test suite to report the failure. This may be because a broken or unfinished feature has tests written, but we aren't currently focusing on improving it. More often, it happens because a feature is only available on a certain platform, Python version, or for advanced versions of a specific library. Python provides us with a few decorators to mark tests as expected to fail or to be skipped under known conditions.

These decorators are as follows:

These are applied using the Python decorator syntax. The first one accepts no arguments, and simply tells the test runner not to record the test as a failure when it fails. The skip method goes one step further and doesn't even bother to run the test. It expects a single string argument describing why the test was skipped. The other two decorators accept two arguments, one a Boolean expression that indicates whether or not the test should be run, and a similar description. In use, these three decorators might be applied as they are in the following code:

import unittest
import sys


class SkipTests(unittest.TestCase):
@unittest.expectedFailure
def test_fails(self):
self.assertEqual(False, True)

@unittest.skip("Test is useless")
def test_skip(self):
self.assertEqual(False, True)

@unittest.skipIf(sys.version_info.minor == 4, "broken on 3.4")
def test_skipif(self):
self.assertEqual(False, True)

@unittest.skipUnless(
sys.platform.startswith("linux"), "broken unless on linux"
)
def test_skipunless(self):
self.assertEqual(False, True)


if __name__ == "__main__":
unittest.main()

The first test fails, but it is reported as an expected failure; the second test is never run. The other two tests may or may not be run depending on the current Python version and operating system. On my Linux system, running Python 3.7, the output looks as follows:

xssF
======================================================================
FAIL: test_skipunless (__main__.SkipTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_skipping.py", line 22, in test_skipunless
self.assertEqual(False, True)
AssertionError: False != True

----------------------------------------------------------------------
Ran 4 tests in 0.001s

FAILED (failures=1, skipped=2, expected failures=1)

The x on the first line indicates an expected failure; the two s characters represent skipped tests, and the F indicates a real failure, since the conditional to skipUnless was True on my system.