improve docs further, refine unittest docs, rename ``autoactive`` to ``autouse``
to better match ``@pytest.mark.usefixtures`` naming.
This commit is contained in:
parent
6eec2f5893
commit
f5d796b093
|
@ -1,2 +1,2 @@
|
|||
#
|
||||
__version__ = '2.3.0.dev22'
|
||||
__version__ = '2.3.0.dev23'
|
||||
|
|
|
@ -11,10 +11,10 @@ import _pytest
|
|||
cutdir = py.path.local(_pytest.__file__).dirpath()
|
||||
|
||||
class FixtureFunctionMarker:
|
||||
def __init__(self, scope, params, autoactive=False):
|
||||
def __init__(self, scope, params, autouse=False):
|
||||
self.scope = scope
|
||||
self.params = params
|
||||
self.autoactive = autoactive
|
||||
self.autouse = autouse
|
||||
|
||||
def __call__(self, function):
|
||||
if inspect.isclass(function):
|
||||
|
@ -23,7 +23,7 @@ class FixtureFunctionMarker:
|
|||
return function
|
||||
|
||||
|
||||
def fixture(scope="function", params=None, autoactive=False):
|
||||
def fixture(scope="function", params=None, autouse=False):
|
||||
""" (return a) decorator to mark a fixture factory function.
|
||||
|
||||
This decorator can be used (with or or without parameters) to define
|
||||
|
@ -41,15 +41,15 @@ def fixture(scope="function", params=None, autoactive=False):
|
|||
invocations of the fixture function and all of the tests
|
||||
using it.
|
||||
|
||||
:arg autoactive: if True, the fixture func is activated for all tests that
|
||||
:arg autouse: if True, the fixture func is activated for all tests that
|
||||
can see it. If False (the default) then an explicit
|
||||
reference is needed to activate the fixture.
|
||||
"""
|
||||
if py.builtin.callable(scope) and params is None and autoactive == False:
|
||||
if py.builtin.callable(scope) and params is None and autouse == False:
|
||||
# direct decoration
|
||||
return FixtureFunctionMarker("function", params, autoactive)(scope)
|
||||
return FixtureFunctionMarker("function", params, autouse)(scope)
|
||||
else:
|
||||
return FixtureFunctionMarker(scope, params, autoactive=autoactive)
|
||||
return FixtureFunctionMarker(scope, params, autouse=autouse)
|
||||
|
||||
defaultfuncargprefixmarker = fixture()
|
||||
|
||||
|
@ -1490,7 +1490,7 @@ class FixtureManager:
|
|||
unittest=unittest)
|
||||
faclist = self.arg2fixturedeflist.setdefault(name, [])
|
||||
faclist.append(fixturedef)
|
||||
if marker.autoactive:
|
||||
if marker.autouse:
|
||||
self._autofixtures.append(name)
|
||||
try:
|
||||
del self._defaultfixtures
|
||||
|
|
|
@ -4,6 +4,8 @@ The writing and reporting of assertions in tests
|
|||
|
||||
.. _`assertfeedback`:
|
||||
.. _`assert with the assert statement`:
|
||||
.. _`assert`:
|
||||
|
||||
|
||||
Asserting with the ``assert`` statement
|
||||
---------------------------------------------------------
|
||||
|
|
|
@ -42,18 +42,18 @@ You can use the following functions in your test, fixture or setup
|
|||
functions to force a certain test outcome. Note that most often
|
||||
you can rather use declarative marks, see :ref:`skipping`.
|
||||
|
||||
.. autofunction:: fail
|
||||
.. autofunction:: skip
|
||||
.. autofunction:: importorskip
|
||||
.. autofunction:: xfail
|
||||
.. autofunction:: exit
|
||||
.. autofunction:: _pytest.runner.fail
|
||||
.. autofunction:: _pytest.runner.skip
|
||||
.. autofunction:: _pytest.runner.importorskip
|
||||
.. autofunction:: _pytest.skipping.xfail
|
||||
.. autofunction:: _pytest.runner.exit
|
||||
|
||||
fixtures and requests
|
||||
-----------------------------------------------------
|
||||
|
||||
To mark a fixture function:
|
||||
|
||||
.. autofunction:: fixture
|
||||
.. autofunction:: _pytest.python.fixture
|
||||
|
||||
Tutorial at :ref:`fixtures`.
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# The short X.Y version.
|
||||
version = release = "2.3.0.dev20"
|
||||
version = release = "2.3.0.dev22"
|
||||
|
||||
import sys, os
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
.. _fixtures:
|
||||
.. _`fixture functions`:
|
||||
|
||||
pytest fixtures: modular, explicit, scalable
|
||||
pytest fixtures: explicit, modular, scalable
|
||||
========================================================
|
||||
|
||||
.. currentmodule:: _pytest.python
|
||||
|
@ -13,20 +13,28 @@ pytest fixtures: modular, explicit, scalable
|
|||
.. _`general purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
|
||||
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition
|
||||
|
||||
pytest allows to create and use test fixtures in a modular and flexible
|
||||
manner, offering dramatic improvements over the classic xUnit style of
|
||||
setup/teardown functions. The `general purpose of test fixtures`_
|
||||
is to provide a fixed baseline upon which tests can reliably
|
||||
and repeatedly execute. With pytest, fixtures have names and can be
|
||||
activated by referencing them from test functions, modules, classes or
|
||||
whole projects. Fixtures are implemented by *fixture functions* which
|
||||
have full access to the requesting test context and can use other
|
||||
fixtures, allowing a modular and flexible approach to organising
|
||||
and parametrizing fixtures for an application. Complemented by
|
||||
pytest's generic :ref:`parametrize features <parametrize>`, pytest
|
||||
fixtures help to write test suites that scale from simple to complex
|
||||
with minimal effort.
|
||||
The `general purpose of test fixtures`_ is to provide a fixed baseline
|
||||
upon which tests can reliably and repeatedly execute. pytest-2.3 fixtures
|
||||
offer dramatic improvements over the classic xUnit style of setup/teardown
|
||||
functions:
|
||||
|
||||
* fixtures have explicit names and are activated by declaring their use
|
||||
from test functions, modules, classes or whole projects.
|
||||
|
||||
* fixtures are implemented in a modular manner, as each fixture name
|
||||
triggers a *fixture function* which can itself easily use other
|
||||
fixtures.
|
||||
|
||||
* fixture management scales from simple unit to complex
|
||||
functional testing, allowing to parametrize fixtures or tests according
|
||||
to configuration and component options.
|
||||
|
||||
In addition to this next-generation (tm) style of organising test fixtures
|
||||
in Python, pytest continues to support :ref:`xunitsetup` which it
|
||||
originally introduced in 2005. You can mix both styles, moving
|
||||
incrementally from classic to new style, if you prefer. You can also
|
||||
start out from existing :ref:`unittest.TestCase style <unittest.TestCase>`
|
||||
or :ref:`nose based <nosestyle>` projects.
|
||||
|
||||
.. _`funcargs`:
|
||||
.. _`funcarg mechanism`:
|
||||
|
@ -39,9 +47,10 @@ Fixtures as Function arguments (funcargs)
|
|||
|
||||
Test functions can receive fixture objects by naming them as an input
|
||||
argument. For each argument name, a fixture function with that name provides
|
||||
a fixture object. Fixture functions are registered by marking them with
|
||||
:py:func:`pytest.fixture`. Let's look at a simple self-contained test
|
||||
module containing a fixture and a test function using it::
|
||||
the fixture object. Fixture functions are registered by marking them with
|
||||
:py:func:`@pytest.fixture <pytest.fixture>`. Let's look at a simple
|
||||
self-contained test module containing a fixture and a test function
|
||||
using it::
|
||||
|
||||
# content of ./test_smtpsimple.py
|
||||
import pytest
|
||||
|
@ -111,10 +120,10 @@ with a list of available function arguments.
|
|||
|
||||
to see available fixtures.
|
||||
|
||||
In versions prior to 2.3 there was no @pytest.fixture marker
|
||||
In versions prior to 2.3 there was no ``@pytest.fixture`` marker
|
||||
and you had to use a magic ``pytest_funcarg__NAME`` prefix
|
||||
for the fixture factory. This remains and will remain supported
|
||||
but is not advertised as the primary means of declaring fixture
|
||||
but is not anymore advertised as the primary means of declaring fixture
|
||||
functions.
|
||||
|
||||
Funcargs a prime example of dependency injection
|
||||
|
@ -134,6 +143,8 @@ details. It's a prime example of `dependency injection`_ where fixture
|
|||
functions take the role of the *injector* and test functions are the
|
||||
*consumers* of fixture objects.
|
||||
|
||||
.. _smtpshared:
|
||||
|
||||
Working with a session-shared fixture
|
||||
-----------------------------------------------------------------
|
||||
|
||||
|
@ -141,12 +152,12 @@ Working with a session-shared fixture
|
|||
|
||||
Fixtures requiring network access depend on connectivity and are
|
||||
usually time-expensive to create. Extending the previous example, we
|
||||
can add a ``scope='session'`` parameter to the ``smtp`` fixture function
|
||||
to cause it to only be invoked once per session. Multiple test
|
||||
functions will thus only involve a once-per-test session creation of the
|
||||
fixture instance. Also, we now split the creation of the fixture into a
|
||||
``conftest.py`` file which will automatically loaded when running a test
|
||||
module::
|
||||
can add a ``scope='session'`` parameter to ``@pytest.fixture`` decorator.
|
||||
to cause the decorated ``smtp`` fixture function to only be invoked once
|
||||
per test session. Multiple test functions will thus each receive the
|
||||
same ``smtp`` fixture instance. The next example also extracts
|
||||
the fixture function into a separate ``conftest.py`` file so that
|
||||
all tests in the directory can access the fixture function::
|
||||
|
||||
# content of conftest.py
|
||||
import pytest
|
||||
|
@ -215,6 +226,7 @@ test functions because pytest shows the incoming argument values in the
|
|||
traceback. As a result, the two test functions using ``smtp`` run as
|
||||
quick as a single one because they reuse the same instance.
|
||||
|
||||
.. _`request-context`:
|
||||
|
||||
Fixtures can interact with the requesting test context
|
||||
-------------------------------------------------------------
|
||||
|
@ -275,7 +287,7 @@ Running it::
|
|||
> assert 0, smtp.helo()
|
||||
E AssertionError: (250, 'hq.merlinux.eu')
|
||||
|
||||
.. _`request`: :ref:pyclass:`_pytest.python.FixtureRequest`
|
||||
.. _`request`: :py:class:`_pytest.python.FixtureRequest`
|
||||
|
||||
.. _`fixture-parametrize`:
|
||||
|
||||
|
@ -289,10 +301,10 @@ to be aware of their re-running. Fixture parametrization helps to
|
|||
write exhaustive functional tests for components which themselves can be
|
||||
configured in multiple ways.
|
||||
|
||||
Extending the previous example, we can flag the fixture to create
|
||||
two ``smtp`` fixture instances which will cause all tests using the
|
||||
fixture to run twice. The fixture function gets
|
||||
access to each parameter through the special `request`_ object::
|
||||
Extending the previous example, we can flag the fixture to create two
|
||||
``smtp`` fixture instances which will cause all tests using the fixture
|
||||
to run twice. The fixture function gets access to each parameter
|
||||
through the special `request`_ object::
|
||||
|
||||
# content of conftest.py
|
||||
import pytest
|
||||
|
@ -565,9 +577,9 @@ into an ini-file::
|
|||
usefixtures = cleandir
|
||||
|
||||
|
||||
.. _`autoactive fixtures`:
|
||||
.. _`autouse fixtures`:
|
||||
|
||||
autoactive fixtures (xUnit setup on steroids)
|
||||
autouse fixtures (xUnit setup on steroids)
|
||||
----------------------------------------------------------------------
|
||||
|
||||
.. regendoc:wipe
|
||||
|
@ -596,7 +608,7 @@ self-contained implementation of this idea::
|
|||
return DB()
|
||||
|
||||
class TestClass:
|
||||
@pytest.fixture(autoactive=True)
|
||||
@pytest.fixture(autouse=True)
|
||||
def transact(self, request, db):
|
||||
db.begin(request.function.__name__)
|
||||
request.addfinalizer(db.rollback)
|
||||
|
@ -607,7 +619,7 @@ self-contained implementation of this idea::
|
|||
def test_method2(self, db):
|
||||
assert db.intransaction == ["test_method2"]
|
||||
|
||||
The class-level ``transact`` fixture is marked with *autoactive=true*
|
||||
The class-level ``transact`` fixture is marked with *autouse=true*
|
||||
which implies that all test methods in the class will use this fixture
|
||||
without a need to state it in the test function signature or with a
|
||||
class-level ``usefixtures`` decorator.
|
||||
|
@ -617,15 +629,15 @@ If we run it, we get two passing tests::
|
|||
$ py.test -q
|
||||
..
|
||||
|
||||
Here is how autoactive fixtures work in other scopes:
|
||||
Here is how autouse fixtures work in other scopes:
|
||||
|
||||
- if an autoactive fixture is defined in a test module, all its test
|
||||
- if an autouse fixture is defined in a test module, all its test
|
||||
functions automatically use it.
|
||||
|
||||
- if an autoactive fixture is defined in a conftest.py file then all tests in
|
||||
- if an autouse fixture is defined in a conftest.py file then all tests in
|
||||
all test modules belows its directory will invoke the fixture.
|
||||
|
||||
- lastly, and **please use that with care**: if you define an autoactive
|
||||
- lastly, and **please use that with care**: if you define an autouse
|
||||
fixture in a plugin, it will be invoked for all tests in all projects
|
||||
where the plugin is installed. This can be useful if a fixture only
|
||||
anyway works in the presence of certain settings e. g. in the ini-file. Such
|
||||
|
@ -635,7 +647,7 @@ Here is how autoactive fixtures work in other scopes:
|
|||
Note that the above ``transact`` fixture may very well be a fixture that
|
||||
you want to make available in your project without having it generally
|
||||
active. The canonical way to do that is to put the transact definition
|
||||
into a conftest.py file **without** using ``autoactive``::
|
||||
into a conftest.py file **without** using ``autouse``::
|
||||
|
||||
# content of conftest.py
|
||||
@pytest.fixture()
|
||||
|
|
|
@ -146,7 +146,7 @@ But it is then not possible to define scoping and parametrization.
|
|||
It is thus recommended to use the factory decorator.
|
||||
|
||||
|
||||
solving per-session setup / autoactive fixtures
|
||||
solving per-session setup / autouse fixtures
|
||||
--------------------------------------------------------------
|
||||
|
||||
pytest for a long time offered a pytest_configure and a pytest_sessionstart
|
||||
|
@ -173,7 +173,7 @@ during test execution and parametrization happens at collection time.
|
|||
|
||||
It follows that pytest_configure/session/runtest_setup are often not
|
||||
appropriate for implementing common fixture needs. Therefore,
|
||||
pytest-2.3 introduces :ref:`autoactive fixtures` which fully
|
||||
pytest-2.3 introduces :ref:`autouse fixtures` which fully
|
||||
integrate with the generic :ref:`fixture mechanism <fixture>`
|
||||
and obsolete many prior uses of pytest hooks.
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ Installation and Getting Started
|
|||
**documentation as PDF**: `download latest <http://pytest.org/latest/pytest.pdf>`_
|
||||
|
||||
.. _`getstarted`:
|
||||
.. _installation:
|
||||
|
||||
Installation
|
||||
----------------------------------------
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
.. _features:
|
||||
|
||||
pytest: makes you write better programs
|
||||
=============================================
|
||||
|
|
|
@ -5,10 +5,12 @@ Running tests written for nose
|
|||
|
||||
py.test has basic support for running tests written for nose_.
|
||||
|
||||
.. _nosestyle:
|
||||
|
||||
Usage
|
||||
-------------
|
||||
|
||||
type::
|
||||
After :ref:`installation` type::
|
||||
|
||||
py.test # instead of 'nosetests'
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
setup: is now an "autoactive fixture"
|
||||
setup: is now an "autouse fixture"
|
||||
========================================================
|
||||
|
||||
During development prior to the pytest-2.3 release the name
|
||||
``pytest.setup`` was used but before the release it was renamed
|
||||
and moved to become part of the general fixture mechanism,
|
||||
namely :ref:`autoactive fixtures`
|
||||
namely :ref:`autouse fixtures`
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
.. _`tmpdir handling`:
|
||||
.. _tmpdir:
|
||||
|
||||
Temporary directories and files
|
||||
================================================
|
||||
|
|
|
@ -4,59 +4,141 @@
|
|||
Support for unittest.TestCase / Integration of fixtures
|
||||
=====================================================================
|
||||
|
||||
py.test has support for running Python `unittest.py style`_ tests.
|
||||
It will automatically collect ``unittest.TestCase`` subclasses
|
||||
and their ``test`` methods in test files. It will invoke
|
||||
``setUp/tearDown`` methods but also perform py.test's standard ways
|
||||
of treating tests such as IO capturing::
|
||||
|
||||
# content of test_unittest.py
|
||||
|
||||
import unittest
|
||||
class MyTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
print ("hello") # output is captured
|
||||
def test_method(self):
|
||||
x = 1
|
||||
self.assertEquals(x, 3)
|
||||
|
||||
Running it yields::
|
||||
|
||||
$ py.test test_unittest.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev20
|
||||
collected 1 items
|
||||
|
||||
test_unittest.py F
|
||||
|
||||
================================= FAILURES =================================
|
||||
____________________________ MyTest.test_method ____________________________
|
||||
|
||||
self = <test_unittest.MyTest testMethod=test_method>
|
||||
|
||||
def test_method(self):
|
||||
x = 1
|
||||
> self.assertEquals(x, 3)
|
||||
E AssertionError: 1 != 3
|
||||
|
||||
test_unittest.py:8: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
hello
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
|
||||
|
||||
Moreover, you can use pytest's new :ref:`autoactive fixtures`
|
||||
functions, thereby connecting pytest's :ref:`fixture mechanism <fixture>`
|
||||
with a setup/teardown style::
|
||||
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 typlical ``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.
|
||||
|
||||
# content of test_unittest_funcargs.py
|
||||
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. This way 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
|
||||
-----------------------------------------------------------
|
||||
|
||||
pytest supports using 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
|
||||
|
||||
# hooks and fixtures in this file are available throughout all test
|
||||
# modules living below the directory of this conftest.py file
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def db_class(request):
|
||||
class DummyDB:
|
||||
pass
|
||||
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. 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.0.dev22
|
||||
plugins: xdist, bugzilla, cache, oejskit, cli, pep8, cov, timeout
|
||||
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 0x135dea8>
|
||||
|
||||
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 0x135dea8>
|
||||
|
||||
test_unittest_db.py:12: AssertionError
|
||||
========================= 2 failed in 0.04 seconds =========================
|
||||
|
||||
This default pytest traceback shows that, indeed, the two test methods
|
||||
see the same ``self.db`` attribute instance which was our intention
|
||||
when writing the class-scoped fixture function.
|
||||
|
||||
|
||||
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. For this, 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 example which makes all test methods of a ``TestCase`` class
|
||||
execute in a clean temporary directory, using a ``initdir`` fixture
|
||||
which itself uses the pytest builtin ``tmpdir`` fixture::
|
||||
|
||||
# content of test_unittest_cleandir.py
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
class MyTest(unittest.TestCase):
|
||||
@pytest.fixture(autoactive=True)
|
||||
def chdir(self, tmpdir):
|
||||
@pytest.fixture(autouse=True)
|
||||
def initdir(self, tmpdir):
|
||||
tmpdir.chdir() # change to pytest-provided temporary directory
|
||||
tmpdir.join("samplefile.ini").write("# testdata")
|
||||
|
||||
|
@ -64,71 +146,28 @@ with a setup/teardown style::
|
|||
s = open("samplefile.ini").read()
|
||||
assert "testdata" in s
|
||||
|
||||
Running this file should give us one passed test because the setup
|
||||
function took care to prepare a directory with some test data
|
||||
which the unittest-testcase method can now use::
|
||||
The ``initdir`` fixture function will be used for all methods of the
|
||||
class where it is defined. This is basically just a shortcut for
|
||||
using a ``@pytest.mark.usefixtures("initdir")`` on the class like in
|
||||
the previous example. Note, that the ``initdir`` fixture function
|
||||
accepts a :ref:`tmpdir <tmpdir>` argument, referencing a pytest
|
||||
builtin fixture.
|
||||
|
||||
$ py.test -q test_unittest_funcargs.py
|
||||
Running this test module ...::
|
||||
|
||||
$ py.test -q test_unittest_cleandir.py
|
||||
.
|
||||
|
||||
If you want to make a database attribute available on unittest.TestCases
|
||||
instances, you can do it using :ref:`usefixtures` and a simple
|
||||
:ref:`fixture function`::
|
||||
... gives us one passed test because the ``initdir`` fixture function
|
||||
was executed ahead of the ``test_method``.
|
||||
|
||||
# content of test_unittest_marked_db.py
|
||||
import pytest
|
||||
import unittest
|
||||
.. note::
|
||||
|
||||
@pytest.fixture
|
||||
def db(request):
|
||||
class DummyDB:
|
||||
entries = []
|
||||
db = DummyDB()
|
||||
if request.instance is not None:
|
||||
request.instance.db = db
|
||||
return db
|
||||
|
||||
@pytest.mark.usefixtures("db")
|
||||
class MyTest(unittest.TestCase):
|
||||
def test_append(self):
|
||||
self.db.entries.append(1)
|
||||
|
||||
def test_method2(self):
|
||||
# check we have a fresh instance
|
||||
assert len(self.db.entries) == 0
|
||||
|
||||
Running it passes both tests::
|
||||
|
||||
$ py.test -q test_unittest_marked_db.py
|
||||
..
|
||||
|
||||
If you rather want to provide a class-cached "db" attribute, you
|
||||
can write a slightly different fixture using a ``scope`` parameter
|
||||
for the fixture decorator ::
|
||||
|
||||
# content of test_unittest_class_db.py
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def db_class(request):
|
||||
class DummyDB:
|
||||
entries = []
|
||||
db = DummyDB()
|
||||
if request.cls is not None:
|
||||
request.cls.db = db
|
||||
return db
|
||||
|
||||
@pytest.mark.usefixtures("db_class")
|
||||
class MyTest(unittest.TestCase):
|
||||
def test_append(self):
|
||||
self.db.entries.append(1)
|
||||
|
||||
def test_method2(self):
|
||||
# check we DONT have a fresh instance
|
||||
assert len(self.db.entries) == 1
|
||||
|
||||
Running it again passes both tests::
|
||||
|
||||
$ py.test -q test_unittest_class_db.py
|
||||
..
|
||||
``unittest.TestCase`` methods cannot directly receive fixture or
|
||||
function arguments as implementing that is likely to inflict
|
||||
on the ability to run general unittest.TestCase test suites.
|
||||
Given enough demand, attempts might be made, though. If
|
||||
unittest finally grows a reasonable 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.
|
||||
|
|
2
setup.py
2
setup.py
|
@ -24,7 +24,7 @@ def main():
|
|||
name='pytest',
|
||||
description='py.test: simple powerful testing with Python',
|
||||
long_description = long_description,
|
||||
version='2.3.0.dev22',
|
||||
version='2.3.0.dev23',
|
||||
url='http://pytest.org',
|
||||
license='MIT license',
|
||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||
|
|
|
@ -28,7 +28,7 @@ def test_setup_func_with_setup_decorator():
|
|||
from _pytest.nose import call_optional
|
||||
l = []
|
||||
class A:
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def f(self):
|
||||
l.append(1)
|
||||
call_optional(A(), "f")
|
||||
|
|
|
@ -767,7 +767,7 @@ class TestMarking:
|
|||
def markers(request):
|
||||
return request.node.markers
|
||||
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def marking(request):
|
||||
request.applymarker(pytest.mark.XYZ("hello"))
|
||||
""")
|
||||
|
@ -1975,14 +1975,14 @@ class TestSetupDiscovery:
|
|||
def pytest_funcarg__testdir(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
import pytest
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def perfunction(request, tmpdir):
|
||||
pass
|
||||
|
||||
@pytest.fixture()
|
||||
def arg1(tmpdir):
|
||||
pass
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def perfunction2(arg1):
|
||||
pass
|
||||
|
||||
|
@ -2008,7 +2008,7 @@ class TestSetupDiscovery:
|
|||
testdir.makepyfile("""
|
||||
import pytest
|
||||
class TestClass:
|
||||
@pytest.fixture(autoactive=True)
|
||||
@pytest.fixture(autouse=True)
|
||||
def permethod(self, request):
|
||||
request.instance.funcname = request.function.__name__
|
||||
def test_method1(self):
|
||||
|
@ -2031,7 +2031,7 @@ class TestSetupDiscovery:
|
|||
def db(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(enabled=enabled, autoactive=True)
|
||||
@pytest.fixture(enabled=enabled, autouse=True)
|
||||
def createdb(db):
|
||||
pass
|
||||
|
||||
|
@ -2072,7 +2072,7 @@ class TestSetupManagement:
|
|||
def arg():
|
||||
l.append(1)
|
||||
return 0
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def something(arg):
|
||||
l.append(2)
|
||||
|
||||
|
@ -2097,7 +2097,7 @@ class TestSetupManagement:
|
|||
def arg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def something(arg):
|
||||
l.append(arg)
|
||||
|
||||
|
@ -2123,7 +2123,7 @@ class TestSetupManagement:
|
|||
def arg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(scope="function", autoactive=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def append(request, arg):
|
||||
if request.function.__name__ == "test_some":
|
||||
l.append(arg)
|
||||
|
@ -2153,7 +2153,7 @@ class TestSetupManagement:
|
|||
def carg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(scope="function", autoactive=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def append(request, farg, carg):
|
||||
def fin():
|
||||
l.append("fin_%s%s" % (carg, farg))
|
||||
|
@ -2179,13 +2179,13 @@ class TestSetupManagement:
|
|||
testdir.makepyfile("""
|
||||
import pytest
|
||||
l = []
|
||||
@pytest.fixture(scope="function", autoactive=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def fappend2():
|
||||
l.append(2)
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def classappend3():
|
||||
l.append(3)
|
||||
@pytest.fixture(scope="module", autoactive=True)
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def mappend():
|
||||
l.append(1)
|
||||
|
||||
|
@ -2205,7 +2205,7 @@ class TestSetupManagement:
|
|||
if metafunc.cls is not None:
|
||||
metafunc.parametrize("item", [1,2], scope="class")
|
||||
class TestClass:
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def addteardown(self, item, request):
|
||||
l.append("setup-%d" % item)
|
||||
request.addfinalizer(lambda: l.append("teardown-%d" % item))
|
||||
|
@ -2482,7 +2482,7 @@ class TestFixtureMarker:
|
|||
def carg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(scope="function", autoactive=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def append(request, farg, carg):
|
||||
def fin():
|
||||
l.append("fin_%s%s" % (carg, farg))
|
||||
|
@ -2620,7 +2620,7 @@ class TestFixtureMarker:
|
|||
def arg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture(scope="module", autoactive=True)
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def mysetup(request, arg):
|
||||
request.addfinalizer(lambda: l.append("fin%s" % arg))
|
||||
l.append("setup%s" % arg)
|
||||
|
@ -2654,7 +2654,7 @@ class TestTestContextScopeAccess:
|
|||
def test_setup(self, testdir, scope, ok, error):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope=%r, autoactive=True)
|
||||
@pytest.fixture(scope=%r, autouse=True)
|
||||
def myscoped(request):
|
||||
for x in %r:
|
||||
assert hasattr(request, x)
|
||||
|
@ -2709,7 +2709,7 @@ class TestErrors:
|
|||
def test_setupfunc_missing_funcarg(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def gen(qwe123):
|
||||
return 1
|
||||
def test_something():
|
||||
|
@ -2744,7 +2744,7 @@ class TestTestContextVarious:
|
|||
def arg(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def mysetup(request, arg):
|
||||
assert not hasattr(request, "param")
|
||||
def test_1(arg):
|
||||
|
@ -2757,10 +2757,10 @@ def test_setupdecorator_and_xunit(testdir):
|
|||
testdir.makepyfile("""
|
||||
import pytest
|
||||
l = []
|
||||
@pytest.fixture(scope='module', autoactive=True)
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def setup_module():
|
||||
l.append("module")
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def setup_function():
|
||||
l.append("function")
|
||||
|
||||
|
@ -2768,10 +2768,10 @@ def test_setupdecorator_and_xunit(testdir):
|
|||
pass
|
||||
|
||||
class TestClass:
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def setup_class(self):
|
||||
l.append("class")
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def setup_method(self):
|
||||
l.append("method")
|
||||
def test_method(self):
|
||||
|
@ -2790,7 +2790,7 @@ def test_setup_funcarg_order(testdir):
|
|||
import pytest
|
||||
|
||||
l = []
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def fix1():
|
||||
l.append(1)
|
||||
@pytest.fixture()
|
||||
|
@ -2812,7 +2812,7 @@ def test_request_fixturenames(testdir):
|
|||
@pytest.fixture()
|
||||
def farg(arg1):
|
||||
pass
|
||||
@pytest.fixture( autoactive=True)
|
||||
@pytest.fixture( autouse=True)
|
||||
def sarg(tmpdir):
|
||||
pass
|
||||
def test_function(request, farg):
|
||||
|
|
|
@ -497,10 +497,10 @@ def test_unittest_setup_interaction(testdir):
|
|||
import unittest
|
||||
import pytest
|
||||
class MyTestCase(unittest.TestCase):
|
||||
@pytest.fixture(scope="class", autoactive=True)
|
||||
@pytest.fixture(scope="class", autouse=True)
|
||||
def perclass(self, request):
|
||||
request.cls.hello = "world"
|
||||
@pytest.fixture(scope="function", autoactive=True)
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def perfunction(self, request):
|
||||
request.instance.funcname = request.function.__name__
|
||||
|
||||
|
|
Loading…
Reference in New Issue