diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /testing/web-platform/tests/tools/pytest/doc/en/unittest.rst | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'testing/web-platform/tests/tools/pytest/doc/en/unittest.rst')
-rw-r--r-- | testing/web-platform/tests/tools/pytest/doc/en/unittest.rst | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/testing/web-platform/tests/tools/pytest/doc/en/unittest.rst b/testing/web-platform/tests/tools/pytest/doc/en/unittest.rst new file mode 100644 index 000000000..ce99bd118 --- /dev/null +++ b/testing/web-platform/tests/tools/pytest/doc/en/unittest.rst @@ -0,0 +1,190 @@ + +.. _`unittest.TestCase`: + +Support for unittest.TestCase / Integration of fixtures +===================================================================== + +.. _`unittest.py style`: http://docs.python.org/library/unittest.html + +``pytest`` 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 ``pytest``. We assume here that you are familiar with writing +``unittest.TestCase`` style tests and rather focus on +integration aspects. + +Usage +------------------------------------------------------------------- + +After :ref:`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 :ref:`pytest features <features>`, for example +``--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 +the general ``pytest`` documentation for many more examples. + +Mixing pytest fixtures into unittest.TestCase style tests +----------------------------------------------------------- + +Running your unittest with ``pytest`` allows you to use its +: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:: + + # 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 <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 + + 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 linux -- Python 3.4.0, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 + rootdir: $REGENDOC_TMPDIR, inifile: + 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.db_class.<locals>.DummyDB object at 0xdeadbeef> + E assert 0 + + 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.db_class.<locals>.DummyDB object at 0xdeadbeef> + E assert 0 + + test_unittest_db.py:12: AssertionError + ======= 2 failed in 0.12 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 explicitly 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 :ref:`tmpdir <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 + . + 1 passed in 0.12 seconds + +... gives us one passed test because the ``initdir`` fixture function +was executed ahead of the ``test_method``. + +.. note:: + + While pytest supports receiving fixtures via :ref:`test function arguments <funcargs>` 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. + + +Converting from unittest to pytest +--------------------------------------- + +If you want to convert your unittest testcases to pytest, there are +some helpers like `unittest2pytest +<https://pypi.python.org/pypi/unittest2pytest/>`__, which uses lib2to3 +and introspection for the transformation. |