Skip unittests image

In this article you will learn how you can skip tests in unittest. This will not teach you the basics of unittest such as creating test classes and running tests, for that you can see the following article,

In some cases we may want some tests to be skipped. Unittest provides several ways of doing this:

  • Using skip decorators:
    • @unittest.skip()
    • @unittest.skipIf()
    • @unittest.skipUnless()
    • @unittest.expectedFailure
  • Using the inherited skipTest() method.
  • Raising the SkipTest exception.

Skip test methods using skip decorators

We can use the skip decorators to skip individual test methods.

skip unconditionally

The @unittest.skip() method skips the decorated test unconditionally. It has the following syntax:

@unittest.skip(reason)

Where reason is a required string stating why the test was skipped.

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      print("Running test 1")
      self.assertEqual(1 + 1, 2)

   @unittest.skip('we want to skip test 2')
   def test_2(self):
      print("Running test 2")

   def test_3(self):
      print("Running test 3")
      self.assertEqual(5 + 5,  10)

   @unittest.skip('we want to skip test 4.')
   def test_4(self):
      print("Running test 4")

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

Running test 1
.s
Running test 3
.s
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=2)

As you can see in the above example, the tests that we decorated with @unittest.skip() are skipped.  The skipped tests are denoted with a .s in the displayed message.

skip if

The @unittest.skipIf decorator allows us to skip a test only if a given condition evaluates to True. Its syntax is shown below:

@unittest.skipIf(condition, reason)

Both condition and reason are required arguments. The condition will be evaluated; if it evaluates to True the test is skipped, otherwise it is not.

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      print("Running test 1")
      self.assertEqual(1 + 1, 2)

   @unittest.skipIf(1 + 1 == 2, 'demonstrate skipIf')
   def test_2(self):
      print("Running test 2")

   def test_3(self):
      print("Running test 3")
      self.assertEqual(5 + 5,  10)

   @unittest.skipIf(1 + 1 == 3, 'demonstrate skipIf')
   def test_4(self):
      print("Running test 4")

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

Running test 1
.s
Running test 3
Running test 4
.
----------------------------------------------------------------------
Ran 4 tests in 0.001s

OK (skipped=1)

In the above example, we used @unittest.skipIf() decorator for both test_2 and test_4. However, only test_2 is skipped but test_4 is not. This is because the condition of test_2 evaluates to True but that of test_4 to False.

skip unless

With @unittest.skipUnless(), the decorated test method is skipped unless the condition evaluates to True. Practically, this decorator will skip a test where @unittest.skipIf will not given the same condition and vice verse. 

@skipUnless(condition, reason)

Consider the following example:

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      print("Running test 1")
      self.assertEqual(1 + 1, 2)

   @unittest.skipUnless(1 + 1 == 2, 'demonstrate skipIf')
   def test_2(self):
      print("Running test 2")

   def test_3(self):
      print("Running test 3")
      self.assertEqual(5 + 5,  10)

   @unittest.skipUnless(1 + 1 == 3, 'demonstrate skipIf')
   def test_4(self):
      print("Running test 4")

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

Running test 1
Running test 2
Running test 3
.s
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=1)

In the above case, test_4 whose condition evaluates to False is skipped, while test_2 whose condition is True is not skipped.

Expect a test to fail

We can use the @expectedFailure decorator to mark a test as an expected failure. When the decorated test fails when it is run, it is not counted as a failure.

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   @unittest.expectedFailure
   def test_2(self):
      self.assertEqual(2 + 2, 8)

   def test_3(self):
      self.assertEqual(3 + 3,  6)

   @unittest.expectedFailure
   def test_4(self):
      self.assertEqual(4 + 4, 6)

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

.x.x
----------------------------------------------------------------------
Ran 4 tests in 0.002s

OK (expected failures=2)

Note that if a test decorated with @expectedFailure passes, it will be considered an unexpected success and therefore a failure. Consider the following example:

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   @unittest.expectedFailure
   def test_2(self):
      self.assertEqual(2 + 2, 8)

   def test_3(self):
      self.assertEqual(3 + 3,  6)

   @unittest.expectedFailure
   def test_4(self):
      self.assertEqual(4 + 4, 8)

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

.x.u
======================================================================
UNEXPECTED SUCCESS: test_4 (__main__.TestExample.test_4)
----------------------------------------------------------------------
Ran 4 tests in 0.001s

FAILED (expected failures=1, unexpected successes=1)

In the above example, we decorated test_4 the @expectedFailure, however the assertion passed and it is therefore considered a failure.  

Skip an entire class with skip decorators

In the previous examples, we saw how we can skip individual test methods using @unittest.skip, @unittest.skipIf, @unittest.skipUnless and @unittest.expectedFailure.

It is also possible to use the decorators with an entire class. With this approach, the decorator will be applied to all test methods in the target class.

Consider the following example:

import unittest

@unittest.skipIf(1 < 2, "We want to skip all tests in this class")
class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   def test_2(self):
      self.assertEqual(2 + 2, 8)

   def test_3(self):
      self.assertEqual(3 + 3,  6)

   def test_4(self):
      self.assertEqual(4 + 4, 8)

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

ssss
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=4)

When we use the @expectedFailure decorator with the entire class, all test methods in that class will be expected to fail.

import unittest

@unittest.expectedFailure
class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   def test_2(self):
      self.assertEqual(2 + 2, 8)

   def test_3(self):
      self.assertEqual(3 + 3,  6)

   def test_4(self):
      self.assertEqual(4 + 4, 8)

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

uxuu
======================================================================
UNEXPECTED SUCCESS: test_1 (__main__.TestExample.test_1)
UNEXPECTED SUCCESS: test_3 (__main__.TestExample.test_3)
UNEXPECTED SUCCESS: test_4 (__main__.TestExample.test_4)
----------------------------------------------------------------------
Ran 4 tests in 0.002s

FAILED (expected failures=1, unexpected successes=3)

skip tests using the skipTest() method

In the previous approaches we saw how we can use the various unittest decorators to skip tests. It is also possible to skip tests inside a test method by calling skipTest() which is inherited from the unittest.TestCase class. 

import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   def test_2(self):
      self.skipTest('Not yet implemented')

   def test_3(self):
      self.assertEqual(3 + 3,  6)

   def test_4(self):
      self.skipTest('Not yet implemented')

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

.s.s
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=2) 

In the above example, we called the skipTest() method in test_2 and test_4.

skip tests by raising SkipTest exception

When we raise the unittest.SkipTest exception inside a test method, the exception will be captured and any subsequent statements in that method will be skipped. 

Its syntax is as shown below:

raise unittest.SkipTest
import unittest

class TestExample(unittest.TestCase):
   def test_1(self):
      self.assertEqual(1 + 1, 2)

   def test_2(self):
      raise unittest.SkipTest
   def test_3(self):
      self.assertEqual(3 + 3,  6)


   def test_4(self):
      raise unittest.SkipTest

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

.s.s
----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK (skipped=2) 

In the above example, we have raised the unittets.SkipTest exception in test_2 and test_4, as you can see in the output, the two tests were skipped.