Fading Coder

One Final Commit for the Last Sprint

Home > Tools > Content

Comprehensive Guide to Python unittest Framework

Tools 2

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.