Zope testing helpers
Zope.testing is a foundational Python package providing a suite of testing frameworks for Zope applications, supporting both doctest and unittest paradigms. It includes a flexible test runner (`zope.testrunner`), along with specialized utilities for test environment cleanup (`zope.testing.cleanup`), HTML form parsing for functional tests (`zope.testing.formparser`), robust logging support (`zope.testing.loggingsupport`), and streamlined setup/teardown automation (`zope.testing.setupstack`). The current version is 6.1, and its release cadence typically aligns with the broader Zope project, seeing updates roughly every 2-6 months.
Common errors
-
ImportError: No module named zope.testing
cause The `zope.testing` package is not installed in the current Python environment or the Python path is misconfigured.fixEnsure `zope.testing` is installed: `pip install zope.testing`. If using virtual environments, activate the correct environment. For buildout-based projects, ensure `zope.testing` is properly listed in `eggs`. -
Doctest output does not match expected output (especially with exceptions/prints)
cause In older versions, or when directly using `zope.testing.doctest`, if a doctest block included print statements immediately before raising an exception, the printed output might interfere with the expected output matching, leading to failure.fixReview the doctest example; if an exception is expected, ensure no extraneous `print` statements precede it in the test block. For modern usage, rely on the standard `doctest` module's behavior for output matching. -
zope-testrunner does not find tests
cause The `zope-testrunner` script was run without specifying the correct `--test-path` or the test files do not follow the expected naming convention (`test_*.py` in `tests/` subpackages or explicitly listed doctests).fixEnsure your test files are named `test_*.py` and located in a `tests/` subdirectory of your package. Run the test runner with `zope-testrunner --test-path=./path/to/your/package`. For doctests, ensure they are `.txt` files in `tests/` or explicitly referenced.
Warnings
- breaking Zope.testing 6.x and newer officially dropped support for Python 3.9. Ensure your environment uses Python 3.10 or later.
- breaking Starting with Zope 6.0 (which zope.testing aligns with), namespace package declarations switched from the older `pkg_resources` style to PEP 420 native implicit namespaces. This change may cause import issues in certain add-ons or complex package structures built with older tools like `zc.buildout` < 5.
- deprecated The `zope.testing.doctest` module is deprecated. The `zope.testrunner` has been modified since version 3.9.0 to use Python's standard `doctest` module. Directly importing `zope.testing.doctest` for new code is discouraged.
- breaking The `setup.py test` command, historically used to run tests, is no longer supported by modern `setuptools` versions and has been removed from `zope.testrunner` in version 8.2 and later.
Install
-
pip install zope.testing
Imports
- Runner
from zope.testing.testrunner.runner import Runner
- cleanup
from zope.testing.cleanup import cleanup
- InstalledHandler
from zope.testing.loggingsupport import InstalledHandler
- setupstack
import zope.testing.setupstack
- doctestcase
import zope.testing.doctestcase
- renormalizing
import zope.testing.renormalizing
Quickstart
import unittest
from zope.testing.testrunner.runner import Runner
class MyTests(unittest.TestCase):
def test_example(self):
self.assertTrue(True)
# To run tests programmatically, typically you'd use the command line script
# or a simple test discovery setup. The zope-testrunner script is often preferred.
# Example command line usage for a project with tests in 'my_package/tests/test_*.py':
# zope-testrunner --test-path=my_package --tests-pattern='^test_.*\.py$'
# Example of programmatic runner usage (advanced/specific scenarios):
# from unittest import TestSuite, makeSuite
# suite = TestSuite()
# suite.addTest(makeSuite(MyTests))
# runner = Runner(args=[], found_suites=[suite])
# succeeded = runner.run()
# if not succeeded:
# print("Tests failed!")