.. _`unittest.TestCase`: .. _`unittest`: How to use ``unittest``-based tests with pytest =============================================== ``pytest`` supports running Python ``unittest``-based tests out of the box. It's meant for leveraging existing ``unittest``-based test suites to use pytest as a test runner and also allow to incrementally adapt the test suite to take full advantage of pytest's features. To run an existing ``unittest``-style test suite using ``pytest``, type: .. code-block:: bash pytest tests pytest will automatically collect ``unittest.TestCase`` subclasses and their ``test`` methods in ``test_*.py`` or ``*_test.py`` files. Almost all ``unittest`` features are supported: * ``@unittest.skip`` style decorators; * ``setUp/tearDown``; * ``setUpClass/tearDownClass``; * ``setUpModule/tearDownModule``; .. _`pytest-subtests`: https://github.com/pytest-dev/pytest-subtests .. _`load_tests protocol`: https://docs.python.org/3/library/unittest.html#load-tests-protocol Additionally, :ref:`subtests ` are supported by the `pytest-subtests`_ plugin. Up to this point pytest does not have support for the following features: * `load_tests protocol`_; Benefits out of the box ----------------------- By running your test suite with pytest you can make use of several features, in most cases without having to modify existing code: * Obtain :ref:`more informative tracebacks `; * :ref:`stdout and stderr ` capturing; * :ref:`Test selection options ` using ``-k`` and ``-m`` flags; * :ref:`maxfail`; * :ref:`--pdb ` command-line option for debugging on test failures (see :ref:`note ` below); * Distribute tests to multiple CPUs using the :pypi:`pytest-xdist` plugin; * Use :ref:`plain assert-statements ` instead of ``self.assert*`` functions (:pypi:`unittest2pytest` is immensely helpful in this); pytest features in ``unittest.TestCase`` subclasses --------------------------------------------------- The following pytest features work in ``unittest.TestCase`` subclasses: * :ref:`Marks `: :ref:`skip `, :ref:`skipif `, :ref:`xfail `; * :ref:`Auto-use fixtures `; The following pytest features **do not** work, and probably never will due to different design philosophies: * :ref:`Fixtures ` (except for ``autouse`` fixtures, see :ref:`below `); * :ref:`Parametrization `; * :ref:`Custom hooks `; Third party plugins may or may not work well, depending on the plugin and the test suite. .. _mixing-fixtures: Mixing pytest fixtures into ``unittest.TestCase`` subclasses using marks ------------------------------------------------------------------------ Running your unittest with ``pytest`` allows you to use its :ref:`fixture mechanism ` with ``unittest.TestCase`` style tests. Assuming you have at least skimmed the pytest fixture features, let's jump-start into an example that integrates a pytest ``db_class`` fixture, setting up a class-cached database object, and then reference it from a unittest-style test: .. code-block:: python # content of conftest.py # we define a fixture function below and it will be "used" by # referencing its name from tests import pytest @pytest.fixture(scope="class") def db_class(request): class DummyDB: pass # set a class attribute on the invoking test context request.cls.db = DummyDB() This defines a fixture function ``db_class`` which - if used - is called once for each test class and which sets the class-level ``db`` attribute to a ``DummyDB`` instance. The fixture function achieves this by receiving a special ``request`` object which gives access to :ref:`the requesting test context ` such as the ``cls`` attribute, denoting the class from which the fixture is used. This architecture de-couples fixture writing from actual test code and allows re-use of the fixture by a minimal reference, the fixture name. So let's write an actual ``unittest.TestCase`` class using our fixture definition: .. code-block:: python # content of test_unittest_db.py import unittest import pytest @pytest.mark.usefixtures("db_class") class MyTest(unittest.TestCase): def test_method1(self): assert hasattr(self, "db") assert 0, self.db # fail for demo purposes def test_method2(self): assert 0, self.db # fail for demo purposes The ``@pytest.mark.usefixtures("db_class")`` class-decorator makes sure that the pytest fixture function ``db_class`` is called once per class. Due to the deliberately failing assert statements, we can take a look at the ``self.db`` values in the traceback: .. code-block:: pytest $ pytest test_unittest_db.py =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items test_unittest_db.py FF [100%] ================================= FAILURES ================================= ___________________________ MyTest.test_method1 ____________________________ self = def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef0001> E assert 0 test_unittest_db.py:11: AssertionError ___________________________ MyTest.test_method2 ____________________________ self = def test_method2(self): > assert 0, self.db # fail for demo purposes E AssertionError: .DummyDB object at 0xdeadbeef0001> E assert 0 test_unittest_db.py:14: AssertionError ========================= short test summary info ========================== FAILED test_unittest_db.py::MyTest::test_method1 - AssertionError: