some doc refinements

This commit is contained in:
holger krekel 2012-10-20 09:52:03 +02:00
parent fae34ca5e3
commit 525b08bc5c
15 changed files with 144 additions and 121 deletions

View File

@ -12,7 +12,7 @@ PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
SITETARGET=dev
SITETARGET=latest
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest

View File

@ -78,7 +78,7 @@ of the failing function and hide the other one::
test_module.py:9: AssertionError
----------------------------- Captured stdout ------------------------------
setting up <function test_func2 at 0x2d98050>
setting up <function test_func2 at 0x2ff0050>
==================== 1 failed, 1 passed in 0.01 seconds ====================
Accessing captured output from a test function

View File

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

View File

@ -98,7 +98,7 @@ That's it, we can now run the test::
self._conftestpath2mod[conftestpath] = mod = conftestpath.pyimport()
File "/home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/py/_path/local.py", line 532, in pyimport
__import__(modname)
File "/tmp/doc-exec-286/conftest.py", line 2, in <module>
File "/tmp/doc-exec-408/conftest.py", line 2, in <module>
from .remoteinterpreter import RemoteInterpreter
ValueError: Attempted relative import in non-package
@ -185,7 +185,7 @@ Running it yields::
self._conftestpath2mod[conftestpath] = mod = conftestpath.pyimport()
File "/home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/py/_path/local.py", line 532, in pyimport
__import__(modname)
File "/tmp/doc-exec-286/conftest.py", line 2, in <module>
File "/tmp/doc-exec-408/conftest.py", line 2, in <module>
from myapp import MyApp
ImportError: No module named myapp

View File

@ -5,16 +5,22 @@ Usages and Examples
===========================================
Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
need more examples or have questions. Also take a look at the :ref:`comprehensive documentation <toc>` which contains many example snippets as well.
need more examples or have questions. Also take a look at the
:ref:`comprehensive documentation <toc>` which contains many example
snippets as well. Also, `pytest on stackoverflow.com
<http://stackoverflow.com/search?q=pytest>`_ often comes with example
answers.
Also, `pytest on stackoverflow.com <http://stackoverflow.com/search?q=pytest>`_
is a primary continously updated source of pytest questions and answers
which often contain examples. New Questions will usually be seen
by pytest users or developers.
For basic examples, see
.. note::
- :doc:`../getting-started` for basic introductory examples
- :ref:`assert` for basic assertion examples
- :ref:`fixtures` for basic fixture/setup examples
- :ref:`parametrize` for basic fixture/setup examples
- :doc:`../unittest` for basic unittest integration
- :doc:`../nose` for basic nosetests integration
see :doc:`../getting-started` for basic introductory examples
The following examples aim at various use cases you might encounter.
.. toctree::
:maxdepth: 2

View File

@ -32,7 +32,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
test_server.py:3: test_send_http PASSED
=================== 1 tests deselected by "-m 'webtest'" ===================
================== 1 passed, 1 deselected in 0.00 seconds ==================
================== 1 passed, 1 deselected in 0.01 seconds ==================
Or the inverse, running all tests except the webtest ones::
@ -239,7 +239,7 @@ and here is one that specifies exactly the environment needed::
test_someenv.py .
========================= 1 passed in 0.01 seconds =========================
========================= 1 passed in 0.00 seconds =========================
The ``--markers`` option always gives you a list of available markers::
@ -356,7 +356,7 @@ then you will see two test skipped and two executed tests as expected::
test_plat.py s.s.
========================= short test summary info ==========================
SKIP [2] /tmp/doc-exec-288/conftest.py:12: cannot run on platform linux2
SKIP [2] /tmp/doc-exec-410/conftest.py:12: cannot run on platform linux2
=================== 2 passed, 2 skipped in 0.01 seconds ====================

View File

