improve docs further, refine unittest docs, rename ``autoactive`` to ``autouse``

to better match ``@pytest.mark.usefixtures`` naming.
This commit is contained in:
holger krekel 2012-10-12 14:52:36 +02:00
parent 6eec2f5893
commit f5d796b093
17 changed files with 255 additions and 197 deletions

View File

@ -1,2 +1,2 @@
# #
__version__ = '2.3.0.dev22' __version__ = '2.3.0.dev23'

View File

@ -11,10 +11,10 @@ import _pytest
cutdir = py.path.local(_pytest.__file__).dirpath() cutdir = py.path.local(_pytest.__file__).dirpath()
class FixtureFunctionMarker: class FixtureFunctionMarker:
def __init__(self, scope, params, autoactive=False): def __init__(self, scope, params, autouse=False):
self.scope = scope self.scope = scope
self.params = params self.params = params
self.autoactive = autoactive self.autouse = autouse
def __call__(self, function): def __call__(self, function):
if inspect.isclass(function): if inspect.isclass(function):
@ -23,7 +23,7 @@ class FixtureFunctionMarker:
return function 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. """ (return a) decorator to mark a fixture factory function.
This decorator can be used (with or or without parameters) to define 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 invocations of the fixture function and all of the tests
using it. 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 can see it. If False (the default) then an explicit
reference is needed to activate the fixture. 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 # direct decoration
return FixtureFunctionMarker("function", params, autoactive)(scope) return FixtureFunctionMarker("function", params, autouse)(scope)
else: else:
return FixtureFunctionMarker(scope, params, autoactive=autoactive) return FixtureFunctionMarker(scope, params, autouse=autouse)
defaultfuncargprefixmarker = fixture() defaultfuncargprefixmarker = fixture()
@ -1490,7 +1490,7 @@ class FixtureManager:
unittest=unittest) unittest=unittest)
faclist = self.arg2fixturedeflist.setdefault(name, []) faclist = self.arg2fixturedeflist.setdefault(name, [])
faclist.append(fixturedef) faclist.append(fixturedef)
if marker.autoactive: if marker.autouse:
self._autofixtures.append(name) self._autofixtures.append(name)
try: try:
del self._defaultfixtures del self._defaultfixtures

View File

@ -4,6 +4,8 @@ The writing and reporting of assertions in tests
.. _`assertfeedback`: .. _`assertfeedback`:
.. _`assert with the assert statement`: .. _`assert with the assert statement`:
.. _`assert`:
Asserting with the ``assert`` statement Asserting with the ``assert`` statement
--------------------------------------------------------- ---------------------------------------------------------

View File

@ -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 functions to force a certain test outcome. Note that most often
you can rather use declarative marks, see :ref:`skipping`. you can rather use declarative marks, see :ref:`skipping`.
.. autofunction:: fail .. autofunction:: _pytest.runner.fail
.. autofunction:: skip .. autofunction:: _pytest.runner.skip
.. autofunction:: importorskip .. autofunction:: _pytest.runner.importorskip
.. autofunction:: xfail .. autofunction:: _pytest.skipping.xfail
.. autofunction:: exit .. autofunction:: _pytest.runner.exit
fixtures and requests fixtures and requests
----------------------------------------------------- -----------------------------------------------------
To mark a fixture function: To mark a fixture function:
.. autofunction:: fixture .. autofunction:: _pytest.python.fixture
Tutorial at :ref:`fixtures`. Tutorial at :ref:`fixtures`.

View File

@ -17,7 +17,7 @@
# #
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
# The short X.Y version. # The short X.Y version.
version = release = "2.3.0.dev20" version = release = "2.3.0.dev22"
import sys, os import sys, os

View File

@ -2,7 +2,7 @@
.. _fixtures: .. _fixtures:
.. _`fixture functions`: .. _`fixture functions`:
pytest fixtures: modular, explicit, scalable pytest fixtures: explicit, modular, scalable
======================================================== ========================================================
.. currentmodule:: _pytest.python .. 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 .. _`general purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition .. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition
pytest allows to create and use test fixtures in a modular and flexible The `general purpose of test fixtures`_ is to provide a fixed baseline
manner, offering dramatic improvements over the classic xUnit style of upon which tests can reliably and repeatedly execute. pytest-2.3 fixtures
setup/teardown functions. The `general purpose of test fixtures`_ offer dramatic improvements over the classic xUnit style of setup/teardown
is to provide a fixed baseline upon which tests can reliably functions:
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.
* 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`: .. _`funcargs`:
.. _`funcarg mechanism`: .. _`funcarg mechanism`:
@ -39,9 +47,10 @@ Fixtures as Function arguments (funcargs)
Test functions can receive fixture objects by naming them as an input Test functions can receive fixture objects by naming them as an input
argument. For each argument name, a fixture function with that name provides argument. For each argument name, a fixture function with that name provides
a fixture object. Fixture functions are registered by marking them with the fixture object. Fixture functions are registered by marking them with
:py:func:`pytest.fixture`. Let's look at a simple self-contained test :py:func:`@pytest.fixture <pytest.fixture>`. Let's look at a simple
module containing a fixture and a test function using it:: self-contained test module containing a fixture and a test function
using it::
# content of ./test_smtpsimple.py # content of ./test_smtpsimple.py
import pytest import pytest
@ -111,10 +120,10 @@ with a list of available function arguments.
to see available fixtures. 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 and you had to use a magic ``pytest_funcarg__NAME`` prefix
for the fixture factory. This remains and will remain supported 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. functions.
Funcargs a prime example of dependency injection 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 functions take the role of the *injector* and test functions are the
*consumers* of fixture objects. *consumers* of fixture objects.
.. _smtpshared:
Working with a session-shared fixture 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 Fixtures requiring network access depend on connectivity and are
usually time-expensive to create. Extending the previous example, we usually time-expensive to create. Extending the previous example, we
can add a ``scope='session'`` parameter to the ``smtp`` fixture function can add a ``scope='session'`` parameter to ``@pytest.fixture`` decorator.
to cause it to only be invoked once per session. Multiple test to cause the decorated ``smtp`` fixture function to only be invoked once
functions will thus only involve a once-per-test session creation of the per test session. Multiple test functions will thus each receive the
fixture instance. Also, we now split the creation of the fixture into a same ``smtp`` fixture instance. The next example also extracts
``conftest.py`` file which will automatically loaded when running a test the fixture function into a separate ``conftest.py`` file so that
module:: all tests in the directory can access the fixture function::
# content of conftest.py # content of conftest.py
import pytest 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 traceback. As a result, the two test functions using ``smtp`` run as
quick as a single one because they reuse the same instance. quick as a single one because they reuse the same instance.
.. _`request-context`:
Fixtures can interact with the requesting test context Fixtures can interact with the requesting test context
------------------------------------------------------------- -------------------------------------------------------------
@ -275,7 +287,7 @@ Running it::
> assert 0, smtp.helo() > assert 0, smtp.helo()
E AssertionError: (250, 'hq.merlinux.eu') E AssertionError: (250, 'hq.merlinux.eu')
.. _`request`: :ref:pyclass:`_pytest.python.FixtureRequest` .. _`request`: :py:class:`_pytest.python.FixtureRequest`
.. _`fixture-parametrize`: .. _`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 write exhaustive functional tests for components which themselves can be
configured in multiple ways. configured in multiple ways.
Extending the previous example, we can flag the fixture to create Extending the previous example, we can flag the fixture to create two
two ``smtp`` fixture instances which will cause all tests using the ``smtp`` fixture instances which will cause all tests using the fixture
fixture to run twice. The fixture function gets to run twice. The fixture function gets access to each parameter
access to each parameter through the special `request`_ object:: through the special `request`_ object::
# content of conftest.py # content of conftest.py
import pytest import pytest
@ -565,9 +577,9 @@ into an ini-file::
usefixtures = cleandir usefixtures = cleandir
.. _`autoactive fixtures`: .. _`autouse fixtures`:
autoactive fixtures (xUnit setup on steroids) autouse fixtures (xUnit setup on steroids)
---------------------------------------------------------------------- ----------------------------------------------------------------------
.. regendoc:wipe .. regendoc:wipe
@ -596,7 +608,7 @@ self-contained implementation of this idea::
return DB() return DB()
class TestClass: class TestClass:
@pytest.fixture(autoactive=True) @pytest.fixture(autouse=True)
def transact(self, request, db): def transact(self, request, db):
db.begin(request.function.__name__) db.begin(request.function.__name__)
request.addfinalizer(db.rollback) request.addfinalizer(db.rollback)
@ -607,7 +619,7 @@ self-contained implementation of this idea::
def test_method2(self, db): def test_method2(self, db):
assert db.intransaction == ["test_method2"] 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 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 without a need to state it in the test function signature or with a
class-level ``usefixtures`` decorator. class-level ``usefixtures`` decorator.
@ -617,15 +629,15 @@ If we run it, we get two passing tests::
$ py.test -q $ 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. 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. 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 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 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 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 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 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 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 # content of conftest.py
@pytest.fixture() @pytest.fixture()

View File

@ -146,7 +146,7 @@ But it is then not possible to define scoping and parametrization.
It is thus recommended to use the factory decorator. 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 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 It follows that pytest_configure/session/runtest_setup are often not
appropriate for implementing common fixture needs. Therefore, 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>` integrate with the generic :ref:`fixture mechanism <fixture>`
and obsolete many prior uses of pytest hooks. and obsolete many prior uses of pytest hooks.

View File

@ -10,6 +10,7 @@ Installation and Getting Started
**documentation as PDF**: `download latest <http://pytest.org/latest/pytest.pdf>`_ **documentation as PDF**: `download latest <http://pytest.org/latest/pytest.pdf>`_
.. _`getstarted`: .. _`getstarted`:
.. _installation:
Installation Installation
---------------------------------------- ----------------------------------------

View File

@ -1,4 +1,5 @@
.. _features:
pytest: makes you write better programs pytest: makes you write better programs
============================================= =============================================

View File

@ -5,10 +5,12 @@ Running tests written for nose
py.test has basic support for running tests written for nose_. py.test has basic support for running tests written for nose_.
.. _nosestyle:
Usage Usage
------------- -------------
type:: After :ref:`installation` type::
py.test # instead of 'nosetests' py.test # instead of 'nosetests'

View File

@ -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 During development prior to the pytest-2.3 release the name
``pytest.setup`` was used but before the release it was renamed ``pytest.setup`` was used but before the release it was renamed
and moved to become part of the general fixture mechanism, and moved to become part of the general fixture mechanism,
namely :ref:`autoactive fixtures` namely :ref:`autouse fixtures`

View File

@ -1,5 +1,6 @@
.. _`tmpdir handling`: .. _`tmpdir handling`:
.. _tmpdir:
Temporary directories and files Temporary directories and files
================================================ ================================================

View File

@ -4,59 +4,141 @@
Support for unittest.TestCase / Integration of fixtures 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 .. _`unittest.py style`: http://docs.python.org/library/unittest.html
Moreover, you can use pytest's new :ref:`autoactive fixtures` py.test has support for running Python `unittest.py style`_ tests.
functions, thereby connecting pytest's :ref:`fixture mechanism <fixture>` It's meant for leveraging existing unittest-style projects
with a setup/teardown style:: 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 pytest
import unittest import unittest
class MyTest(unittest.TestCase): class MyTest(unittest.TestCase):
@pytest.fixture(autoactive=True) @pytest.fixture(autouse=True)
def chdir(self, tmpdir): def initdir(self, tmpdir):
tmpdir.chdir() # change to pytest-provided temporary directory tmpdir.chdir() # change to pytest-provided temporary directory
tmpdir.join("samplefile.ini").write("# testdata") tmpdir.join("samplefile.ini").write("# testdata")
@ -64,71 +146,28 @@ with a setup/teardown style::
s = open("samplefile.ini").read() s = open("samplefile.ini").read()
assert "testdata" in s assert "testdata" in s
Running this file should give us one passed test because the setup The ``initdir`` fixture function will be used for all methods of the
function took care to prepare a directory with some test data class where it is defined. This is basically just a shortcut for
which the unittest-testcase method can now use:: 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 ... gives us one passed test because the ``initdir`` fixture function
instances, you can do it using :ref:`usefixtures` and a simple was executed ahead of the ``test_method``.
:ref:`fixture function`::
# content of test_unittest_marked_db.py .. note::
import pytest
import unittest
@pytest.fixture ``unittest.TestCase`` methods cannot directly receive fixture or
def db(request): function arguments as implementing that is likely to inflict
class DummyDB: on the ability to run general unittest.TestCase test suites.
entries = [] Given enough demand, attempts might be made, though. If
db = DummyDB() unittest finally grows a reasonable plugin system that should
if request.instance is not None: help as well. In the meanwhile, the above ``usefixtures`` and
request.instance.db = db ``autouse`` examples should help to mix in pytest fixtures into
return db unittest suites.
@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
..

View File

@ -24,7 +24,7 @@ def main():
name='pytest', name='pytest',
description='py.test: simple powerful testing with Python', description='py.test: simple powerful testing with Python',
long_description = long_description, long_description = long_description,
version='2.3.0.dev22', version='2.3.0.dev23',
url='http://pytest.org', url='http://pytest.org',
license='MIT license', license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

View File

@ -28,7 +28,7 @@ def test_setup_func_with_setup_decorator():
from _pytest.nose import call_optional from _pytest.nose import call_optional
l = [] l = []
class A: class A:
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def f(self): def f(self):
l.append(1) l.append(1)
call_optional(A(), "f") call_optional(A(), "f")

View File

@ -767,7 +767,7 @@ class TestMarking:
def markers(request): def markers(request):
return request.node.markers return request.node.markers
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def marking(request): def marking(request):
request.applymarker(pytest.mark.XYZ("hello")) request.applymarker(pytest.mark.XYZ("hello"))
""") """)
@ -1975,14 +1975,14 @@ class TestSetupDiscovery:
def pytest_funcarg__testdir(self, testdir): def pytest_funcarg__testdir(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
import pytest import pytest
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def perfunction(request, tmpdir): def perfunction(request, tmpdir):
pass pass
@pytest.fixture() @pytest.fixture()
def arg1(tmpdir): def arg1(tmpdir):
pass pass
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def perfunction2(arg1): def perfunction2(arg1):
pass pass
@ -2008,7 +2008,7 @@ class TestSetupDiscovery:
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
class TestClass: class TestClass:
@pytest.fixture(autoactive=True) @pytest.fixture(autouse=True)
def permethod(self, request): def permethod(self, request):
request.instance.funcname = request.function.__name__ request.instance.funcname = request.function.__name__
def test_method1(self): def test_method1(self):
@ -2031,7 +2031,7 @@ class TestSetupDiscovery:
def db(request): def db(request):
return request.param return request.param
@pytest.fixture(enabled=enabled, autoactive=True) @pytest.fixture(enabled=enabled, autouse=True)
def createdb(db): def createdb(db):
pass pass
@ -2072,7 +2072,7 @@ class TestSetupManagement:
def arg(): def arg():
l.append(1) l.append(1)
return 0 return 0
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def something(arg): def something(arg):
l.append(2) l.append(2)
@ -2097,7 +2097,7 @@ class TestSetupManagement:
def arg(request): def arg(request):
return request.param return request.param
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def something(arg): def something(arg):
l.append(arg) l.append(arg)
@ -2123,7 +2123,7 @@ class TestSetupManagement:
def arg(request): def arg(request):
return request.param return request.param
@pytest.fixture(scope="function", autoactive=True) @pytest.fixture(scope="function", autouse=True)
def append(request, arg): def append(request, arg):
if request.function.__name__ == "test_some": if request.function.__name__ == "test_some":
l.append(arg) l.append(arg)
@ -2153,7 +2153,7 @@ class TestSetupManagement:
def carg(request): def carg(request):
return request.param return request.param
@pytest.fixture(scope="function", autoactive=True) @pytest.fixture(scope="function", autouse=True)
def append(request, farg, carg): def append(request, farg, carg):
def fin(): def fin():
l.append("fin_%s%s" % (carg, farg)) l.append("fin_%s%s" % (carg, farg))
@ -2179,13 +2179,13 @@ class TestSetupManagement:
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
l = [] l = []
@pytest.fixture(scope="function", autoactive=True) @pytest.fixture(scope="function", autouse=True)
def fappend2(): def fappend2():
l.append(2) l.append(2)
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def classappend3(): def classappend3():
l.append(3) l.append(3)
@pytest.fixture(scope="module", autoactive=True) @pytest.fixture(scope="module", autouse=True)
def mappend(): def mappend():
l.append(1) l.append(1)
@ -2205,7 +2205,7 @@ class TestSetupManagement:
if metafunc.cls is not None: if metafunc.cls is not None:
metafunc.parametrize("item", [1,2], scope="class") metafunc.parametrize("item", [1,2], scope="class")
class TestClass: class TestClass:
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def addteardown(self, item, request): def addteardown(self, item, request):
l.append("setup-%d" % item) l.append("setup-%d" % item)
request.addfinalizer(lambda: l.append("teardown-%d" % item)) request.addfinalizer(lambda: l.append("teardown-%d" % item))
@ -2482,7 +2482,7 @@ class TestFixtureMarker:
def carg(request): def carg(request):
return request.param return request.param
@pytest.fixture(scope="function", autoactive=True) @pytest.fixture(scope="function", autouse=True)
def append(request, farg, carg): def append(request, farg, carg):
def fin(): def fin():
l.append("fin_%s%s" % (carg, farg)) l.append("fin_%s%s" % (carg, farg))
@ -2620,7 +2620,7 @@ class TestFixtureMarker:
def arg(request): def arg(request):
return request.param return request.param
@pytest.fixture(scope="module", autoactive=True) @pytest.fixture(scope="module", autouse=True)
def mysetup(request, arg): def mysetup(request, arg):
request.addfinalizer(lambda: l.append("fin%s" % arg)) request.addfinalizer(lambda: l.append("fin%s" % arg))
l.append("setup%s" % arg) l.append("setup%s" % arg)
@ -2654,7 +2654,7 @@ class TestTestContextScopeAccess:
def test_setup(self, testdir, scope, ok, error): def test_setup(self, testdir, scope, ok, error):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
@pytest.fixture(scope=%r, autoactive=True) @pytest.fixture(scope=%r, autouse=True)
def myscoped(request): def myscoped(request):
for x in %r: for x in %r:
assert hasattr(request, x) assert hasattr(request, x)
@ -2709,7 +2709,7 @@ class TestErrors:
def test_setupfunc_missing_funcarg(self, testdir): def test_setupfunc_missing_funcarg(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def gen(qwe123): def gen(qwe123):
return 1 return 1
def test_something(): def test_something():
@ -2744,7 +2744,7 @@ class TestTestContextVarious:
def arg(request): def arg(request):
return request.param return request.param
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def mysetup(request, arg): def mysetup(request, arg):
assert not hasattr(request, "param") assert not hasattr(request, "param")
def test_1(arg): def test_1(arg):
@ -2757,10 +2757,10 @@ def test_setupdecorator_and_xunit(testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
l = [] l = []
@pytest.fixture(scope='module', autoactive=True) @pytest.fixture(scope='module', autouse=True)
def setup_module(): def setup_module():
l.append("module") l.append("module")
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def setup_function(): def setup_function():
l.append("function") l.append("function")
@ -2768,10 +2768,10 @@ def test_setupdecorator_and_xunit(testdir):
pass pass
class TestClass: class TestClass:
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def setup_class(self): def setup_class(self):
l.append("class") l.append("class")
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def setup_method(self): def setup_method(self):
l.append("method") l.append("method")
def test_method(self): def test_method(self):
@ -2790,7 +2790,7 @@ def test_setup_funcarg_order(testdir):
import pytest import pytest
l = [] l = []
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def fix1(): def fix1():
l.append(1) l.append(1)
@pytest.fixture() @pytest.fixture()
@ -2812,7 +2812,7 @@ def test_request_fixturenames(testdir):
@pytest.fixture() @pytest.fixture()
def farg(arg1): def farg(arg1):
pass pass
@pytest.fixture( autoactive=True) @pytest.fixture( autouse=True)
def sarg(tmpdir): def sarg(tmpdir):
pass pass
def test_function(request, farg): def test_function(request, farg):

View File

@ -497,10 +497,10 @@ def test_unittest_setup_interaction(testdir):
import unittest import unittest
import pytest import pytest
class MyTestCase(unittest.TestCase): class MyTestCase(unittest.TestCase):
@pytest.fixture(scope="class", autoactive=True) @pytest.fixture(scope="class", autouse=True)
def perclass(self, request): def perclass(self, request):
request.cls.hello = "world" request.cls.hello = "world"
@pytest.fixture(scope="function", autoactive=True) @pytest.fixture(scope="function", autouse=True)
def perfunction(self, request): def perfunction(self, request):
request.instance.funcname = request.function.__name__ request.instance.funcname = request.function.__name__