
Support for unittest.TestCase / Integration of fixtures
*******************************************************

py.test has support for running Python unittest.py style tests. 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 test files.
It will invoke typical setup/teardown methods and generally try to
make test suites written to run on unittest, to also run using
"py.test".  We assume here that you are familiar with writing
"unittest.TestCase" style tests and rather focus on integration
aspects.


Usage
=====

After *Installation* type:

   py.test

and you should be able to run your unittest-style tests if they are
contained in "test_*" modules.  If that works for you then you can
make use of most *pytest features*, for example "--pdb" debugging in
failures, using *plain assert-statements*, *more informative
tracebacks*, stdout-capturing or distributing tests to multiple CPUs
via the "-nNUM" option if you installed the "pytest-xdist" plugin.
Please refer to the general pytest documentation for many more
examples.


Mixing pytest fixtures into unittest.TestCase style tests
=========================================================

Running your unittest with "py.test" allows you to use its *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:

   # 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 *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:

   # 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:

   $ py.test test_unittest_db.py
   =========================== test session starts ============================
   platform linux2 -- Python 2.7.3 -- pytest-2.3.5
   collected 2 items

   test_unittest_db.py FF

   ================================= FAILURES =================================
   ___________________________ MyTest.test_method1 ____________________________

   self = <test_unittest_db.MyTest testMethod=test_method1>

       def test_method1(self):
           assert hasattr(self, "db")
   >       assert 0, self.db   # fail for demo purposes
   E       AssertionError: <conftest.DummyDB instance at 0x19fdf38>

   test_unittest_db.py:9: AssertionError
   ___________________________ MyTest.test_method2 ____________________________

   self = <test_unittest_db.MyTest testMethod=test_method2>

       def test_method2(self):
   >       assert 0, self.db   # fail for demo purposes
   E       AssertionError: <conftest.DummyDB instance at 0x19fdf38>

   test_unittest_db.py:12: AssertionError
   ========================= 2 failed in 0.02 seconds =========================

This default pytest traceback shows that the two test methods share
the same "self.db" instance which was our intention when writing the
class-scoped fixture function above.


autouse fixtures and accessing other fixtures
=============================================

Although it's usually better to explicitely declare use of fixtures
you need for a given test, you may sometimes want to have fixtures
that are 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 *tmpdir* fixture to delegate the creation of a per-test
temporary directory:

   # content of test_unittest_cleandir.py
   import pytest
   import unittest

   class MyTest(unittest.TestCase):
       @pytest.fixture(autouse=True)
       def initdir(self, tmpdir):
           tmpdir.chdir() # change to pytest-provided temporary directory
           tmpdir.join("samplefile.ini").write("# testdata")

       def test_method(self):
           s = open("samplefile.ini").read()
           assert "testdata" in s

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 shortcut
for using a "@pytest.mark.usefixtures("initdir")" marker on the class
like in the previous example.

Running this test module ...:

   $ py.test -q test_unittest_cleandir.py
   .

... gives us one passed test because the "initdir" fixture function
was executed ahead of the "test_method".

Note: While pytest supports receiving fixtures via *test function
  arguments* for non-unittest test methods, "unittest.TestCase"
  methods cannot directly receive fixture function arguments as
  implementing that is likely to inflict on the ability to run general
  unittest.TestCase test suites. 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.
