Skip to main content

Add a short description here

Project description

unittest-observability

This is a Python project for unittest observability.

Features

This library provides several mixins to enhance unittest with observability features:

  • TimingMixin: Integrates with unittest.TestCase to automatically measure and report the execution time of each test method. It now uses time.monotonic() for more accurate duration measurements, helping in identifying slow tests and performance bottlenecks. Its proxy methods (timing_class_setup, timing_class_teardown, timing_method_setup, timing_method_teardown) now return detailed timing information or explanatory strings.
  • InventoryMixin: Designed for unittest.TestCase, this mixin now discovers all test_* methods within a class during setUpClass. In tearDownClass, it reports on the total number of tests discovered, how many actually ran, and identifies any tests that were skipped or not executed. This provides a comprehensive inventory and helps diagnose missing or skipped tests. Its proxy methods (inventory_class_setup, inventory_class_teardown, inventory_method_setup, inventory_method_teardown) now return inventory statistics or explanatory strings.
  • ResultMixin: Extends unittest.TestResult to gather detailed information about the outcome of each test, including success, failure, errors, skips, and execution duration. It also uses time.monotonic() for precise duration tracking and provides full tracebacks for issues. This provides a rich dataset for analysis and reporting.

Usage

TimingMixin and InventoryMixin

To use TimingMixin or InventoryMixin, simply inherit from them in your unittest.TestCase classes. It's recommended to place unittest.TestCase first in the inheritance list for conventional Method Resolution Order (MRO).

Important: The mixins provide proxy methods that must be explicitly called within your unittest.TestCase's setUpClass, tearDownClass, setUp, and tearDown methods to enable their functionality. Remember to call super().setUpClass()/super().setUp() first in your setup methods, and super().tearDownClass()/super().tearDown() last in your teardown methods.

import unittest
from unittest_observability import TimingMixin, InventoryMixin

class MyTests(unittest.TestCase, TimingMixin, InventoryMixin): # Updated inheritance order
    @classmethod
    def setUpClass(cls):
        super().setUpClass() # Call parent setUpClass first
        cls.inventory_class_setup() # Initialize InventoryMixin for the class
        cls.timing_class_setup()    # Initialize TimingMixin for the class

    @classmethod
    def tearDownClass(cls):
        # Call mixin teardown methods to get results before parent tearDownClass
        inventory_stats = cls.inventory_class_teardown()
        timing_stats = cls.timing_class_teardown()
        
        print(f"Class Inventory Stats: {inventory_stats}")
        print(f"Class Timing Stats: {timing_stats}")
        
        super().tearDownClass() # Call parent tearDownClass last

    def setUp(self):
        super().setUp() # Call parent setUp first
        self.inventory_method_setup() # Initialize InventoryMixin for the method
        self.timing_method_setup()    # Initialize TimingMixin for the method

    def tearDown(self):
        # Call mixin teardown methods to get results before parent tearDown
        method_inventory = self.inventory_method_teardown()
        method_timing = self.timing_method_teardown()
        
        print(f"Method Inventory: {method_inventory}")
        print(f"Method Timing: {method_timing}")
        
        super().tearDown() # Call parent tearDown last

    def test_example(self):
        # Your test code
        self.assertTrue(True)

# To access inventory (after tests have run):
# expected_inventory = MyTests.get_expected_inventory()
# ran_inventory = MyTests.get_test_inventory()

The proxy methods (timing_class_setup, timing_class_teardown, etc.) now return data (strings, lists, or dictionaries) which you can capture and process as needed, rather than just printing to sys.stdout.

ResultMixin

ResultMixin extends unittest.TestResult and is designed to be used with a unittest.TextTestRunner (or similar test runner) by passing it as the resultclass argument. This allows it to collect detailed results from all tests run by the runner.

import unittest
from unittest_observability import ResultMixin

# Assuming you have a TestSuite or individual TestCases
suite = unittest.TestSuite()
# suite.addTest(...)

runner = unittest.TextTestRunner(resultclass=ResultMixin)
result = runner.run(suite)

# Access collected results
detailed_results = result.get_collected_results()
for test_info in detailed_results:
    print(test_info)

Development and Publishing

This project uses GitHub Actions for continuous integration and publishing. A workflow is configured to build and publish the package to TestPyPI on pushes to the main branch or when a new tag (e.g., v1.0.0) is created. The CI pipeline now also includes coverage measurement to ensure code quality. Ensure you have a TEST_PYPI_API_TOKEN GitHub Secret configured for publishing.

For local development, you can run tests with coverage using the provided batch script:

run_tests_with_coverage.bat

Changelog

See CHANGELOG.md for a history of changes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

unittest_observability-0.2.0.tar.gz (20.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

unittest_observability-0.2.0-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file unittest_observability-0.2.0.tar.gz.

File metadata

  • Download URL: unittest_observability-0.2.0.tar.gz
  • Upload date:
  • Size: 20.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for unittest_observability-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d1e03df8de7b0ff76ae3cd6f72d3f67ca5a67a664483514ce72519ea5e3bc889
MD5 ad20dd2888918de1e13de05eb18cfbf5
BLAKE2b-256 1f34d563bc5c67952f9cc3842a5335d23dca2db1b20d3ab53127d83a3879ea29

See more details on using hashes here.

Provenance

The following attestation bundles were made for unittest_observability-0.2.0.tar.gz:

Publisher: publish.yml on Eki23/unittest-observability

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file unittest_observability-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for unittest_observability-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 587525c5853abfb61467a332e04227a6a3c89db86c480cad4e6a21e863acfbb5
MD5 72c9041711f64d648203975f923fd9af
BLAKE2b-256 ed51630f41dfd4e12af0aa522b6a492aaed2678af66befb4a7e390f537b93acb

See more details on using hashes here.

Provenance

The following attestation bundles were made for unittest_observability-0.2.0-py3-none-any.whl:

Publisher: publish.yml on Eki23/unittest-observability

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page