@ -195,7 +195,7 @@ And then when we run the test::
================================= FAILURES =================================
_________________________ test_db_initialized[d2] __________________________
db = <conftest.DB2 instance at 0x2928878>
db = <conftest.DB2 instance at 0x2ae5878>
def test_db_initialized(db):
# a dummy test
@ -250,7 +250,7 @@ argument sets to use for each test function. Let's run it::
================================= FAILURES =================================
________________________ TestClass.test_equals[1-2] ________________________
self = <test_parametrize.TestClass instance at 0x18dd4d0>, a = 1, b = 2
self = <test_parametrize.TestClass instance at 0x1de24d0>, a = 1, b = 2
def test_equals(self, a, b):
> assert a == b

View File

@ -51,7 +51,7 @@ then the test collection looks like this::
<Function 'check_simple'>
<Function 'check_complex'>
============================= in 0.00 seconds =============================
============================= in 0.01 seconds =============================
Interpreting cmdline arguments as Python packages
-----------------------------------------------------

View File

@ -30,7 +30,7 @@ get on the terminal - we are working on that):
failure_demo.py:15: AssertionError
_________________________ TestFailing.test_simple __________________________
self = <failure_demo.TestFailing object at 0x2727750>
self = <failure_demo.TestFailing object at 0x23f57d0>
def test_simple(self):
def f():
@ -40,13 +40,13 @@ get on the terminal - we are working on that):
> assert f() == g()
E assert 42 == 43
E + where 42 = <function f at 0x26cf488>()
E + and 43 = <function g at 0x26cf500>()
E + where 42 = <function f at 0x239d488>()
E + and 43 = <function g at 0x239d500>()
failure_demo.py:28: AssertionError
____________________ TestFailing.test_simple_multiline _____________________
self = <failure_demo.TestFailing object at 0x27277d0>
self = <failure_demo.TestFailing object at 0x23f5850>
def test_simple_multiline(self):
otherfunc_multi(
@ -66,19 +66,19 @@ get on the terminal - we are working on that):
failure_demo.py:11: AssertionError
___________________________ TestFailing.test_not ___________________________
self = <failure_demo.TestFailing object at 0x2727890>
self = <failure_demo.TestFailing object at 0x23f5a90>
def test_not(self):
def f():
return 42
> assert not f()
E assert not 42
E + where 42 = <function f at 0x26cf7d0>()
E + where 42 = <function f at 0x239d7d0>()
failure_demo.py:38: AssertionError
_________________ TestSpecialisedExplanations.test_eq_text _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x2727c10>
self = <failure_demo.TestSpecialisedExplanations object at 0x23f5b90>
def test_eq_text(self):
> assert 'spam' == 'eggs'
@ -89,7 +89,7 @@ get on the terminal - we are working on that):
failure_demo.py:42: AssertionError
_____________ TestSpecialisedExplanations.test_eq_similar_text _____________
self = <failure_demo.TestSpecialisedExplanations object at 0x26d1110>
self = <failure_demo.TestSpecialisedExplanations object at 0x239f190>
def test_eq_similar_text(self):
> assert 'foo 1 bar' == 'foo 2 bar'
@ -102,7 +102,7 @@ get on the terminal - we are working on that):
failure_demo.py:45: AssertionError
____________ TestSpecialisedExplanations.test_eq_multiline_text ____________
self = <failure_demo.TestSpecialisedExplanations object at 0x26d1190>
self = <failure_demo.TestSpecialisedExplanations object at 0x239f210>
def test_eq_multiline_text(self):
> assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
@ -115,7 +115,7 @@ get on the terminal - we are working on that):
failure_demo.py:48: AssertionError
______________ TestSpecialisedExplanations.test_eq_long_text _______________
self = <failure_demo.TestSpecialisedExplanations object at 0x26d1090>
self = <failure_demo.TestSpecialisedExplanations object at 0x239f090>
def test_eq_long_text(self):
a = '1'*100 + 'a' + '2'*100
@ -132,7 +132,7 @@ get on the terminal - we are working on that):
failure_demo.py:53: AssertionError
_________ TestSpecialisedExplanations.test_eq_long_text_multiline __________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c7ed0>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395f10>
def test_eq_long_text_multiline(self):
a = '1\n'*100 + 'a' + '2\n'*100
@ -156,7 +156,7 @@ get on the terminal - we are working on that):
failure_demo.py:58: AssertionError
_________________ TestSpecialisedExplanations.test_eq_list _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c7190>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395210>
def test_eq_list(self):
> assert [0, 1, 2] == [0, 1, 3]
@ -166,7 +166,7 @@ get on the terminal - we are working on that):
failure_demo.py:61: AssertionError
______________ TestSpecialisedExplanations.test_eq_list_long _______________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c7410>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395490>
def test_eq_list_long(self):
a = [0]*100 + [1] + [3]*100
@ -178,7 +178,7 @@ get on the terminal - we are working on that):
failure_demo.py:66: AssertionError
_________________ TestSpecialisedExplanations.test_eq_dict _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c78d0>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395bd0>
def test_eq_dict(self):
> assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
@ -191,7 +191,7 @@ get on the terminal - we are working on that):
failure_demo.py:69: AssertionError
_________________ TestSpecialisedExplanations.test_eq_set __________________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c7690>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395710>
def test_eq_set(self):
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
@ -207,7 +207,7 @@ get on the terminal - we are working on that):
failure_demo.py:72: AssertionError
_____________ TestSpecialisedExplanations.test_eq_longer_list ______________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c7510>
self = <failure_demo.TestSpecialisedExplanations object at 0x2395590>
def test_eq_longer_list(self):
> assert [1,2] == [1,2,3]
@ -217,7 +217,7 @@ get on the terminal - we are working on that):
failure_demo.py:75: AssertionError
_________________ TestSpecialisedExplanations.test_in_list _________________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c3190>
self = <failure_demo.TestSpecialisedExplanations object at 0x2391050>
def test_in_list(self):
> assert 1 in [0, 2, 3, 4, 5]
@ -226,7 +226,7 @@ get on the terminal - we are working on that):
failure_demo.py:78: AssertionError
__________ TestSpecialisedExplanations.test_not_in_text_multiline __________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c3d10>
self = <failure_demo.TestSpecialisedExplanations object at 0x23919d0>
def test_not_in_text_multiline(self):
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
@ -244,7 +244,7 @@ get on the terminal - we are working on that):
failure_demo.py:82: AssertionError
___________ TestSpecialisedExplanations.test_not_in_text_single ____________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c3d50>
self = <failure_demo.TestSpecialisedExplanations object at 0x2391f50>
def test_not_in_text_single(self):
text = 'single foo line'
@ -257,7 +257,7 @@ get on the terminal - we are working on that):
failure_demo.py:86: AssertionError
_________ TestSpecialisedExplanations.test_not_in_text_single_long _________
self = <failure_demo.TestSpecialisedExplanations object at 0x26c3790>
self = <failure_demo.TestSpecialisedExplanations object at 0x2391810>
def test_not_in_text_single_long(self):
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
@ -270,7 +270,7 @@ get on the terminal - we are working on that):
failure_demo.py:90: AssertionError
______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
self = <failure_demo.TestSpecialisedExplanations object at 0x26c3150>
self = <failure_demo.TestSpecialisedExplanations object at 0x2391250>
def test_not_in_text_single_long_term(self):
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
@ -289,7 +289,7 @@ get on the terminal - we are working on that):
i = Foo()
> assert i.b == 2
E assert 1 == 2
E + where 1 = <failure_demo.Foo object at 0x26c3850>.b
E + where 1 = <failure_demo.Foo object at 0x23918d0>.b
failure_demo.py:101: AssertionError
_________________________ test_attribute_instance __________________________
@ -299,8 +299,8 @@ get on the terminal - we are working on that):
b = 1
> assert Foo().b == 2
E assert 1 == 2
E + where 1 = <failure_demo.Foo object at 0x26c39d0>.b
E + where <failure_demo.Foo object at 0x26c39d0> = <class 'failure_demo.Foo'>()
E + where 1 = <failure_demo.Foo object at 0x2391ed0>.b
E + where <failure_demo.Foo object at 0x2391ed0> = <class 'failure_demo.Foo'>()
failure_demo.py:107: AssertionError
__________________________ test_attribute_failure __________________________
@ -316,7 +316,7 @@ get on the terminal - we are working on that):
failure_demo.py:116:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <failure_demo.Foo object at 0x2890810>
self = <failure_demo.Foo object at 0x255e890>
def _get_b(self):
> raise Exception('Failed to get attrib')
@ -332,15 +332,15 @@ get on the terminal - we are working on that):
b = 2
> assert Foo().b == Bar().b
E assert 1 == 2
E + where 1 = <failure_demo.Foo object at 0x26c35d0>.b
E + where <failure_demo.Foo object at 0x26c35d0> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x26c3c50>.b
E + where <failure_demo.Bar object at 0x26c3c50> = <class 'failure_demo.Bar'>()
E + where 1 = <failure_demo.Foo object at 0x2391650>.b
E + where <failure_demo.Foo object at 0x2391650> = <class 'failure_demo.Foo'>()
E + and 2 = <failure_demo.Bar object at 0x2391cd0>.b
E + where <failure_demo.Bar object at 0x2391cd0> = <class 'failure_demo.Bar'>()
failure_demo.py:124: AssertionError
__________________________ TestRaises.test_raises __________________________
self = <failure_demo.TestRaises instance at 0x2738c68>
self = <failure_demo.TestRaises instance at 0x2406c68>
def test_raises(self):
s = 'qwe'
@ -355,7 +355,7 @@ get on the terminal - we are working on that):
<0-codegen /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:838>:1: ValueError
______________________ TestRaises.test_raises_doesnt _______________________
self = <failure_demo.TestRaises instance at 0x27413b0>
self = <failure_demo.TestRaises instance at 0x240f3b0>
def test_raises_doesnt(self):
> raises(IOError, "int('3')")
@ -364,7 +364,7 @@ get on the terminal - we are working on that):
failure_demo.py:136: Failed
__________________________ TestRaises.test_raise ___________________________
self = <failure_demo.TestRaises instance at 0x273a4d0>
self = <failure_demo.TestRaises instance at 0x24084d0>
def test_raise(self):
> raise ValueError("demo error")
@ -373,7 +373,7 @@ get on the terminal - we are working on that):
failure_demo.py:139: ValueError
________________________ TestRaises.test_tupleerror ________________________
self = <failure_demo.TestRaises instance at 0x272d248>
self = <failure_demo.TestRaises instance at 0x23fb248>
def test_tupleerror(self):
> a,b = [1]
@ -382,7 +382,7 @@ get on the terminal - we are working on that):
failure_demo.py:142: ValueError
______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
self = <failure_demo.TestRaises instance at 0x272df80>
self = <failure_demo.TestRaises instance at 0x23fbf80>
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
l = [1,2,3]
@ -395,7 +395,7 @@ get on the terminal - we are working on that):
l is [1, 2, 3]
________________________ TestRaises.test_some_error ________________________
self = <failure_demo.TestRaises instance at 0x272ed88>
self = <failure_demo.TestRaises instance at 0x23fcd88>
def test_some_error(self):
> if namenotexi:
@ -423,7 +423,7 @@ get on the terminal - we are working on that):
<2-codegen 'abc-123' /home/hpk/p/pytest/doc/en/example/assertion/failure_demo.py:162>:2: AssertionError
____________________ TestMoreErrors.test_complex_error _____________________
self = <failure_demo.TestMoreErrors instance at 0x2741758>
self = <failure_demo.TestMoreErrors instance at 0x240f758>
def test_complex_error(self):
def f():
@ -452,7 +452,7 @@ get on the terminal - we are working on that):
failure_demo.py:5: AssertionError
___________________ TestMoreErrors.test_z1_unpack_error ____________________
self = <failure_demo.TestMoreErrors instance at 0x2728d88>
self = <failure_demo.TestMoreErrors instance at 0x23f6d88>
def test_z1_unpack_error(self):
l = []
@ -462,7 +462,7 @@ get on the terminal - we are working on that):
failure_demo.py:179: ValueError
____________________ TestMoreErrors.test_z2_type_error _____________________
self = <failure_demo.TestMoreErrors instance at 0x272ab90>
self = <failure_demo.TestMoreErrors instance at 0x23f8b90>
def test_z2_type_error(self):
l = 3
@ -472,19 +472,19 @@ get on the terminal - we are working on that):
failure_demo.py:183: TypeError
______________________ TestMoreErrors.test_startswith ______________________
self = <failure_demo.TestMoreErrors instance at 0x272b998>
self = <failure_demo.TestMoreErrors instance at 0x23f9998>
def test_startswith(self):
s = "123"
g = "456"
> assert s.startswith(g)
E assert <built-in method startswith of str object at 0x2734ad0>('456')
E + where <built-in method startswith of str object at 0x2734ad0> = '123'.startswith
E assert <built-in method startswith of str object at 0x2402ad0>('456')
E + where <built-in method startswith of str object at 0x2402ad0> = '123'.startswith
failure_demo.py:188: AssertionError
__________________ TestMoreErrors.test_startswith_nested ___________________
self = <failure_demo.TestMoreErrors instance at 0x272a0e0>
self = <failure_demo.TestMoreErrors instance at 0x23f80e0>
def test_startswith_nested(self):
def f():
@ -492,15 +492,15 @@ get on the terminal - we are working on that):
def g():
return "456"
> assert f().startswith(g())
E assert <built-in method startswith of str object at 0x2734ad0>('456')
E + where <built-in method startswith of str object at 0x2734ad0> = '123'.startswith
E + where '123' = <function f at 0x27549b0>()
E + and '456' = <function g at 0x27488c0>()
E assert <built-in method startswith of str object at 0x2402ad0>('456')
E + where <built-in method startswith of str object at 0x2402ad0> = '123'.startswith
E + where '123' = <function f at 0x24229b0>()
E + and '456' = <function g at 0x24168c0>()
failure_demo.py:195: AssertionError
_____________________ TestMoreErrors.test_global_func ______________________
self = <failure_demo.TestMoreErrors instance at 0x273b7a0>
self = <failure_demo.TestMoreErrors instance at 0x24097a0>
def test_global_func(self):
> assert isinstance(globf(42), float)
@ -510,18 +510,18 @@ get on the terminal - we are working on that):
failure_demo.py:198: AssertionError
_______________________ TestMoreErrors.test_instance _______________________
self = <failure_demo.TestMoreErrors instance at 0x272dd88>
self = <failure_demo.TestMoreErrors instance at 0x23fbd88>
def test_instance(self):
self.x = 6*7
> assert self.x != 42
E assert 42 != 42
E + where 42 = <failure_demo.TestMoreErrors instance at 0x272dd88>.x
E + where 42 = <failure_demo.TestMoreErrors instance at 0x23fbd88>.x
failure_demo.py:202: AssertionError
_______________________ TestMoreErrors.test_compare ________________________
self = <failure_demo.TestMoreErrors instance at 0x2729560>
self = <failure_demo.TestMoreErrors instance at 0x23f7560>
def test_compare(self):
> assert globf(10) < 5
@ -531,7 +531,7 @@ get on the terminal - we are working on that):
failure_demo.py:205: AssertionError
_____________________ TestMoreErrors.test_try_finally ______________________
self = <failure_demo.TestMoreErrors instance at 0x271f3b0>
self = <failure_demo.TestMoreErrors instance at 0x23f2ef0>
def test_try_finally(self):
x = 1

View File

@ -155,7 +155,7 @@ and when running it will see a skipped "slow" test::
test_module.py .s
========================= short test summary info ==========================
SKIP [1] /tmp/doc-exec-293/conftest.py:9: need --runslow option to run
SKIP [1] /tmp/doc-exec-415/conftest.py:9: need --runslow option to run
=================== 1 passed, 1 skipped in 0.01 seconds ====================
@ -327,7 +327,7 @@ Now we can profile which test functions execute the slowest::
========================= slowest 3 test durations =========================
0.20s call test_some_are_slow.py::test_funcslow2
0.10s call test_some_are_slow.py::test_funcslow1
0.00s setup test_some_are_slow.py::test_funcfast
0.00s call test_some_are_slow.py::test_funcfast
========================= 3 passed in 0.31 seconds =========================
incremental testing - test steps
@ -388,7 +388,7 @@ If we run this::
================================= FAILURES =================================
____________________ TestUserHandling.test_modification ____________________
self = <test_step.TestUserHandling instance at 0x1db2638>
self = <test_step.TestUserHandling instance at 0x1e88638>
def test_modification(self):
> assert 0

View File

@ -26,8 +26,9 @@ functions:
fixtures.
* fixture management scales from simple unit to complex
functional testing, allowing to parametrize fixtures or tests according
to configuration and component options.
functional testing, allowing to parametrize fixtures and tests according
to configuration and component options, or to re-use fixtures
across class, module or whole test session scopes.
In addition, pytest continues to support :ref:`xunitsetup` which it
originally introduced in 2005. You can mix both styles, moving
@ -47,7 +48,7 @@ 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
the fixture object. Fixture functions are registered by marking them with
:py:func:`@pytest.fixture <pytest.fixture>`. Let's look at a simple
:py:func:`@pytest.fixture <_pytest.python.fixture>`. Let's look at a simple
self-contained test module containing a fixture and a test function
using it::
@ -66,8 +67,8 @@ using it::
assert 0 # for demo purposes
Here, the ``test_function`` needs the ``smtp`` fixture value. pytest
will discover and call the ``@pytest.fixture`` marked ``smtp``
fixture function. Running the test looks like this::
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
marked ``smtp`` fixture function. Running the test looks like this::
$ py.test test_smtpsimple.py
=========================== test session starts ============================
@ -79,7 +80,7 @@ fixture function. Running the test looks like this::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP instance at 0x1eade18>
smtp = <smtplib.SMTP instance at 0x23e1e18>
def test_ehlo(smtp):
response, msg = smtp.ehlo()
@ -89,7 +90,7 @@ fixture function. Running the test looks like this::
E assert 0
test_smtpsimple.py:12: AssertionError
========================= 1 failed in 0.20 seconds =========================
========================= 1 failed in 0.25 seconds =========================
In the failure traceback we see that the test function was called with a
``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
@ -143,25 +144,27 @@ functions take the role of the *injector* and test functions are the
.. _smtpshared:
Working with a session-shared fixture
Working with a module-shared fixture
-----------------------------------------------------------------
.. regendoc:wipe
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 ``@pytest.fixture`` decorator.
can add a ``scope='module'`` parameter to the
:py:func:`@pytest.fixture <_pytest.python.fixture>` invocation
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::
per test module. Multiple test functions in a test module 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 test modules in the directory can access the fixture
function::
# content of conftest.py
import pytest
import smtplib
@pytest.fixture(scope="session")
@pytest.fixture(scope="module")
def smtp():
return smtplib.SMTP("merlinux.eu")
@ -195,7 +198,7 @@ inspect what is going on and can now run the tests::
================================= FAILURES =================================
________________________________ test_ehlo _________________________________
smtp = <smtplib.SMTP instance at 0x29213b0>
smtp = <smtplib.SMTP instance at 0x24bf3b0>
def test_ehlo(smtp):
response = smtp.ehlo()
@ -207,7 +210,7 @@ inspect what is going on and can now run the tests::
test_module.py:6: AssertionError
________________________________ test_noop _________________________________
smtp = <smtplib.SMTP instance at 0x29213b0>
smtp = <smtplib.SMTP instance at 0x24bf3b0>
def test_noop(smtp):
response = smtp.noop()
@ -216,28 +219,39 @@ inspect what is going on and can now run the tests::
E assert 0
test_module.py:11: AssertionError
========================= 2 failed in 0.20 seconds =========================
========================= 2 failed in 0.17 seconds =========================
You see the two ``assert 0`` failing and more importantly you can also see
that the same (session-scoped) ``smtp`` object was passed into the two
that the same (module-scoped) ``smtp`` object was passed into the two
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.
If you decide that you rather want to have a session-scoped ``smtp``
instance, you can simply declare it::
@pytest.fixture(scope=``session``)
def smtp(...):
# the returned fixture value will be shared for
# all tests needing it
.. _`request-context`:
Fixtures can interact with the requesting test context
-------------------------------------------------------------
Using the special :py:class:`request <FixtureRequest>` argument,
fixture functions can introspect the function, class or module for which
they are invoked or can register finalizing (cleanup)
Fixture functions can themselves use other fixtures by naming
them as an input argument just like test functions do, see
:ref:`interdependent fixtures`. Moreover, pytest
provides a builtin :py:class:`request <FixtureRequest>` object,
which fixture functions can use to introspect the function, class or module
for which they are invoked or to register finalizing (cleanup)
functions which are called when the last test finished execution.
Further extending the previous ``smtp`` fixture example, let's try to
read the server URL from the module namespace, also use module-caching and
register a finalizer that closes the smtp connection after the last
test finished execution::
Further extending the previous ``smtp`` fixture example, let's
read an optional server URL from the module namespace and register
a finalizer that closes the smtp connection after the last
test in a module finished execution::
# content of conftest.py
import pytest
@ -258,12 +272,12 @@ using it has executed::
$ py.test -s -q --tb=no
FF
finalizing <smtplib.SMTP instance at 0x1a9d5a8>
finalizing <smtplib.SMTP instance at 0x125f5a8>
We see that the ``smtp`` instance is finalized after the two
tests using it tests executed. If we had specified ``scope='function'``
then fixture setup and cleanup would occur around each single test.
Note that the test module itself did not need to change!
Note that either case the test module itself does not need to change!
Let's quickly create another test module that actually sets the
server URL and has a test to verify the fixture picks it up::
@ -289,7 +303,7 @@ Running it::
.. _`fixture-parametrize`:
Parametrizing a session-shared fixture
Parametrizing a fixture
-----------------------------------------------------------------
Fixture functions can be parametrized in which case they will be called
@ -308,7 +322,7 @@ through the special `request`_ object::
import pytest
import smtplib
@pytest.fixture(scope="session",
@pytest.fixture(scope="module",
params=["merlinux.eu", "mail.python.org"])
def smtp(request):
smtp = smtplib.SMTP(request.param)
@ -318,7 +332,8 @@ through the special `request`_ object::
request.addfinalizer(fin)
return smtp
The main change is the declaration of ``params``, a list of values
The main change is the declaration of ``params`` with
:py:func:`@pytest.fixture <_pytest.python.fixture>`, a list of values
for each of which the fixture function will execute and can access
a value via ``request.param``. No test function code needs to change.
So let's just do another run::
@ -328,7 +343,7 @@ So let's just do another run::
================================= FAILURES =================================
__________________________ test_ehlo[merlinux.eu] __________________________
smtp = <smtplib.SMTP instance at 0x1eae680>
smtp = <smtplib.SMTP instance at 0x2fc2680>
def test_ehlo(smtp):
response = smtp.ehlo()
@ -340,7 +355,7 @@ So let's just do another run::
test_module.py:6: AssertionError
__________________________ test_noop[merlinux.eu] __________________________
smtp = <smtplib.SMTP instance at 0x1eae680>
smtp = <smtplib.SMTP instance at 0x2fc2680>
def test_noop(smtp):
response = smtp.noop()
@ -351,7 +366,7 @@ So let's just do another run::
test_module.py:11: AssertionError
________________________ test_ehlo[mail.python.org] ________________________
smtp = <smtplib.SMTP instance at 0x1eb7fc8>
smtp = <smtplib.SMTP instance at 0x2fcbfc8>
def test_ehlo(smtp):
response = smtp.ehlo()
@ -362,7 +377,7 @@ So let's just do another run::
test_module.py:5: AssertionError
________________________ test_noop[mail.python.org] ________________________
smtp = <smtplib.SMTP instance at 0x1eb7fc8>
smtp = <smtplib.SMTP instance at 0x2fcbfc8>
def test_noop(smtp):
response = smtp.noop()
@ -416,15 +431,17 @@ Here we declare an ``app`` fixture which receives the previously defined
test_appsetup.py:12: test_smtp_exists[merlinux.eu] PASSED
test_appsetup.py:12: test_smtp_exists[mail.python.org] PASSED
========================= 2 passed in 0.17 seconds =========================
========================= 2 passed in 0.15 seconds =========================
Due to the parametrization of ``smtp`` the test will run twice with two
different ``App`` instances and respective smtp servers. There is no
need for the ``app`` fixture to be aware of the ``smtp`` parametrization
as pytest will fully analyse the fixture dependency graph. Note also,
that the ``app`` fixture has a scope of ``module`` but may use a
session-scoped ``smtp`` from the example higher up: it is fine for
fixtures to use "broader" scoped fixtures but not the other way round:
as pytest will fully analyse the fixture dependency graph.
Note, that the ``app`` fixture has a scope of ``module`` and uses a
module-scoped ``smtp`` fixture. The example would still work if ``smtp``
was cached on a ``session`` scope: it is fine for fixtures to use
"broader" scoped fixtures but not the other way round:
A session-scoped fixture could not use a module-scoped one in a
meaningful way.

View File

@ -122,7 +122,7 @@ run the module by passing its filename::
================================= FAILURES =================================
____________________________ TestClass.test_two ____________________________
self = <test_class.TestClass instance at 0x1f8a6c8>
self = <test_class.TestClass instance at 0x1a686c8>
def test_two(self):
x = "hello"
@ -157,7 +157,7 @@ before performing the test function call. Let's just run it::
================================= FAILURES =================================
_____________________________ test_needsfiles ______________________________
tmpdir = local('/tmp/pytest-1409/test_needsfiles0')
tmpdir = local('/tmp/pytest-1437/test_needsfiles0')
def test_needsfiles(tmpdir):
print tmpdir
@ -166,7 +166,7 @@ before performing the test function call. Let's just run it::
test_tmpdir.py:3: AssertionError
----------------------------- Captured stdout ------------------------------
/tmp/pytest-1409/test_needsfiles0
/tmp/pytest-1437/test_needsfiles0
Before the test runs, a unique-per-test-invocation temporary directory
was created. More info at :ref:`tmpdir handling`.

View File

@ -135,8 +135,8 @@ Let's also run with a stringinput that will lead to a failing test::
def test_valid_string(stringinput):
> assert stringinput.isalpha()
E assert <built-in method isalpha of str object at 0x2b7d7a85a030>()
E + where <built-in method isalpha of str object at 0x2b7d7a85a030> = '!'.isalpha
E assert <built-in method isalpha of str object at 0x2b2964af2030>()
E + where <built-in method isalpha of str object at 0x2b2964af2030> = '!'.isalpha
test_strings.py:3: AssertionError
@ -149,7 +149,7 @@ listlist::
$ py.test -q -rs test_strings.py
s
========================= short test summary info ==========================
SKIP [1] /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:947: got empty parameter set, function test_valid_string at /tmp/doc-exec-259/test_strings.py:1
SKIP [1] /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:947: got empty parameter set, function test_valid_string at /tmp/doc-exec-381/test_strings.py:1
For further examples, you might want to look at :ref:`more
parametrization examples <paramexamples>`.

View File

@ -37,7 +37,7 @@ Running this would result in a passed test except for the last
================================= FAILURES =================================
_____________________________ test_create_file _____________________________
tmpdir = local('/tmp/pytest-1410/test_create_file0')
tmpdir = local('/tmp/pytest-1438/test_create_file0')
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt")
@ -48,7 +48,7 @@ Running this would result in a passed test except for the last
E assert 0
test_tmpdir.py:7: AssertionError
========================= 1 failed in 0.03 seconds =========================
========================= 1 failed in 0.04 seconds =========================
.. _`base temporary directory`:

View File

@ -101,7 +101,7 @@ the ``self.db`` values in the traceback::
def test_method1(self):
assert hasattr(self, "db")
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.DummyDB instance at 0x2e36bd8>
E AssertionError: <conftest.DummyDB instance at 0x2ef8bd8>
test_unittest_db.py:9: AssertionError
___________________________ MyTest.test_method2 ____________________________
@ -110,7 +110,7 @@ the ``self.db`` values in the traceback::
def test_method2(self):
> assert 0, self.db # fail for demo purposes
E AssertionError: <conftest.DummyDB instance at 0x2e36bd8>
E AssertionError: <conftest.DummyDB instance at 0x2ef8bd8>
test_unittest_db.py:12: AssertionError
========================= 2 failed in 0.02 seconds =========================