Install & Compatibility
Where this runs
tested against v2.9.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.910 runs
installs and imports cleanly · install 0.0s · import 0.479s · 53.4MB
glibcpy 3.10–3.910 runs
installs and imports cleanly · install 3.0s · import 0.405s · 54MB
56MB installed
● package 56MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
TestCase
✓ from testtools import TestCase
text_content
✓ from testtools.content import text_content
✗ from testtools.details import text_content
Content details classes are in `testtools.content`, not `testtools.details`.
run
✓ from testtools.run import main as testtools_main
✗ import testtools.run
While `testtools.run` can be imported, it's typically used via its `main` function for direct execution, often aliased.
This quickstart demonstrates defining a test case using `testtools.TestCase`, adding custom details to test results for enhanced debugging, and explicitly skipping tests. It also shows how to invoke the `testtools` runner directly.
from testtools import TestCase
from testtools.content import text_content
from testtools.run import main as testtools_main
class MyTest(TestCase):
def test_example_success(self):
self.assertTrue(True, "This assertion should pass.")
def test_example_failure_with_detail(self):
# Add a custom detail to the test result for context on failure.
self.addDetail('debug-log', text_content("Detailed log entry from test execution."))
self.assertEqual(1, 2, "Expected 1 to equal 2, but it did not.")
def test_example_skip(self):
self.skipTest("This test is intentionally skipped as it's not relevant right now.")
if __name__ == '__main__':
# Run tests using the testtools runner.
# In larger projects, consider 'testrepository' or 'python -m testtools.run'
testtools_main()
Debug
Known issues
breakingtesttools versions 2.5.0 and later removed the dependency on and explicit references to `unittest2`. If your project implicitly relied on `unittest2` being present or imported from it, this change will cause import errors or behavioral differences.fixMigrate any `unittest2` imports or usage to the standard library's `unittest` module or the equivalent `testtools.TestCase` methods. Ensure your test runner is compatible with standard `unittest` modules.
affects: >=2.5.0
breakingWhen running on Python 3.12.1, `testtools` versions older than 2.7.2 may encounter issues due to a breaking API change within Python itself. `testtools` 2.7.2 includes a fix for this incompatibility.fixUpgrade `testtools` to version 2.7.2 or later to ensure compatibility with Python 3.12.1. If remaining on an older `testtools` version is necessary, avoid Python 3.12.1.
affects: <2.7.2 (when running on Python 3.12.1)
gotchaRecent versions of `testtools` (2.9.0 and later) require Python 3.10+. Attempting to install or run `testtools` on older Python environments will result in installation failures or runtime errors.fixEnsure your Python environment is 3.10 or newer. For projects requiring older Python versions, consult the PyPI page for `testtools` to find a compatible older `testtools` release.
affects: >=2.9.0 (when running on Python < 3.10)
deprecatedThe `distutils` integration within `testtools` was deprecated in version 2.6.0. While `distutils` itself is deprecated in Python, projects that relied on this specific `testtools` integration may need to update their build or test setup scripts.fixTransition to modern packaging tools like `setuptools` or `hatchling` (which `testtools` itself adopted in 2.8.0) and avoid direct reliance on `distutils` integration points provided by `testtools`.
affects: >=2.6.0
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'testtools'
The 'testtools' library is not installed in the current Python environment.
ImportError: cannot import name 'Matches' from 'testtools'
The 'Matches' class (and other matchers like 'Equals', 'DocTestMatches') is located in the 'testtools.matchers' submodule, not directly under the top-level 'testtools' package.
fixfrom testtools.matchers import Matches
AttributeError: 'TestCase' object has no attribute 'assertThat'
The test class inherits from `unittest.TestCase` instead of `testtools.TestCase`, which is required to use the `assertThat` method and its integrated matchers.
fixChange the base class of your test class from `unittest.TestCase` to `testtools.TestCase` (e.g., `class MyTest(testtools.TestCase):`).
Upgrade
Version history
2.9.1latest on PyPI · released Apr 24, 2026
Audit
Dependencies
twistedoptionalOptional dependency for Twisted framework integration.
fixturesoptionalOptional dependency for fixture support, an alternative to custom fixture objects.