unittest.py


Overview

The [unittest.py](/projects/286/67465) module provides pytest integration for tests written using Python’s standard library **unittest** framework. It enables pytest to **discover**, **collect**, **execute**, and **report** `unittest.TestCase`-style tests seamlessly alongside native pytest tests.

Key functionalities include:

This module is a crucial part of pytest’s **Integration with Other Test Frameworks**, allowing users to run legacy or mixed unittest tests in pytest with minimal friction while benefiting from pytest’s advanced features like fixtures, reporting, and debugging.


Classes and Functions

pytest_pycollect_makeitem(collector: Module | Class, name: str, obj: object) -> UnitTestCase | None

**Purpose:** Pytest collection hook to identify unittest test classes for collection.

**Parameters:**

**Returns:**

**Usage:** Called by pytest during collection to discover classes derived from `unittest.TestCase` that are not abstract and not explicitly skipped.


class UnitTestCase(Class)

A pytest collector representing a unittest test class. Inherits from pytest’s `Class`.

**Attributes:**

**Key Methods:**

**Usage Example:**

# During collection, pytest calls:
unit_test_case = UnitTestCase.from_parent(parent_collector, name="MyTestCase", obj=MyTestCase)
for test_item in unit_test_case.collect():
    # test_item is a TestCaseFunction representing a test method
    ...

class TestCaseFunction(Function)

Represents an individual unittest test method wrapped as a pytest `Function` test item.

**Attributes:**

**Key Methods:**

**Usage Example:**

test_func = TestCaseFunction.from_parent(unit_test_case, name="test_example")
test_func.runtest()  # Runs the unittest test method

@hookimpl(tryfirst=True)

pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None

Pytest hook to customize test report creation.


def _is_skipped(obj) -> bool

Helper function to check if a unittest test class or instance has been marked with `@unittest.skip`.

Returns `True` if the `__unittest_skip__` attribute is set on the object.


def pytest_configure() -> None

Pytest hook called on configuration stage.


class TwistedVersion(Enum)

Enumeration of Twisted framework versions for conditional compatibility logic.


def _get_twisted_version() -> TwistedVersion

Determines the installed Twisted version by inspecting `sys.modules` and querying package metadata.

Returns one of the `TwistedVersion` enum values.


@hookimpl(wrapper=True)

pytest_runtest_protocol(item: Item) -> Iterator[None]

A pytest hook wrapping the test run protocol.


def _handle_twisted_exc_info(rawexcinfo: _SysExcInfoType | BaseException) -> _SysExcInfoType

Converts Twisted Trial exception representations (`Failure` instances) into standard Python `sys.exc_info()` tuples for pytest compatibility.

Handles different Twisted versions and removes stored attributes to avoid memory leaks.


Implementation Details and Algorithms


Interaction with Other System Components


Visual Diagram: Class Structure and Key Methods

classDiagram
    class UnitTestCase {
        +nofuncargs: bool = True
        +newinstance()
        +collect() Iterable[Item | Collector]
        -_register_unittest_setup_class_fixture(cls: type)
        -_register_unittest_setup_method_fixture(cls: type)
    }

    class TestCaseFunction {
        +nofuncargs: bool = True
        -_excinfo: list[ExceptionInfo] | None
        +_getinstance()
        +setup()
        +teardown()
        +startTest(testcase)
        +addError(testcase, rawexcinfo)
        +addFailure(testcase, rawexcinfo)
        +addSkip(testcase, reason)
        +addExpectedFailure(testcase, rawexcinfo, reason="")
        +addUnexpectedSuccess(testcase, reason=None)
        +addSuccess(testcase)
        +stopTest(testcase)
        +addDuration(testcase, elapsed)
        +runtest()
        -_traceback_filter(excinfo)
    }

    UnitTestCase <|-- TestCaseFunction
    UnitTestCase ..> unittest.TestCase : wraps

Example Usage Snippet

# pytest invokes this hook during collection
def pytest_pycollect_makeitem(collector, name, obj):
    try:
        ut = sys.modules["unittest"]
        if not issubclass(obj, ut.TestCase):
            return None
    except Exception:
        return None
    if inspect.isabstract(obj):
        return None
    return UnitTestCase.from_parent(collector, name=name, obj=obj)

# UnitTestCase collects test methods
class UnitTestCase(Class):
    def collect(self):
        from unittest import TestLoader
        loader = TestLoader()
        for name in loader.getTestCaseNames(self.obj):
            yield TestCaseFunction.from_parent(self, name=name)

Summary

The [unittest.py](/projects/286/67465) module is a core component of pytest’s support for running unittest-based tests. It bridges the gap between the unittest and pytest worlds by:

This integration empowers users to run legacy unittest tests alongside pytest tests, leveraging pytest’s powerful features without rewriting existing test code.


End of Documentation for unittest.py