Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Comprehensive Guide to Python unittest Framework

Tools Apr 16 10

Initialization Methods

setUp and tearDown

These methods run before and after each test method. If you have multiple tests, setUp and tearDown execute multiple times, which can be resource-intensive.

setUpClass and tearDownClass

Recommended for one-time initialization of shared resources. These class methods run once per test class. Use the @classmethod decorator.

import unittest

class SearchEngineTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("Initializing test class...")
    
    @classmethod
    def tearDownClass(cls):
        print("Cleaning up test class...")
    
    def test_search_engine_a(self):
        print("Testing search engine A...")
    
    def test_search_engine_b(self):
        print("Testing search engine B...")

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

Verbosity Levels

unittest.main(verbosity=0/1/2) controls output detail:

  • Default is 1 (shows test count and overall result)
  • 0 provides minimal output
  • 2 shows detailed information

Test Execution Order

Sequential Execution with addTest

Tests execute in the order they're added to the test suite.

import unittest

class SearchEngineTest(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("Starting tests...")
    
    @classmethod
    def tearDownClass(cls):
        print("Tests completed...")
    
    def test_engine_a(self):
        print("Testing engine A...")
    
    def test_engine_b(self):
        print("Testing engine B...")

if __name__ == '__main__':
    test_suite = unittest.TestSuite()
    test_suite.addTest(SearchEngineTest('test_engine_b'))
    test_suite.addTest(SearchEngineTest('test_engine_a'))
    unittest.TextTestRunner(verbosity=2).run(test_suite)

Running Specific Test Classes

Execute tests from a single class when you have multiple classes but only need one.

import unittest

class SearchEngineTestA(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("Starting TestA...")
    
    @classmethod
    def tearDownClass(cls):
        print("Completed TestA...")
    
    def test_search_a(self):
        print("Testing search A...")

class SearchEngineTestB(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("Starting TestB...")
    
    @classmethod
    def tearDownClass(cls):
        print("Completed TestB...")
    
    def test_search_b(self):
        print("Testing search B...")

if __name__ == '__main__':
    # Method 1: Using makeSuite
    test_suite = unittest.TestSuite(unittest.makeSuite(SearchEngineTestB))
    
    # Method 2: Using TestLoader
    # test_suite = unittest.TestLoader().loadTestsFromTestCase(SearchEngineTestB)
    
    unittest.TextTestRunner(verbosity=2).run(test_suite)

Module-Level Test Execution

Run all tests in a module or directory for batch execution.

import unittest
import os

class SearchEngineTest(unittest.TestCase):
    def test_search_engine(self):
        print("Testing search engine...")

if __name__ == '__main__':
    # Define test directory
    current_dir = os.path.dirname(__file__)
    print(f"Test directory: {current_dir}")
    
    # Discover tests (supports regex patterns)
    # discover = unittest.defaultTestLoader.discover(current_dir, pattern='test*.py')
    discover = unittest.defaultTestLoader.discover(current_dir, pattern='search_test.py')
    
    runner = unittest.TextTestRunner(verbosity=2).run(discover)

Shared Initialization Module

Separate common setup code into a base class for reuse.

import unittest

class BaseTestSetup(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("Base setup: Initializing shared resources...")
    
    @classmethod
    def tearDownClass(cls):
        print("Base teardown: Cleaning up shared resources...")

class SearchEngineTest(BaseTestSetup):
    def test_search_functionality(self):
        print("Testing search functionality...")

Test Skipping

Skip tests conditionally or unconditionally.

import unittest

class SearchEngineTest(unittest.TestCase):
    def test_basic_search(self):
        print("Running basic search test...")
    
    @unittest.skip("Skipping this test case")
    def test_advanced_search(self):
        print("This test won't run...")
    
    @unittest.skipIf(1 != 2, "Skipping when condition is false")
    def test_conditional_search(self):
        print("This test runs only when condition is true...")

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

Assertiosn

Common assertion methods for test validation.

def test_search_assertions(self):
    # Equality assertions
    self.assertEqual(5, 5)           # Passes
    self.assertNotEqual(5, 6)        # Passes
    
    # Boolean assertions
    self.assertTrue(True)            # Passes
    self.assertFalse(False)          # Passes
    
    # Identity assertions
    a = [1, 2, 3]
    b = a
    self.assertIs(a, b)              # Passes (same object)
    self.assertIsNot(a, [1, 2, 3])   # Passes (different objects)
    
    # None assertions
    self.assertIsNone(None)          # Passes
    self.assertIsNotNone(5)          # Passes
    
    # Membership assertions
    self.assertIn(2, [1, 2, 3])      # Passes
    self.assertNotIn(4, [1, 2, 3])   # Passes

Note: When an assertion fails, subsequent assertions in the same test method won't execute.

Related Articles

Efficient Usage of HTTP Client in IntelliJ IDEA

IntelliJ IDEA incorporates a versatile HTTP client tool, enabling developres to interact with RESTful services and APIs effectively with in the editor. This functionality streamlines workflows, replac...

Installing CocoaPods on macOS Catalina (10.15) Using a User-Managed Ruby

System Ruby on macOS 10.15 frequently fails to build native gems required by CocoaPods (for example, ffi), leading to errors like: ERROR: Failed to build gem native extension checking for ffi.h... no...

Resolve PhpStorm "Interpreter is not specified or invalid" on WAMP (Windows)

Symptom PhpStorm displays: "Interpreter is not specified or invalid. Press ‘Fix’ to edit your project configuration." This occurs when the IDE cannot locate a valid PHP CLI executable or when the debu...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.