2010-11-06 06:37:25 +08:00
.. _`unittest.TestCase`:
2016-08-23 10:35:41 +08:00
.. _`unittest`:
2010-11-06 06:37:25 +08:00
2012-10-07 19:06:17 +08:00
Support for unittest.TestCase / Integration of fixtures
2010-10-12 16:59:04 +08:00
=====================================================================
2012-10-12 20:52:36 +08:00
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
2014-01-18 19:31:33 +08:00
`` pytest `` has support for running Python `unittest.py style`_ tests.
2012-10-12 20:52:36 +08:00
It's meant for leveraging existing unittest-style projects
to use pytest features. Concretely, pytest will automatically
collect `` unittest.TestCase `` subclasses and their `` test `` methods in
2012-10-19 16:07:11 +08:00
test files. It will invoke typical setup/teardown methods and
2012-10-12 20:52:36 +08:00
generally try to make test suites written to run on unittest, to also
2014-01-18 19:31:33 +08:00
run using `` pytest `` . We assume here that you are familiar with writing
2012-10-12 20:52:36 +08:00
`` unittest.TestCase `` style tests and rather focus on
integration aspects.
2017-01-25 20:20:38 +08:00
Note that this is meant as a provisional way of running your test code
until you fully convert to pytest-style tests. To fully take advantage of
:ref: `fixtures <fixture>` , :ref: `parametrization <parametrize>` and
2017-01-25 20:44:07 +08:00
:ref: `hooks <writing-plugins>` you should convert (tools like `unittest2pytest
2017-01-25 20:20:38 +08:00
<https://pypi.python.org/pypi/unittest2pytest/> `__ are helpful).
Also, not all 3rd party pluging are expected to work best with
`` unittest.TestCase `` style tests.
2012-10-12 20:52:36 +08:00
Usage
-------------------------------------------------------------------
After :ref: `installation` type::
2016-06-21 22:16:57 +08:00
pytest
2012-10-12 20:52:36 +08:00
and you should be able to run your unittest-style tests if they
2012-10-19 16:07:11 +08:00
are contained in `` test_* `` modules. If that works for you then
you can make use of most :ref: `pytest features <features>` , for example
2012-10-12 20:52:36 +08:00
`` --pdb `` debugging in failures, using :ref: `plain assert-statements <assert>` ,
:ref: `more informative tracebacks <tbreportdemo>` , stdout-capturing or
distributing tests to multiple CPUs via the `` -nNUM `` option if you
installed the `` pytest-xdist `` plugin. Please refer to
2014-01-18 19:31:33 +08:00
the general `` pytest `` documentation for many more examples.
2012-10-12 20:52:36 +08:00
2016-09-01 04:33:47 +08:00
.. note ::
Running tests from `` unittest.TestCase `` subclasses with `` --pdb `` will
2016-09-01 04:46:40 +08:00
disable tearDown and cleanup methods for the case that an Exception
2016-09-01 04:33:47 +08:00
occurs. This allows proper post mortem debugging for all applications
2016-09-18 01:58:27 +08:00
which have significant logic in their tearDown machinery. However,
supporting this feature has the following side effect: If people
overwrite `` unittest.TestCase `` `` __call__ `` or `` run `` , they need to
to overwrite `` debug `` in the same way (this is also true for standard
unittest).
2016-09-01 04:33:47 +08:00
2012-10-12 20:52:36 +08:00
Mixing pytest fixtures into unittest.TestCase style tests
-----------------------------------------------------------
2014-01-18 19:31:33 +08:00
Running your unittest with `` pytest `` allows you to use its
2012-10-19 16:07:11 +08:00
:ref: `fixture mechanism <fixture>` 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::
2012-10-12 20:52:36 +08:00
# content of conftest.py
2012-10-19 16:07:11 +08:00
# we define a fixture function below and it will be "used" by
# referencing its name from tests
2012-10-12 20:52:36 +08:00
import pytest
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
@pytest.fixture(scope="class")
def db_class(request):
2017-02-17 02:41:51 +08:00
class DummyDB(object):
2012-10-12 20:52:36 +08:00
pass
2012-10-19 16:07:11 +08:00
# set a class attribute on the invoking test context
2012-10-12 20:52:36 +08:00
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 <request-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::
# content of test_unittest_db.py
2010-10-12 16:59:04 +08:00
import unittest
2012-10-12 20:52:36 +08:00
import pytest
@pytest.mark.usefixtures("db_class")
2010-10-12 16:59:04 +08:00
class MyTest(unittest.TestCase):
2012-10-12 20:52:36 +08:00
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
2012-10-19 16:07:11 +08:00
the pytest fixture function `` db_class `` is called once per class.
2012-10-18 18:24:50 +08:00
Due to the deliberately failing assert statements, we can take a look at
the `` self.db `` values in the traceback::
2010-10-12 16:59:04 +08:00
2016-06-21 22:16:57 +08:00
$ pytest test_unittest_db.py
2015-06-07 05:30:49 +08:00
======= test session starts ========
2017-05-13 04:17:40 +08:00
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
2017-03-14 06:41:20 +08:00
rootdir: $REGENDOC_TMPDIR, inifile:
2012-10-12 20:52:36 +08:00
collected 2 items
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
test_unittest_db.py FF
2010-10-12 16:59:04 +08:00
2015-06-07 05:30:49 +08:00
======= FAILURES ========
_______ MyTest.test_method1 ________
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
self = <test_unittest_db.MyTest testMethod=test_method1>
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
def test_method1(self):
assert hasattr(self, "db")
> assert 0, self.db # fail for demo purposes
2015-09-22 22:52:35 +08:00
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
2014-09-24 20:46:56 +08:00
E assert 0
2012-10-12 20:52:36 +08:00
test_unittest_db.py:9: AssertionError
2015-06-07 05:30:49 +08:00
_______ MyTest.test_method2 ________
2012-10-12 20:52:36 +08:00
self = <test_unittest_db.MyTest testMethod=test_method2>
def test_method2(self):
> assert 0, self.db # fail for demo purposes
2015-09-22 22:52:35 +08:00
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0xdeadbeef>
2014-09-24 20:46:56 +08:00
E assert 0
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
test_unittest_db.py:12: AssertionError
2015-06-07 05:30:49 +08:00
======= 2 failed in 0.12 seconds ========
2012-10-12 20:52:36 +08:00
2012-10-19 16:07:11 +08:00
This default pytest traceback shows that the two test methods
2012-10-18 18:24:50 +08:00
share the same `` self.db `` instance which was our intention
when writing the class-scoped fixture function above.
2010-10-12 16:59:04 +08:00
2012-10-12 20:52:36 +08:00
autouse fixtures and accessing other fixtures
-------------------------------------------------------------------
2012-09-18 16:54:12 +08:00
2015-11-28 14:46:45 +08:00
Although it's usually better to explicitly declare use of fixtures you need
2012-10-12 20:52:36 +08:00
for a given test, you may sometimes want to have fixtures that are
2012-10-19 16:07:11 +08:00
automatically used in a given context. After all, the traditional
style of unittest-setup mandates the use of this implicit fixture writing
and chances are, you are used to it or like it.
You can flag fixture functions with `` @pytest.fixture(autouse=True) ``
and define the fixture function in the context where you want it used.
Let's look at an `` initdir `` fixture which makes all test methods of a
`` TestCase `` class execute in a temporary directory with a
pre-initialized `` samplefile.ini `` . Our `` initdir `` fixture itself uses
the pytest builtin :ref: `tmpdir <tmpdir>` fixture to delegate the
creation of a per-test temporary directory::
2012-10-12 20:52:36 +08:00
# content of test_unittest_cleandir.py
2012-09-18 16:54:12 +08:00
import pytest
import unittest
class MyTest(unittest.TestCase):
2012-10-12 20:52:36 +08:00
@pytest.fixture(autouse=True)
def initdir(self, tmpdir):
2012-09-18 16:54:12 +08:00
tmpdir.chdir() # change to pytest-provided temporary directory
tmpdir.join("samplefile.ini").write("# testdata")
def test_method(self):
2017-05-16 07:25:53 +08:00
with open("samplefile.ini") as f:
s = f.read()
2012-09-18 16:54:12 +08:00
assert "testdata" in s
2012-10-18 18:24:50 +08:00
Due to the `` autouse `` flag the `` initdir `` fixture function will be
used for all methods of the class where it is defined. This is a
2012-10-19 16:07:11 +08:00
shortcut for using a `` @pytest.mark.usefixtures("initdir") `` marker
on the class like in the previous example.
2012-09-18 16:54:12 +08:00
2012-10-12 20:52:36 +08:00
Running this test module ...::
2012-09-18 16:54:12 +08:00
2016-06-21 22:16:57 +08:00
$ pytest -q test_unittest_cleandir.py
2012-10-12 20:52:36 +08:00
.
2017-05-13 04:17:40 +08:00
======= warnings summary ========
test_unittest_cleandir.py::MyTest::test_method
$REGENDOC_TMPDIR/test_unittest_cleandir.py:11: ResourceWarning: unclosed file <_io.TextIOWrapper name='samplefile.ini' mode='r' encoding='UTF-8'>
s = open("samplefile.ini").read()
-- Docs: http://doc.pytest.org/en/latest/warnings.html
1 passed, 1 warnings in 0.12 seconds
2012-10-07 19:06:17 +08:00
2012-10-12 20:52:36 +08:00
... gives us one passed test because the ``initdir`` fixture function
was executed ahead of the `` test_method `` .
2012-10-07 19:06:17 +08:00
2012-10-12 20:52:36 +08:00
.. note ::
2012-10-07 19:06:17 +08:00
2012-10-19 16:07:11 +08:00
While pytest supports receiving fixtures via :ref: `test function arguments <funcargs>` for non-unittest test methods, `` unittest.TestCase `` methods cannot directly receive fixture
2012-10-12 20:52:36 +08:00
function arguments as implementing that is likely to inflict
on the ability to run general unittest.TestCase test suites.
2012-10-19 16:07:11 +08:00
Maybe optional support would be possible, though. If unittest finally
grows a plugin system that should help as well. In the meanwhile, the
above `` usefixtures `` and `` autouse `` examples should help to mix in
pytest fixtures into unittest suites. And of course you can also start
to selectively leave away the `` unittest.TestCase `` subclassing, use
plain asserts and get the unlimited pytest feature set.