Compare commits
150 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1830de2c13 | ||
|
|
25ab906b8b | ||
|
|
8a3b4b9c37 | ||
|
|
2b8a54d5d9 | ||
|
|
4eabfed651 | ||
|
|
505a34bb85 | ||
|
|
2dade6ed00 | ||
|
|
825ea9bfa1 | ||
|
|
cc1186242c | ||
|
|
86284689a3 | ||
|
|
c70d020bf3 | ||
|
|
4622c28ffd | ||
|
|
899998cf9c | ||
|
|
6f385fb4ea | ||
|
|
18e12cbd67 | ||
|
|
3cf4e133cc | ||
|
|
d53bfe0aa7 | ||
|
|
97da43d909 | ||
|
|
ee080ce8a5 | ||
|
|
741a3e8602 | ||
|
|
177637bfb9 | ||
|
|
ae64221c34 | ||
|
|
22017f11d0 | ||
|
|
c1eaad7d57 | ||
|
|
8e6d538a57 | ||
|
|
0836d74ae7 | ||
|
|
a9e5bd52d3 | ||
|
|
b4b5e358c3 | ||
|
|
4190809d1a | ||
|
|
4e2a820c6a | ||
|
|
14a43fffee | ||
|
|
245d39f52d | ||
|
|
ac0b862f8f | ||
|
|
c41db8ebbb | ||
|
|
75c124ea17 | ||
|
|
ab13c3f362 | ||
|
|
c9af19dae1 | ||
|
|
ffffac27f9 | ||
|
|
618bd56acf | ||
|
|
402232e60f | ||
|
|
400b51caf6 | ||
|
|
9aaf0fd340 | ||
|
|
8976b3ee0e | ||
|
|
ac2f2b1deb | ||
|
|
0be961a0f3 | ||
|
|
b4a397d153 | ||
|
|
d1a9ab3df0 | ||
|
|
0ede968ec0 | ||
|
|
5f21abc3a3 | ||
|
|
e2bb81124c | ||
|
|
ea18e9656b | ||
|
|
3cc58c2f78 | ||
|
|
0ac94134f5 | ||
|
|
c142f2551d | ||
|
|
cccfaa81fb | ||
|
|
d960fb78fc | ||
|
|
d02d0bb7b7 | ||
|
|
fe4cdd8a90 | ||
|
|
54a143e6a8 | ||
|
|
3a4f69734a | ||
|
|
fbdc6e8cc0 | ||
|
|
c2c44f0ffc | ||
|
|
e12fe64b54 | ||
|
|
5240252164 | ||
|
|
1ffc006363 | ||
|
|
836232e544 | ||
|
|
2539e5a352 | ||
|
|
8e457338ee | ||
|
|
d92ee8c3c3 | ||
|
|
492c60c202 | ||
|
|
86ef81454f | ||
|
|
675669c52e | ||
|
|
92c5d395a2 | ||
|
|
fa4ea1d9e8 | ||
|
|
657a395839 | ||
|
|
9fb2079458 | ||
|
|
83620ced2e | ||
|
|
1fb824cd28 | ||
|
|
0d35994fb8 | ||
|
|
3a37f33d99 | ||
|
|
ddfb2d5f3a | ||
|
|
d81c0e9a92 | ||
|
|
048cb71bf6 | ||
|
|
903fd144ff | ||
|
|
d51e27a5cb | ||
|
|
064290a606 | ||
|
|
e6ae68c0cc | ||
|
|
43f970ab6b | ||
|
|
49b9f9091a | ||
|
|
99277be25f | ||
|
|
699892bd03 | ||
|
|
70c1503afc | ||
|
|
ee5d2eb696 | ||
|
|
2058f11931 | ||
|
|
53a9ee21d4 | ||
|
|
04118a5761 | ||
|
|
c101c30690 | ||
|
|
0e664d3471 | ||
|
|
fcb1749f10 | ||
|
|
180eb098f1 | ||
|
|
cc9b3ec296 | ||
|
|
66bd71a5d7 | ||
|
|
3365907989 | ||
|
|
6b2040f98d | ||
|
|
90551c6ce2 | ||
|
|
d3b8390df3 | ||
|
|
9554fe0bf8 | ||
|
|
5a13f31bce | ||
|
|
41bddb48a1 | ||
|
|
b820cf2e39 | ||
|
|
fd8638652d | ||
|
|
01ae5dbb2e | ||
|
|
b4797d6295 | ||
|
|
c9195a0f45 | ||
|
|
86c56c829a | ||
|
|
ef023ebad3 | ||
|
|
0c737e3de0 | ||
|
|
1b7c70eab4 | ||
|
|
6a5456f873 | ||
|
|
28b1079548 | ||
|
|
fe01d1b0df | ||
|
|
54174c308f | ||
|
|
901f764825 | ||
|
|
c1759fc384 | ||
|
|
e843b028e6 | ||
|
|
305cbecb34 | ||
|
|
a986b3fb4a | ||
|
|
fd42133d89 | ||
|
|
d6d7f3821f | ||
|
|
e79b43eeb2 | ||
|
|
afba6ce907 | ||
|
|
d5948325d4 | ||
|
|
b9b44bb87c | ||
|
|
00b00ff931 | ||
|
|
6f54a6be1e | ||
|
|
d1faccb061 | ||
|
|
0f6bb3b3ef | ||
|
|
542b87fed3 | ||
|
|
33f1df2369 | ||
|
|
041a12fdf2 | ||
|
|
555999397b | ||
|
|
25a45f6bf7 | ||
|
|
82f017edeb | ||
|
|
b4842b20f6 | ||
|
|
e14e966da9 | ||
|
|
ebe0c34a02 | ||
|
|
7d711083ec | ||
|
|
0a4d5a423e | ||
|
|
b9ccb9d31f | ||
|
|
cf37c477bb |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,7 +13,6 @@ include/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.swp
|
||||
*.html
|
||||
*.class
|
||||
*.orig
|
||||
*~
|
||||
|
||||
2
.hgtags
2
.hgtags
@@ -63,3 +63,5 @@ b93ac0cdae02effaa3c136a681cc45bba757fe46 1.4.14
|
||||
af860de70cc3f157ac34ca1d4bf557a057bff775 2.4.0
|
||||
8828c924acae0b4cad2e2cb92943d51da7cb744a 2.4.1
|
||||
8d051f89184bfa3033f5e59819dff9f32a612941 2.4.2
|
||||
a064ad64d167508a8e9e73766b1a4e6bd10c85db 2.5.0
|
||||
039d543d1ca02a716c0b0de9a7131beb8021e8a2 2.5.1
|
||||
|
||||
@@ -2,7 +2,8 @@ language: python
|
||||
# command to install dependencies
|
||||
install: "pip install -U detox"
|
||||
# # command to run tests
|
||||
script: detox --recreate
|
||||
script: detox --recreate -i ALL=https://devpi.net/hpk/dev/
|
||||
|
||||
notifications:
|
||||
irc:
|
||||
- "chat.freenode.net#pytest-dev"
|
||||
|
||||
12
AUTHORS
12
AUTHORS
@@ -1,7 +1,7 @@
|
||||
Holger Krekel, holger at merlinux eu
|
||||
merlinux GmbH, Germany, office at merlinux eu
|
||||
|
||||
Contributors include::
|
||||
Contributors include::
|
||||
|
||||
Ronny Pfannschmidt
|
||||
Benjamin Peterson
|
||||
@@ -9,21 +9,21 @@ Floris Bruynooghe
|
||||
Jason R. Coombs
|
||||
Wouter van Ackooy
|
||||
Samuele Pedroni
|
||||
Anatoly Bubenkoff
|
||||
Anatoly Bubenkoff
|
||||
Brianna Laugher
|
||||
Carl Friedrich Bolz
|
||||
Armin Rigo
|
||||
Maho
|
||||
Jaap Broekhuizen
|
||||
Jaap Broekhuizen
|
||||
Maciek Fijalkowski
|
||||
Guido Wesdorp
|
||||
Brian Dorsey
|
||||
Ross Lawley
|
||||
Ralf Schmitt
|
||||
Chris Lamb
|
||||
Chris Lamb
|
||||
Harald Armin Massa
|
||||
Martijn Faassen
|
||||
Ian Bicking
|
||||
Ian Bicking
|
||||
Jan Balster
|
||||
Grig Gheorghiu
|
||||
Bob Ippolito
|
||||
@@ -36,3 +36,5 @@ Katarzyna Jachim
|
||||
Christian Theunert
|
||||
Anthon van der Neut
|
||||
Mark Abramowitz
|
||||
Piotr Banaszkiewicz
|
||||
Jurko Gospodnetić
|
||||
|
||||
253
CHANGELOG
253
CHANGELOG
@@ -1,28 +1,77 @@
|
||||
2.5.2
|
||||
-----------------------------------
|
||||
|
||||
- fix issue409 -- better interoperate with cx_freeze by not
|
||||
trying to import from collections.abc which causes problems
|
||||
for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
|
||||
|
||||
- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
|
||||
Thanks Jurko Gospodnetic for the complete PR.
|
||||
|
||||
- fix issue425: mention at end of "py.test -h" that --markers
|
||||
and --fixtures work according to specified test path (or current dir)
|
||||
|
||||
- fix issue413: exceptions with unicode attributes are now printed
|
||||
correctly also on python2 and with pytest-xdist runs. (the fix
|
||||
requires py-1.4.20)
|
||||
|
||||
- copy, cleanup and integrate py.io capture
|
||||
from pylib 1.4.20.dev2 (rev 13d9af95547e)
|
||||
|
||||
- address issue416: clarify docs as to conftest.py loading semantics
|
||||
|
||||
- fix issue429: comparing byte strings with non-ascii chars in assert
|
||||
expressions now work better. Thanks Floris Bruynooghe.
|
||||
|
||||
- make capfd/capsys.capture private, its unused and shouldnt be exposed
|
||||
|
||||
|
||||
2.5.1
|
||||
-----------------------------------
|
||||
|
||||
- merge new documentation styling PR from Tobias Bieniek.
|
||||
|
||||
- fix issue403: allow parametrize of multiple same-name functions within
|
||||
a collection node. Thanks Andreas Kloeckner and Alex Gaynor for reporting
|
||||
and analysis.
|
||||
|
||||
- Allow parameterized fixtures to specify the ID of the parameters by
|
||||
adding an ids argument to pytest.fixture() and pytest.yield_fixture().
|
||||
Thanks Floris Bruynooghe.
|
||||
|
||||
- fix issue404 by always using the binary xml escape in the junitxml
|
||||
plugin. Thanks Ronny Pfannschmidt.
|
||||
|
||||
- fix issue407: fix addoption docstring to point to argparse instead of
|
||||
optparse. Thanks Daniel D. Wright.
|
||||
|
||||
|
||||
|
||||
2.5.0
|
||||
-----------------------------------
|
||||
|
||||
- dropped python2.5 from automated release testing of pytest itself
|
||||
which means it's probably going to break soon (but still works
|
||||
- dropped python2.5 from automated release testing of pytest itself
|
||||
which means it's probably going to break soon (but still works
|
||||
with this release we believe).
|
||||
|
||||
- simplified and fixed implementation for calling finalizers when
|
||||
parametrized fixtures or function arguments are involved. finalization
|
||||
parametrized fixtures or function arguments are involved. finalization
|
||||
is now performed lazily at setup time instead of in the "teardown phase".
|
||||
While this might sound odd at first, it helps to ensure that we are
|
||||
While this might sound odd at first, it helps to ensure that we are
|
||||
correctly handling setup/teardown even in complex code. User-level code
|
||||
should not be affected unless it's implementing the pytest_runtest_teardown
|
||||
hook and expecting certain fixture instances are torn down within (very
|
||||
unlikely and would have been unreliable anyway).
|
||||
|
||||
- PR90: add --color=yes|no|auto option to force terminal coloring
|
||||
- PR90: add --color=yes|no|auto option to force terminal coloring
|
||||
mode ("auto" is default). Thanks Marc Abramowitz.
|
||||
|
||||
- fix issue319 - correctly show unicode in assertion errors. Many
|
||||
thanks to Floris Bruynooghe for the complete PR. Also means
|
||||
we depend on py>=1.4.19 now.
|
||||
|
||||
- fix issue396 - correctly sort and finalize class-scoped parametrized
|
||||
tests independently from number of methods on the class.
|
||||
- fix issue396 - correctly sort and finalize class-scoped parametrized
|
||||
tests independently from number of methods on the class.
|
||||
|
||||
- refix issue323 in a better way -- parametrization should now never
|
||||
cause Runtime Recursion errors because the underlying algorithm
|
||||
@@ -31,18 +80,18 @@
|
||||
to problems for more than >966 non-function scoped parameters).
|
||||
|
||||
- fix issue290 - there is preliminary support now for parametrizing
|
||||
with repeated same values (sometimes useful to to test if calling
|
||||
with repeated same values (sometimes useful to to test if calling
|
||||
a second time works as with the first time).
|
||||
|
||||
- close issue240 - document precisely how pytest module importing
|
||||
works, discuss the two common test directory layouts, and how it
|
||||
works, discuss the two common test directory layouts, and how it
|
||||
interacts with PEP420-namespace packages.
|
||||
|
||||
- fix issue246 fix finalizer order to be LIFO on independent fixtures
|
||||
depending on a parametrized higher-than-function scoped fixture.
|
||||
depending on a parametrized higher-than-function scoped fixture.
|
||||
(was quite some effort so please bear with the complexity of this sentence :)
|
||||
Thanks Ralph Schmitt for the precise failure example.
|
||||
|
||||
|
||||
- fix issue244 by implementing special index for parameters to only use
|
||||
indices for paramentrized test ids
|
||||
|
||||
@@ -60,9 +109,9 @@
|
||||
filtering with simple strings that are not valid python expressions.
|
||||
Examples: "-k 1.3" matches all tests parametrized with 1.3.
|
||||
"-k None" filters all tests that have "None" in their name
|
||||
and conversely "-k 'not None'".
|
||||
and conversely "-k 'not None'".
|
||||
Previously these examples would raise syntax errors.
|
||||
|
||||
|
||||
- fix issue384 by removing the trial support code
|
||||
since the unittest compat enhancements allow
|
||||
trial to handle it on its own
|
||||
@@ -70,7 +119,7 @@
|
||||
- don't hide an ImportError when importing a plugin produces one.
|
||||
fixes issue375.
|
||||
|
||||
- fix issue275 - allow usefixtures and autouse fixtures
|
||||
- fix issue275 - allow usefixtures and autouse fixtures
|
||||
for running doctest text files.
|
||||
|
||||
- fix issue380 by making --resultlog only rely on longrepr instead
|
||||
@@ -96,20 +145,20 @@
|
||||
(it already did neutralize pytest.mark.xfail markers)
|
||||
|
||||
- refine pytest / pkg_resources interactions: The AssertionRewritingHook
|
||||
PEP302 compliant loader now registers itself with setuptools/pkg_resources
|
||||
PEP302 compliant loader now registers itself with setuptools/pkg_resources
|
||||
properly so that the pkg_resources.resource_stream method works properly.
|
||||
Fixes issue366. Thanks for the investigations and full PR to Jason R. Coombs.
|
||||
|
||||
- pytestconfig fixture is now session-scoped as it is the same object during the
|
||||
whole test run. Fixes issue370.
|
||||
whole test run. Fixes issue370.
|
||||
|
||||
- avoid one surprising case of marker malfunction/confusion::
|
||||
|
||||
|
||||
@pytest.mark.some(lambda arg: ...)
|
||||
def test_function():
|
||||
|
||||
would not work correctly because pytest assumes @pytest.mark.some
|
||||
gets a function to be decorated already. We now at least detect if this
|
||||
would not work correctly because pytest assumes @pytest.mark.some
|
||||
gets a function to be decorated already. We now at least detect if this
|
||||
arg is an lambda and thus the example will work. Thanks Alex Gaynor
|
||||
for bringing it up.
|
||||
|
||||
@@ -120,11 +169,11 @@
|
||||
although it's not needed by pytest itself atm. Also
|
||||
fix caching. Fixes issue376.
|
||||
|
||||
- fix issue221 - handle importing of namespace-package with no
|
||||
- fix issue221 - handle importing of namespace-package with no
|
||||
__init__.py properly.
|
||||
|
||||
- refactor internal FixtureRequest handling to avoid monkeypatching.
|
||||
One of the positive user-facing effects is that the "request" object
|
||||
One of the positive user-facing effects is that the "request" object
|
||||
can now be used in closures.
|
||||
|
||||
- fixed version comparison in pytest.importskip(modname, minverstring)
|
||||
@@ -134,7 +183,7 @@
|
||||
|
||||
- fix verbose reporting for @mock'd test functions
|
||||
|
||||
Changes between 2.4.1 and 2.4.2
|
||||
v2.4.2
|
||||
-----------------------------------
|
||||
|
||||
- on Windows require colorama and a newer py lib so that py.io.TerminalWriter()
|
||||
@@ -160,19 +209,19 @@ Changes between 2.4.1 and 2.4.2
|
||||
|
||||
- remove attempt to "dup" stdout at startup as it's icky.
|
||||
the normal capturing should catch enough possibilities
|
||||
of tests messing up standard FDs.
|
||||
of tests messing up standard FDs.
|
||||
|
||||
- add pluginmanager.do_configure(config) as a link to
|
||||
- add pluginmanager.do_configure(config) as a link to
|
||||
config.do_configure() for plugin-compatibility
|
||||
|
||||
Changes between 2.4.0 and 2.4.1
|
||||
v2.4.1
|
||||
-----------------------------------
|
||||
|
||||
- When using parser.addoption() unicode arguments to the
|
||||
"type" keyword should also be converted to the respective types.
|
||||
thanks Floris Bruynooghe, @dnozay. (fixes issue360 and issue362)
|
||||
|
||||
- fix dotted filename completion when using argcomplete
|
||||
- fix dotted filename completion when using argcomplete
|
||||
thanks Anthon van der Neuth. (fixes issue361)
|
||||
|
||||
- fix regression when a 1-tuple ("arg",) is used for specifying
|
||||
@@ -181,7 +230,7 @@ Changes between 2.4.0 and 2.4.1
|
||||
|
||||
- merge doc typo fixes, thanks Andy Dirnberger
|
||||
|
||||
Changes between 2.3.5 and 2.4
|
||||
v2.4
|
||||
-----------------------------------
|
||||
|
||||
known incompatibilities:
|
||||
@@ -228,12 +277,12 @@ new features:
|
||||
- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
|
||||
"-s" needed anymore), making ``pytest.set_trace()`` a mere shortcut.
|
||||
|
||||
- fix issue181: --pdb now also works on collect errors (and
|
||||
on internal errors) . This was implemented by a slight internal
|
||||
refactoring and the introduction of a new hook
|
||||
- fix issue181: --pdb now also works on collect errors (and
|
||||
on internal errors) . This was implemented by a slight internal
|
||||
refactoring and the introduction of a new hook
|
||||
``pytest_exception_interact`` hook (see next item).
|
||||
|
||||
- fix issue341: introduce new experimental hook for IDEs/terminals to
|
||||
- fix issue341: introduce new experimental hook for IDEs/terminals to
|
||||
intercept debugging: ``pytest_exception_interact(node, call, report)``.
|
||||
|
||||
- new monkeypatch.setattr() variant to provide a shorter
|
||||
@@ -251,7 +300,7 @@ new features:
|
||||
phase of a node.
|
||||
|
||||
- simplify pytest.mark.parametrize() signature: allow to pass a
|
||||
CSV-separated string to specify argnames. For example:
|
||||
CSV-separated string to specify argnames. For example:
|
||||
``pytest.mark.parametrize("input,expected", [(1,2), (2,3)])``
|
||||
works as well as the previous:
|
||||
``pytest.mark.parametrize(("input", "expected"), ...)``.
|
||||
@@ -276,10 +325,10 @@ new features:
|
||||
|
||||
Bug fixes:
|
||||
|
||||
- fix issue358 - capturing options are now parsed more properly
|
||||
- fix issue358 - capturing options are now parsed more properly
|
||||
by using a new parser.parse_known_args method.
|
||||
|
||||
- pytest now uses argparse instead of optparse (thanks Anthon) which
|
||||
- pytest now uses argparse instead of optparse (thanks Anthon) which
|
||||
means that "argparse" is added as a dependency if installing into python2.6
|
||||
environments or below.
|
||||
|
||||
@@ -320,7 +369,7 @@ Bug fixes:
|
||||
- fix issue323 - sorting of many module-scoped arg parametrizations
|
||||
|
||||
- make sessionfinish hooks execute with the same cwd-context as at
|
||||
session start (helps fix plugin behaviour which write output files
|
||||
session start (helps fix plugin behaviour which write output files
|
||||
with relative path such as pytest-cov)
|
||||
|
||||
- fix issue316 - properly reference collection hooks in docs
|
||||
@@ -328,7 +377,7 @@ Bug fixes:
|
||||
- fix issue 306 - cleanup of -k/-m options to only match markers/test
|
||||
names/keywords respectively. Thanks Wouter van Ackooy.
|
||||
|
||||
- improved doctest counting for doctests in python modules --
|
||||
- improved doctest counting for doctests in python modules --
|
||||
files without any doctest items will not show up anymore
|
||||
and doctest examples are counted as separate test items.
|
||||
thanks Danilo Bellini.
|
||||
@@ -338,7 +387,7 @@ Bug fixes:
|
||||
mode. Thanks Jason R. Coombs.
|
||||
|
||||
- fix junitxml generation when test output contains control characters,
|
||||
addressing issue267, thanks Jaap Broekhuizen
|
||||
addressing issue267, thanks Jaap Broekhuizen
|
||||
|
||||
- fix issue338: honor --tb style for setup/teardown errors as well. Thanks Maho.
|
||||
|
||||
@@ -347,10 +396,10 @@ Bug fixes:
|
||||
- better parametrize error messages, thanks Brianna Laugher
|
||||
|
||||
- pytest_terminal_summary(terminalreporter) hooks can now use
|
||||
".section(title)" and ".line(msg)" methods to print extra
|
||||
".section(title)" and ".line(msg)" methods to print extra
|
||||
information at the end of a test run.
|
||||
|
||||
Changes between 2.3.4 and 2.3.5
|
||||
v2.3.5
|
||||
-----------------------------------
|
||||
|
||||
- fix issue169: respect --tb=style with setup/teardown errors as well.
|
||||
@@ -401,7 +450,7 @@ Changes between 2.3.4 and 2.3.5
|
||||
- fix bug where using capsys with pytest.set_trace() in a test
|
||||
function would break when looking at capsys.readouterr()
|
||||
|
||||
- allow to specify prefixes starting with "_" when
|
||||
- allow to specify prefixes starting with "_" when
|
||||
customizing python_functions test discovery. (thanks Graham Horler)
|
||||
|
||||
- improve PYTEST_DEBUG tracing output by puting
|
||||
@@ -415,10 +464,10 @@ Changes between 2.3.4 and 2.3.5
|
||||
|
||||
- fix issue266 - accept unicode in MarkEvaluator expressions
|
||||
|
||||
Changes between 2.3.3 and 2.3.4
|
||||
v2.3.4
|
||||
-----------------------------------
|
||||
|
||||
- yielded test functions will now have autouse-fixtures active but
|
||||
- yielded test functions will now have autouse-fixtures active but
|
||||
cannot accept fixtures as funcargs - it's anyway recommended to
|
||||
rather use the post-2.0 parametrize features instead of yield, see:
|
||||
http://pytest.org/latest/example/parametrize.html
|
||||
@@ -433,9 +482,9 @@ Changes between 2.3.3 and 2.3.4
|
||||
can write: -k "name1 or name2" etc. This is a slight incompatibility
|
||||
if you used special syntax like "TestClass.test_method" which you now
|
||||
need to write as -k "TestClass and test_method" to match a certain
|
||||
method in a certain test class.
|
||||
method in a certain test class.
|
||||
|
||||
Changes between 2.3.2 and 2.3.3
|
||||
v2.3.3
|
||||
-----------------------------------
|
||||
|
||||
- fix issue214 - parse modules that contain special objects like e. g.
|
||||
@@ -467,10 +516,10 @@ Changes between 2.3.2 and 2.3.3
|
||||
- fix issue127 - improve documentation for pytest_addoption() and
|
||||
add a ``config.getoption(name)`` helper function for consistency.
|
||||
|
||||
Changes between 2.3.1 and 2.3.2
|
||||
v2.3.2
|
||||
-----------------------------------
|
||||
|
||||
- fix issue208 and fix issue29 use new py version to avoid long pauses
|
||||
- fix issue208 and fix issue29 use new py version to avoid long pauses
|
||||
when printing tracebacks in long modules
|
||||
|
||||
- fix issue205 - conftests in subdirs customizing
|
||||
@@ -500,7 +549,7 @@ Changes between 2.3.1 and 2.3.2
|
||||
- add tox.ini to pytest distribution so that ignore-dirs and others config
|
||||
bits are properly distributed for maintainers who run pytest-own tests
|
||||
|
||||
Changes between 2.3.0 and 2.3.1
|
||||
v2.3.1
|
||||
-----------------------------------
|
||||
|
||||
- fix issue202 - fix regression: using "self" from fixture functions now
|
||||
@@ -513,7 +562,7 @@ Changes between 2.3.0 and 2.3.1
|
||||
- link to web pages from --markers output which provides help for
|
||||
pytest.mark.* usage.
|
||||
|
||||
Changes between 2.2.4 and 2.3.0
|
||||
v2.3.0
|
||||
-----------------------------------
|
||||
|
||||
- fix issue202 - better automatic names for parametrized test functions
|
||||
@@ -554,7 +603,7 @@ Changes between 2.2.4 and 2.3.0
|
||||
- pluginmanager.register(...) now raises ValueError if the
|
||||
plugin has been already registered or the name is taken
|
||||
|
||||
- fix issue159: improve http://pytest.org/latest/faq.html
|
||||
- fix issue159: improve http://pytest.org/latest/faq.html
|
||||
especially with respect to the "magic" history, also mention
|
||||
pytest-django, trial and unittest integration.
|
||||
|
||||
@@ -585,14 +634,14 @@ Changes between 2.2.4 and 2.3.0
|
||||
you can use startdir.bestrelpath(yourpath) to show
|
||||
nice relative path
|
||||
|
||||
- allow plugins to implement both pytest_report_header and
|
||||
- allow plugins to implement both pytest_report_header and
|
||||
pytest_sessionstart (sessionstart is invoked first).
|
||||
|
||||
- don't show deselected reason line if there is none
|
||||
|
||||
- py.test -vv will show all of assert comparisations instead of truncating
|
||||
|
||||
Changes between 2.2.3 and 2.2.4
|
||||
v2.2.4
|
||||
-----------------------------------
|
||||
|
||||
- fix error message for rewritten assertions involving the % operator
|
||||
@@ -609,17 +658,17 @@ Changes between 2.2.3 and 2.2.4
|
||||
- fix issue #144: better mangle test ids to junitxml classnames
|
||||
- upgrade distribute_setup.py to 0.6.27
|
||||
|
||||
Changes between 2.2.2 and 2.2.3
|
||||
v2.2.3
|
||||
----------------------------------------
|
||||
|
||||
- fix uploaded package to only include neccesary files
|
||||
|
||||
Changes between 2.2.1 and 2.2.2
|
||||
v2.2.2
|
||||
----------------------------------------
|
||||
|
||||
- fix issue101: wrong args to unittest.TestCase test function now
|
||||
produce better output
|
||||
- fix issue102: report more useful errors and hints for when a
|
||||
- fix issue102: report more useful errors and hints for when a
|
||||
test directory was renamed and some pyc/__pycache__ remain
|
||||
- fix issue106: allow parametrize to be applied multiple times
|
||||
e.g. from module, class and at function level.
|
||||
@@ -634,11 +683,11 @@ Changes between 2.2.1 and 2.2.2
|
||||
- allow adding of attributes to test reports such that it also works
|
||||
with distributed testing (no upgrade of pytest-xdist needed)
|
||||
|
||||
Changes between 2.2.0 and 2.2.1
|
||||
v2.2.1
|
||||
----------------------------------------
|
||||
|
||||
- fix issue99 (in pytest and py) internallerrors with resultlog now
|
||||
produce better output - fixed by normalizing pytest_internalerror
|
||||
produce better output - fixed by normalizing pytest_internalerror
|
||||
input arguments.
|
||||
- fix issue97 / traceback issues (in pytest and py) improve traceback output
|
||||
in conjunction with jinja2 and cython which hack tracebacks
|
||||
@@ -646,25 +695,25 @@ Changes between 2.2.0 and 2.2.1
|
||||
the final test in a test node will now run its teardown directly
|
||||
instead of waiting for the end of the session. Thanks Dave Hunt for
|
||||
the good reporting and feedback. The pytest_runtest_protocol as well
|
||||
as the pytest_runtest_teardown hooks now have "nextitem" available
|
||||
as the pytest_runtest_teardown hooks now have "nextitem" available
|
||||
which will be None indicating the end of the test run.
|
||||
- fix collection crash due to unknown-source collected items, thanks
|
||||
to Ralf Schmitt (fixed by depending on a more recent pylib)
|
||||
|
||||
Changes between 2.1.3 and 2.2.0
|
||||
v2.2.0
|
||||
----------------------------------------
|
||||
|
||||
- fix issue90: introduce eager tearing down of test items so that
|
||||
teardown function are called earlier.
|
||||
- add an all-powerful metafunc.parametrize function which allows to
|
||||
- add an all-powerful metafunc.parametrize function which allows to
|
||||
parametrize test function arguments in multiple steps and therefore
|
||||
from indepdenent plugins and palces.
|
||||
from indepdenent plugins and palces.
|
||||
- add a @pytest.mark.parametrize helper which allows to easily
|
||||
call a test function with different argument values
|
||||
- Add examples to the "parametrize" example page, including a quick port
|
||||
- Add examples to the "parametrize" example page, including a quick port
|
||||
of Test scenarios and the new parametrize function and decorator.
|
||||
- introduce registration for "pytest.mark.*" helpers via ini-files
|
||||
or through plugin hooks. Also introduce a "--strict" option which
|
||||
or through plugin hooks. Also introduce a "--strict" option which
|
||||
will treat unregistered markers as errors
|
||||
allowing to avoid typos and maintain a well described set of markers
|
||||
for your test suite. See exaples at http://pytest.org/latest/mark.html
|
||||
@@ -673,12 +722,12 @@ Changes between 2.1.3 and 2.2.0
|
||||
(this is a stricter and more predictable version of '-k' in that "-m"
|
||||
only matches complete markers and has more obvious rules for and/or
|
||||
semantics.
|
||||
- new feature to help optimizing the speed of your tests:
|
||||
--durations=N option for displaying N slowest test calls
|
||||
- new feature to help optimizing the speed of your tests:
|
||||
--durations=N option for displaying N slowest test calls
|
||||
and setup/teardown methods.
|
||||
- fix issue87: --pastebin now works with python3
|
||||
- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
|
||||
- fix and cleanup pytest's own test suite to not leak FDs
|
||||
- fix and cleanup pytest's own test suite to not leak FDs
|
||||
- fix issue83: link to generated funcarg list
|
||||
- fix issue74: pyarg module names are now checked against imp.find_module false positives
|
||||
- fix compatibility with twisted/trial-11.1.0 use cases
|
||||
@@ -686,7 +735,7 @@ Changes between 2.1.3 and 2.2.0
|
||||
- simplify junitxml output code by relying on py.xml
|
||||
- add support for skip properties on unittest classes and functions
|
||||
|
||||
Changes between 2.1.2 and 2.1.3
|
||||
v2.1.3
|
||||
----------------------------------------
|
||||
|
||||
- fix issue79: assertion rewriting failed on some comparisons in boolops
|
||||
@@ -695,7 +744,7 @@ Changes between 2.1.2 and 2.1.3
|
||||
- fix issue75 / skipping test failure on jython
|
||||
- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
|
||||
|
||||
Changes between 2.1.1 and 2.1.2
|
||||
v2.1.2
|
||||
----------------------------------------
|
||||
|
||||
- fix assertion rewriting on files with windows newlines on some Python versions
|
||||
@@ -705,7 +754,7 @@ Changes between 2.1.1 and 2.1.2
|
||||
- fix issue66: use different assertion rewriting caches when the -O option is passed
|
||||
- don't try assertion rewriting on Jython, use reinterp
|
||||
|
||||
Changes between 2.1.0 and 2.1.1
|
||||
v2.1.1
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
|
||||
@@ -718,7 +767,7 @@ Changes between 2.1.0 and 2.1.1
|
||||
- fix issue61: assertion rewriting on boolean operations with 3 or more operands
|
||||
- you can now build a man page with "cd doc ; make man"
|
||||
|
||||
Changes between 2.0.3 and 2.1.0.DEV
|
||||
v2.1.0
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue53 call nosestyle setup functions with correct ordering
|
||||
@@ -738,7 +787,7 @@ Changes between 2.0.3 and 2.1.0.DEV
|
||||
- report KeyboardInterrupt even if interrupted during session startup
|
||||
- fix issue 35 - provide PDF doc version and download link from index page
|
||||
|
||||
Changes between 2.0.2 and 2.0.3
|
||||
v2.0.3
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue38: nicer tracebacks on calls to hooks, particularly early
|
||||
@@ -758,7 +807,7 @@ Changes between 2.0.2 and 2.0.3
|
||||
|
||||
- fix issue37: avoid invalid characters in junitxml's output
|
||||
|
||||
Changes between 2.0.1 and 2.0.2
|
||||
v2.0.2
|
||||
----------------------------------------------
|
||||
|
||||
- tackle issue32 - speed up test runs of very quick test functions
|
||||
@@ -770,17 +819,17 @@ Changes between 2.0.1 and 2.0.2
|
||||
|
||||
Also you can now access module globals from xfail/skipif
|
||||
expressions so that this for example works now::
|
||||
|
||||
|
||||
import pytest
|
||||
import mymodule
|
||||
@pytest.mark.skipif("mymodule.__version__[0] == "1")
|
||||
def test_function():
|
||||
pass
|
||||
|
||||
This will not run the test function if the module's version string
|
||||
This will not run the test function if the module's version string
|
||||
does not start with a "1". Note that specifying a string instead
|
||||
of a boolean expressions allows py.test to report meaningful information
|
||||
when summarizing a test run as to what conditions lead to skipping
|
||||
of a boolean expressions allows py.test to report meaningful information
|
||||
when summarizing a test run as to what conditions lead to skipping
|
||||
(or xfail-ing) tests.
|
||||
|
||||
- fix issue28 - setup_method and pytest_generate_tests work together
|
||||
@@ -803,14 +852,14 @@ Changes between 2.0.1 and 2.0.2
|
||||
- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
|
||||
thanks to Laura Creighton who also revieved parts of the documentation.
|
||||
|
||||
- fix slighly wrong output of verbose progress reporting for classes
|
||||
- fix slighly wrong output of verbose progress reporting for classes
|
||||
(thanks Amaury)
|
||||
|
||||
- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
|
||||
|
||||
- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
|
||||
|
||||
Changes between 2.0.0 and 2.0.1
|
||||
v2.0.1
|
||||
----------------------------------------------
|
||||
|
||||
- refine and unify initial capturing so that it works nicely
|
||||
@@ -819,7 +868,7 @@ Changes between 2.0.0 and 2.0.1
|
||||
- allow to omit "()" in test ids to allow for uniform test ids
|
||||
as produced by Alfredo's nice pytest.vim plugin.
|
||||
- fix issue12 - show plugin versions with "--version" and
|
||||
"--traceconfig" and also document how to add extra information
|
||||
"--traceconfig" and also document how to add extra information
|
||||
to reporting test header
|
||||
- fix issue17 (import-* reporting issue on python3) by
|
||||
requiring py>1.4.0 (1.4.1 is going to include it)
|
||||
@@ -849,17 +898,17 @@ Changes between 2.0.0 and 2.0.1
|
||||
- fix issue14: no logging errors at process exit
|
||||
- refinements to "collecting" output on non-ttys
|
||||
- refine internal plugin registration and --traceconfig output
|
||||
- introduce a mechanism to prevent/unregister plugins from the
|
||||
- introduce a mechanism to prevent/unregister plugins from the
|
||||
command line, see http://pytest.org/plugins.html#cmdunregister
|
||||
- activate resultlog plugin by default
|
||||
- fix regression wrt yielded tests which due to the
|
||||
collection-before-running semantics were not
|
||||
collection-before-running semantics were not
|
||||
setup as with pytest 1.3.4. Note, however, that
|
||||
the recommended and much cleaner way to do test
|
||||
the recommended and much cleaner way to do test
|
||||
parametraization remains the "pytest_generate_tests"
|
||||
mechanism, see the docs.
|
||||
|
||||
Changes between 1.3.4 and 2.0.0
|
||||
v2.0.0
|
||||
----------------------------------------------
|
||||
|
||||
- pytest-2.0 is now its own package and depends on pylib-2.0
|
||||
@@ -904,7 +953,7 @@ Changes between 1.3.4 and 2.0.0
|
||||
- add ability to use "class" level for cached_setup helper
|
||||
- fix strangeness: mark.* objects are now immutable, create new instances
|
||||
|
||||
Changes between 1.3.3 and 1.3.4
|
||||
v1.3.4
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue111: improve install documentation for windows
|
||||
@@ -913,7 +962,7 @@ Changes between 1.3.3 and 1.3.4
|
||||
- fix issue115: unify internal exception passthrough/catching/GeneratorExit
|
||||
- fix issue118: new --tb=native for presenting cpython-standard exceptions
|
||||
|
||||
Changes between 1.3.2 and 1.3.3
|
||||
v1.3.3
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue113: assertion representation problem with triple-quoted strings
|
||||
@@ -928,7 +977,7 @@ Changes between 1.3.2 and 1.3.3
|
||||
(thanks Armin Ronacher for reporting)
|
||||
- remove trailing whitespace in all py/text distribution files
|
||||
|
||||
Changes between 1.3.1 and 1.3.2
|
||||
v1.3.2
|
||||
----------------------------------------------
|
||||
|
||||
New features
|
||||
@@ -1003,7 +1052,7 @@ Bug fixes / Maintenance
|
||||
- fix homedir detection on Windows
|
||||
- ship distribute_setup.py version 0.6.13
|
||||
|
||||
Changes between 1.3.0 and 1.3.1
|
||||
v1.3.1
|
||||
---------------------------------------------
|
||||
|
||||
New features
|
||||
@@ -1075,7 +1124,7 @@ Fixes / Maintenance
|
||||
(and internally be more careful when presenting unexpected byte sequences)
|
||||
|
||||
|
||||
Changes between 1.2.1 and 1.3.0
|
||||
v1.3.0
|
||||
---------------------------------------------
|
||||
|
||||
- deprecate --report option in favour of a new shorter and easier to
|
||||
@@ -1140,7 +1189,7 @@ Changes between 1.2.1 and 1.3.0
|
||||
- added links to the new capturelog and coverage plugins
|
||||
|
||||
|
||||
Changes between 1.2.1 and 1.2.0
|
||||
v1.2.0
|
||||
---------------------------------------------
|
||||
|
||||
- refined usage and options for "py.cleanup"::
|
||||
@@ -1179,7 +1228,7 @@ Changes between 1.2.1 and 1.2.0
|
||||
|
||||
- fix plugin links
|
||||
|
||||
Changes between 1.2 and 1.1.1
|
||||
v1.1.1
|
||||
---------------------------------------------
|
||||
|
||||
- moved dist/looponfailing from py.test core into a new
|
||||
@@ -1263,7 +1312,7 @@ Changes between 1.2 and 1.1.1
|
||||
- fix docs, fix internal bin/ script generation
|
||||
|
||||
|
||||
Changes between 1.1.1 and 1.1.0
|
||||
v1.1.0
|
||||
---------------------------------------------
|
||||
|
||||
- introduce automatic plugin registration via 'pytest11'
|
||||
@@ -1282,7 +1331,7 @@ Changes between 1.1.1 and 1.1.0
|
||||
- try harder to have deprecation warnings for py.compat.* accesses
|
||||
report a correct location
|
||||
|
||||
Changes between 1.1.0 and 1.0.2
|
||||
v1.0.2
|
||||
---------------------------------------------
|
||||
|
||||
* adjust and improve docs
|
||||
@@ -1367,7 +1416,7 @@ Changes between 1.1.0 and 1.0.2
|
||||
|
||||
* simplified internal localpath implementation
|
||||
|
||||
Changes between 1.0.1 and 1.0.2
|
||||
v1.0.2
|
||||
-------------------------------------------
|
||||
|
||||
* fixing packaging issues, triggered by fedora redhat packaging,
|
||||
@@ -1375,7 +1424,7 @@ Changes between 1.0.1 and 1.0.2
|
||||
|
||||
* added a documentation link to the new django plugin.
|
||||
|
||||
Changes between 1.0.0 and 1.0.1
|
||||
v1.0.1
|
||||
-------------------------------------------
|
||||
|
||||
* added a 'pytest_nose' plugin which handles nose.SkipTest,
|
||||
@@ -1409,13 +1458,13 @@ Changes between 1.0.0 and 1.0.1
|
||||
* simplified multicall mechanism and plugin architecture,
|
||||
renamed some internal methods and argnames
|
||||
|
||||
Changes between 1.0.0b9 and 1.0.0
|
||||
v1.0.0
|
||||
-------------------------------------------
|
||||
|
||||
* more terse reporting try to show filesystem path relatively to current dir
|
||||
* improve xfail output a bit
|
||||
|
||||
Changes between 1.0.0b8 and 1.0.0b9
|
||||
v1.0.0b9
|
||||
-------------------------------------------
|
||||
|
||||
* cleanly handle and report final teardown of test setup
|
||||
@@ -1449,7 +1498,7 @@ Changes between 1.0.0b8 and 1.0.0b9
|
||||
* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
|
||||
|
||||
|
||||
Changes between 1.0.0b7 and 1.0.0b8
|
||||
v1.0.0b8
|
||||
-------------------------------------------
|
||||
|
||||
* pytest_unittest-plugin is now enabled by default
|
||||
@@ -1478,7 +1527,7 @@ Changes between 1.0.0b7 and 1.0.0b8
|
||||
* tweaked doctest output for docstrings in py modules,
|
||||
thanks Radomir.
|
||||
|
||||
Changes between 1.0.0b3 and 1.0.0b7
|
||||
v1.0.0b7
|
||||
-------------------------------------------
|
||||
|
||||
* renamed py.test.xfail back to py.test.mark.xfail to avoid
|
||||
@@ -1503,7 +1552,7 @@ Changes between 1.0.0b3 and 1.0.0b7
|
||||
|
||||
* make __name__ == "__channelexec__" for remote_exec code
|
||||
|
||||
Changes between 1.0.0b1 and 1.0.0b3
|
||||
v1.0.0b3
|
||||
-------------------------------------------
|
||||
|
||||
* plugin classes are removed: one now defines
|
||||
@@ -1520,7 +1569,7 @@ Changes between 1.0.0b1 and 1.0.0b3
|
||||
well with function arguments.
|
||||
|
||||
|
||||
Changes between 0.9.2 and 1.0.0b1
|
||||
v1.0.0b1
|
||||
-------------------------------------------
|
||||
|
||||
* introduced new "funcarg" setup method,
|
||||
@@ -1544,7 +1593,7 @@ Changes between 0.9.2 and 1.0.0b1
|
||||
|
||||
XXX lots of things missing here XXX
|
||||
|
||||
Changes between 0.9.1 and 0.9.2
|
||||
v0.9.2
|
||||
-------------------------------------------
|
||||
|
||||
* refined installation and metadata, created new setup.py,
|
||||
@@ -1577,10 +1626,10 @@ Changes between 0.9.1 and 0.9.2
|
||||
|
||||
* there now is a py.__version__ attribute
|
||||
|
||||
Changes between 0.9.0 and 0.9.1
|
||||
v0.9.1
|
||||
-------------------------------------------
|
||||
|
||||
This is a fairly complete list of changes between 0.9 and 0.9.1, which can
|
||||
This is a fairly complete list of v0.9.1, which can
|
||||
serve as a reference for developers.
|
||||
|
||||
* allowing + signs in py.path.svn urls [39106]
|
||||
|
||||
171
CONTRIBUTING.rst
Normal file
171
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,171 @@
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
|
||||
Contributions are highly welcomed and appreciated. Every little help counts,
|
||||
so do not hesitate!
|
||||
|
||||
|
||||
Types of contributions
|
||||
======================
|
||||
|
||||
Report bugs
|
||||
-----------
|
||||
|
||||
Report bugs at https://bitbucket.org/hpk42/pytest/issues.
|
||||
|
||||
If you are reporting a bug, please include:
|
||||
|
||||
* Your operating system name and version.
|
||||
* Any details about your local setup that might be helpful in troubleshooting,
|
||||
specifically Python interpreter version,
|
||||
installed libraries and pytest version.
|
||||
* Detailed steps to reproduce the bug.
|
||||
|
||||
Submit feedback for developers
|
||||
------------------------------
|
||||
|
||||
Do you like pytest? Share some love on Twitter or in your blog posts!
|
||||
|
||||
We'd also like to hear about your propositions and suggestions. Feel free to
|
||||
`submit them as issues <https://bitbucket.org/hpk42/pytest/issues>`__ and:
|
||||
|
||||
* Set the "kind" to "enhancement" or "proposal" so that we can quickly find
|
||||
about them.
|
||||
* Explain in detail how they should work.
|
||||
* Keep the scope as narrow as possible. This will make it easier to implement.
|
||||
* If you have required skills and/or knowledge, we are very happy for
|
||||
:ref:`pull requests <pull-requests>`.
|
||||
|
||||
|
||||
Fix bugs
|
||||
--------
|
||||
|
||||
Look through the BitBucket issues for bugs. Here is sample filter you can use:
|
||||
https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=bug
|
||||
|
||||
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
|
||||
|
||||
Implement features
|
||||
------------------
|
||||
|
||||
Look through the BitBucket issues for enhancements. Here is sample filter you
|
||||
can use:
|
||||
https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&kind=enhancement
|
||||
|
||||
:ref:`Talk <contact>` to developers to find out how you can implement specific
|
||||
features.
|
||||
|
||||
Write documentation
|
||||
-------------------
|
||||
|
||||
pytest could always use more documentation. What exactly is needed?
|
||||
|
||||
* More complementary documentation. Have you perhaps found something unclear?
|
||||
* Documentation translations. We currently have English and Japanese versions.
|
||||
* Docstrings. There's never too much of them.
|
||||
* Blog posts, articles and such -- they're all very appreciated.
|
||||
|
||||
.. _pull-requests:
|
||||
|
||||
Preparing Pull Requests on Bitbucket
|
||||
=====================================
|
||||
|
||||
.. note::
|
||||
What is a "pull request"? It informs project's core developers about the
|
||||
changes you want to review and merge. Pull requests are stored on
|
||||
`BitBucket servers <https://bitbucket.org/hpk42/pytest/pull-requests>`__.
|
||||
Once you send pull request, we can discuss it's potential modifications and
|
||||
even add more commits to it later on.
|
||||
|
||||
The primary development platform for pytest is BitBucket. You can find all
|
||||
the issues there and submit your pull requests.
|
||||
|
||||
1. Fork the
|
||||
`pytest BitBucket repository <https://bitbucket.org/hpk42/pytest>`__. It's
|
||||
fine to use ``pytest`` as your fork repository name because it will live
|
||||
under your user.
|
||||
|
||||
.. _virtualenvactivate:
|
||||
|
||||
2. Create and activate a fork-specific virtualenv
|
||||
(http://www.virtualenv.org/en/latest/)::
|
||||
|
||||
$ virtualenv pytest-venv
|
||||
$ source pytest-venv/bin/activate
|
||||
|
||||
.. _checkout:
|
||||
|
||||
3. Clone your fork locally using `Mercurial <http://mercurial.selenic.com/>`_
|
||||
(``hg``) and create a branch::
|
||||
|
||||
$ hg clone ssh://hg@bitbucket.org/YOUR_BITBUCKET_USERNAME/pytest
|
||||
$ cd pytest
|
||||
$ hg branch your-branch-name
|
||||
|
||||
If you need some help with Mercurial, follow this quick start
|
||||
guide: http://mercurial.selenic.com/wiki/QuickStart
|
||||
|
||||
.. _testing-pytest:
|
||||
|
||||
4. You can now edit your local working copy. To test you need to
|
||||
install the "tox" tool into your virtualenv::
|
||||
|
||||
$ pip install tox
|
||||
|
||||
You need to have Python 2.7 and 3.3 available in your system. Now
|
||||
running tests is as simple as issuing this command::
|
||||
|
||||
$ python runtox.py -e py27,py33,flakes
|
||||
|
||||
This command will run tests via the "tox" tool against Python 2.7 and 3.3
|
||||
and also perform "flakes" coding-style checks. ``runtox.py`` is
|
||||
a thin wrapper around ``tox`` which installs from a development package
|
||||
index where newer (not yet released to pypi) versions of dependencies
|
||||
(especially ``py``) might be present.
|
||||
|
||||
To run tests on py27 and pass options (e.g. enter pdb on failure)
|
||||
to pytest you can do::
|
||||
|
||||
$ python runtox.py -e py27 -- --pdb
|
||||
|
||||
or to only run tests in a particular test module on py33::
|
||||
|
||||
$ python runtox.py -e py33 -- testing/test_config.py
|
||||
|
||||
5. Commit and push once your tests pass and you are happy with your change(s)::
|
||||
|
||||
$ hg commit -m"<commit message>"
|
||||
$ hg push -b .
|
||||
|
||||
6. Finally, submit a pull request through the BitBucket website:
|
||||
|
||||
.. image:: img/pullrequest.png
|
||||
:width: 700px
|
||||
:align: center
|
||||
|
||||
::
|
||||
|
||||
source: YOUR_BITBUCKET_USERNAME/pytest
|
||||
branch: your-branch-name
|
||||
|
||||
target: hpk42/pytest
|
||||
branch: default
|
||||
|
||||
.. _contribution-using-git:
|
||||
|
||||
What about git (and so GitHub)?
|
||||
-------------------------------
|
||||
|
||||
There used to be the pytest GitHub mirror. It was removed in favor of the
|
||||
Mercurial one, to remove confusion of people not knowing where it's better to
|
||||
put their issues and pull requests. Also it wasn't easily possible to automate
|
||||
the mirroring process.
|
||||
|
||||
However, it's still possible to use git to contribute to pytest using tools
|
||||
like `gitifyhg <https://github.com/buchuki/gitifyhg>`_ which allows you to
|
||||
clone and work with Mercurial repo still using git.
|
||||
|
||||
.. warning::
|
||||
Remember that git is **not** a default version control system for pytest and
|
||||
you need to be careful using it.
|
||||
40
ISSUES.txt
40
ISSUES.txt
@@ -122,8 +122,8 @@ customize test function collection
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
- introduce py.test.mark.nocollect for not considering a function for
|
||||
test collection at all. maybe also introduce a py.test.mark.test to
|
||||
- introduce pytest.mark.nocollect for not considering a function for
|
||||
test collection at all. maybe also introduce a pytest.mark.test to
|
||||
explicitely mark a function to become a tested one. Lookup JUnit ways
|
||||
of tagging tests.
|
||||
|
||||
@@ -135,18 +135,18 @@ in addition to the imperative pytest.importorskip also introduce
|
||||
a pytest.mark.importorskip so that the test count is more correct.
|
||||
|
||||
|
||||
introduce py.test.mark.platform
|
||||
introduce pytest.mark.platform
|
||||
-------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
Introduce nice-to-spell platform-skipping, examples:
|
||||
|
||||
@py.test.mark.platform("python3")
|
||||
@py.test.mark.platform("not python3")
|
||||
@py.test.mark.platform("win32 and not python3")
|
||||
@py.test.mark.platform("darwin")
|
||||
@py.test.mark.platform("not (jython and win32)")
|
||||
@py.test.mark.platform("not (jython and win32)", xfail=True)
|
||||
@pytest.mark.platform("python3")
|
||||
@pytest.mark.platform("not python3")
|
||||
@pytest.mark.platform("win32 and not python3")
|
||||
@pytest.mark.platform("darwin")
|
||||
@pytest.mark.platform("not (jython and win32)")
|
||||
@pytest.mark.platform("not (jython and win32)", xfail=True)
|
||||
|
||||
etc. Idea is to allow Python expressions which can operate
|
||||
on common spellings for operating systems and python
|
||||
@@ -181,8 +181,8 @@ tags: feature
|
||||
allow to name conftest.py files (in sub directories) that should
|
||||
be imported early, as to include command line options.
|
||||
|
||||
improve central py.test ini file
|
||||
----------------------------------
|
||||
improve central pytest ini file
|
||||
-------------------------------
|
||||
tags: feature
|
||||
|
||||
introduce more declarative configuration options:
|
||||
@@ -196,7 +196,7 @@ new documentation
|
||||
----------------------------------
|
||||
tags: feature
|
||||
|
||||
- logo py.test
|
||||
- logo pytest
|
||||
- examples for unittest or functional testing
|
||||
- resource management for functional testing
|
||||
- patterns: page object
|
||||
@@ -205,17 +205,17 @@ have imported module mismatch honour relative paths
|
||||
--------------------------------------------------------
|
||||
tags: bug
|
||||
|
||||
With 1.1.1 py.test fails at least on windows if an import
|
||||
With 1.1.1 pytest fails at least on windows if an import
|
||||
is relative and compared against an absolute conftest.py
|
||||
path. Normalize.
|
||||
|
||||
consider globals: py.test.ensuretemp and config
|
||||
consider globals: pytest.ensuretemp and config
|
||||
--------------------------------------------------------------
|
||||
tags: experimental-wish
|
||||
|
||||
consider deprecating py.test.ensuretemp and py.test.config
|
||||
to further reduce py.test globality. Also consider
|
||||
having py.test.config and ensuretemp coming from
|
||||
consider deprecating pytest.ensuretemp and pytest.config
|
||||
to further reduce pytest globality. Also consider
|
||||
having pytest.config and ensuretemp coming from
|
||||
a plugin rather than being there from the start.
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ consider pytest_addsyspath hook
|
||||
-----------------------------------------
|
||||
tags: wish
|
||||
|
||||
py.test could call a new pytest_addsyspath() in order to systematically
|
||||
pytest could call a new pytest_addsyspath() in order to systematically
|
||||
allow manipulation of sys.path and to inhibit it via --no-addsyspath
|
||||
in order to more easily run against installed packages.
|
||||
|
||||
@@ -232,11 +232,11 @@ and pytest_configure.
|
||||
|
||||
|
||||
|
||||
deprecate global py.test.config usage
|
||||
deprecate global pytest.config usage
|
||||
----------------------------------------------------------------
|
||||
tags: feature
|
||||
|
||||
py.test.ensuretemp and py.test.config are probably the last
|
||||
pytest.ensuretemp and pytest.config are probably the last
|
||||
objects containing global state. Often using them is not
|
||||
neccessary. This is about trying to get rid of them, i.e.
|
||||
deprecating them and checking with PyPy's usages as well
|
||||
|
||||
14
README.rst
14
README.rst
@@ -5,7 +5,7 @@ Changelog: http://pytest.org/latest/changelog.html
|
||||
|
||||
Issues: https://bitbucket.org/hpk42/pytest/issues?status=open
|
||||
|
||||
The ``py.test`` testing tool makes it easy to write small tests, yet
|
||||
The ``pytest`` testing tool makes it easy to write small tests, yet
|
||||
scales to support complex functional testing. It provides
|
||||
|
||||
- `auto-discovery
|
||||
@@ -14,17 +14,14 @@ scales to support complex functional testing. It provides
|
||||
- detailed info on failing `assert statements <http://pytest.org/latest/assert.html>`_ (no need to remember ``self.assert*`` names)
|
||||
- `modular fixtures <http://pytest.org/latest/fixture.html>`_ for
|
||||
managing small or parametrized long-lived test resources.
|
||||
- multi-paradigm support: you can use ``py.test`` to run test suites based
|
||||
- multi-paradigm support: you can use ``pytest`` to run test suites based
|
||||
on `unittest <http://pytest.org/latest/unittest.html>`_ (or trial),
|
||||
`nose <http://pytest.org/latest/nose.html>`_
|
||||
- single-source compatibility to Python2.4 all the way up to Python3.3,
|
||||
- single-source compatibility to Python2.5 all the way up to Python3.3,
|
||||
PyPy-1.9 and Jython-2.5.1.
|
||||
|
||||
- many `external plugins <http://pytest.org/latest/plugins.html#installing-external-plugins-searching>`_.
|
||||
|
||||
.. image:: https://secure.travis-ci.org/hpk42/pytest.png
|
||||
:target: http://travis-ci.org/hpk42/pytest
|
||||
|
||||
A simple example for a test::
|
||||
|
||||
# content of test_module.py
|
||||
@@ -42,11 +39,10 @@ and report bugs at:
|
||||
|
||||
http://bitbucket.org/hpk42/pytest/issues/
|
||||
|
||||
and checkout repos at:
|
||||
and checkout or fork repo at:
|
||||
|
||||
http://github.com/hpk42/pytest/ (mirror)
|
||||
http://bitbucket.org/hpk42/pytest/
|
||||
|
||||
|
||||
Copyright Holger Krekel and others, 2004-2013
|
||||
Copyright Holger Krekel and others, 2004-2014
|
||||
Licensed under the MIT license.
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#
|
||||
__version__ = '2.5.0'
|
||||
__version__ = '2.5.2'
|
||||
|
||||
@@ -80,10 +80,10 @@ def pytest_runtest_setup(item):
|
||||
if new_expl:
|
||||
# Don't include pageloads of data unless we are very
|
||||
# verbose (-vv)
|
||||
if (len(py.builtin._totext('').join(new_expl[1:])) > 80*8
|
||||
if (sum(len(p) for p in new_expl[1:]) > 80*8
|
||||
and item.config.option.verbose < 2):
|
||||
new_expl[1:] = [py.builtin._totext(
|
||||
'Detailed information truncated, use "-vv" to see')]
|
||||
'Detailed information truncated, use "-vv" to show')]
|
||||
res = py.builtin._totext('\n~').join(new_expl)
|
||||
if item.config.getvalue("assertmode") == "rewrite":
|
||||
# The result will be fed back a python % formatting
|
||||
|
||||
@@ -15,7 +15,7 @@ import py
|
||||
from _pytest.assertion import util
|
||||
|
||||
|
||||
# py.test caches rewritten pycs in __pycache__.
|
||||
# pytest caches rewritten pycs in __pycache__.
|
||||
if hasattr(imp, "get_tag"):
|
||||
PYTEST_TAG = imp.get_tag() + "-PYTEST"
|
||||
else:
|
||||
@@ -102,7 +102,7 @@ class AssertionRewritingHook(object):
|
||||
# the most magical part of the process: load the source, rewrite the
|
||||
# asserts, and load the rewritten source. We also cache the rewritten
|
||||
# module code in a special pyc. We must be aware of the possibility of
|
||||
# concurrent py.test processes rewriting and loading pycs. To avoid
|
||||
# concurrent pytest processes rewriting and loading pycs. To avoid
|
||||
# tricky race conditions, we maintain the following invariant: The
|
||||
# cached pyc is always a complete, valid pyc. Operations on it must be
|
||||
# atomic. POSIX's atomic rename comes in handy.
|
||||
@@ -290,7 +290,7 @@ def _make_rewritten_pyc(state, fn, pyc, co):
|
||||
os.rename(proc_pyc, pyc)
|
||||
|
||||
def _read_pyc(source, pyc):
|
||||
"""Possibly read a py.test pyc containing rewritten code.
|
||||
"""Possibly read a pytest pyc containing rewritten code.
|
||||
|
||||
Return rewritten code if successful or None if not.
|
||||
"""
|
||||
|
||||
@@ -2,13 +2,9 @@
|
||||
|
||||
import py
|
||||
try:
|
||||
from collections.abc import Sequence
|
||||
from collections import Sequence
|
||||
except ImportError:
|
||||
try:
|
||||
from collections import Sequence
|
||||
except ImportError:
|
||||
Sequence = list
|
||||
|
||||
Sequence = list
|
||||
|
||||
BuiltinAssertionError = py.builtin.builtins.AssertionError
|
||||
u = py.builtin._totext
|
||||
@@ -166,12 +162,18 @@ def assertrepr_compare(config, op, left, right):
|
||||
|
||||
|
||||
def _diff_text(left, right, verbose=False):
|
||||
"""Return the explanation for the diff between text
|
||||
"""Return the explanation for the diff between text or bytes
|
||||
|
||||
Unless --verbose is used this will skip leading and trailing
|
||||
characters which are identical to keep the diff minimal.
|
||||
|
||||
If the input are bytes they will be safely converted to text.
|
||||
"""
|
||||
explanation = []
|
||||
if isinstance(left, py.builtin.bytes):
|
||||
left = u(repr(left)[1:-1]).replace(r'\n', '\n')
|
||||
if isinstance(right, py.builtin.bytes):
|
||||
right = u(repr(right)[1:-1]).replace(r'\n', '\n')
|
||||
if not verbose:
|
||||
i = 0 # just in case left or right has zero length
|
||||
for i in range(min(len(left), len(right))):
|
||||
|
||||
@@ -1,17 +1,55 @@
|
||||
""" per-test stdout/stderr capturing mechanisms, ``capsys`` and ``capfd`` function arguments. """
|
||||
|
||||
import pytest, py
|
||||
"""
|
||||
per-test stdout/stderr capturing mechanisms,
|
||||
``capsys`` and ``capfd`` function arguments.
|
||||
"""
|
||||
# note: py.io capture was where copied from
|
||||
# pylib 1.4.20.dev2 (rev 13d9af95547e)
|
||||
import sys
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import py
|
||||
import pytest
|
||||
|
||||
try:
|
||||
from io import StringIO
|
||||
except ImportError:
|
||||
from StringIO import StringIO
|
||||
|
||||
try:
|
||||
from io import BytesIO
|
||||
except ImportError:
|
||||
class BytesIO(StringIO):
|
||||
def write(self, data):
|
||||
if isinstance(data, unicode):
|
||||
raise TypeError("not a byte value: %r" % (data,))
|
||||
StringIO.write(self, data)
|
||||
|
||||
if sys.version_info < (3, 0):
|
||||
class TextIO(StringIO):
|
||||
def write(self, data):
|
||||
if not isinstance(data, unicode):
|
||||
enc = getattr(self, '_encoding', 'UTF-8')
|
||||
data = unicode(data, enc, 'replace')
|
||||
StringIO.write(self, data)
|
||||
else:
|
||||
TextIO = StringIO
|
||||
|
||||
|
||||
patchsysdict = {0: 'stdin', 1: 'stdout', 2: 'stderr'}
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group._addoption('--capture', action="store", default=None,
|
||||
group._addoption(
|
||||
'--capture', action="store", default=None,
|
||||
metavar="method", choices=['fd', 'sys', 'no'],
|
||||
help="per-test capturing method: one of fd (default)|sys|no.")
|
||||
group._addoption('-s', action="store_const", const="no", dest="capture",
|
||||
group._addoption(
|
||||
'-s', action="store_const", const="no", dest="capture",
|
||||
help="shortcut for --capture=no.")
|
||||
|
||||
|
||||
@pytest.mark.tryfirst
|
||||
def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
|
||||
ns = parser.parse_known_args(args)
|
||||
@@ -22,13 +60,16 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
|
||||
method = "sys"
|
||||
capman = CaptureManager(method)
|
||||
early_config.pluginmanager.register(capman, "capturemanager")
|
||||
|
||||
# make sure that capturemanager is properly reset at final shutdown
|
||||
def teardown():
|
||||
try:
|
||||
capman.reset_capturings()
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
early_config.pluginmanager.add_shutdown(teardown)
|
||||
|
||||
# make sure logging does not raise exceptions at the end
|
||||
def silence_logging_at_shutdown():
|
||||
if "logging" in sys.modules:
|
||||
@@ -47,21 +88,27 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
|
||||
sys.stderr.write(err)
|
||||
raise
|
||||
|
||||
|
||||
def addouterr(rep, outerr):
|
||||
for secname, content in zip(["out", "err"], outerr):
|
||||
if content:
|
||||
rep.sections.append(("Captured std%s" % secname, content))
|
||||
|
||||
|
||||
class NoCapture:
|
||||
def startall(self):
|
||||
pass
|
||||
|
||||
def resume(self):
|
||||
pass
|
||||
|
||||
def reset(self):
|
||||
pass
|
||||
|
||||
def suspend(self):
|
||||
return "", ""
|
||||
|
||||
|
||||
class CaptureManager:
|
||||
def __init__(self, defaultmethod=None):
|
||||
self._method2capture = {}
|
||||
@@ -69,21 +116,23 @@ class CaptureManager:
|
||||
|
||||
def _maketempfile(self):
|
||||
f = py.std.tempfile.TemporaryFile()
|
||||
newf = py.io.dupfile(f, encoding="UTF-8")
|
||||
newf = dupfile(f, encoding="UTF-8")
|
||||
f.close()
|
||||
return newf
|
||||
|
||||
def _makestringio(self):
|
||||
return py.io.TextIO()
|
||||
return TextIO()
|
||||
|
||||
def _getcapture(self, method):
|
||||
if method == "fd":
|
||||
return py.io.StdCaptureFD(now=False,
|
||||
out=self._maketempfile(), err=self._maketempfile()
|
||||
return StdCaptureFD(
|
||||
out=self._maketempfile(),
|
||||
err=self._maketempfile(),
|
||||
)
|
||||
elif method == "sys":
|
||||
return py.io.StdCapture(now=False,
|
||||
out=self._makestringio(), err=self._makestringio()
|
||||
return StdCapture(
|
||||
out=self._makestringio(),
|
||||
err=self._makestringio(),
|
||||
)
|
||||
elif method == "no":
|
||||
return NoCapture()
|
||||
@@ -98,23 +147,24 @@ class CaptureManager:
|
||||
method = config._conftest.rget("option_capture", path=fspath)
|
||||
except KeyError:
|
||||
method = "fd"
|
||||
if method == "fd" and not hasattr(os, 'dup'): # e.g. jython
|
||||
if method == "fd" and not hasattr(os, 'dup'): # e.g. jython
|
||||
method = "sys"
|
||||
return method
|
||||
|
||||
def reset_capturings(self):
|
||||
for name, cap in self._method2capture.items():
|
||||
for cap in self._method2capture.values():
|
||||
cap.reset()
|
||||
|
||||
def resumecapture_item(self, item):
|
||||
method = self._getmethod(item.config, item.fspath)
|
||||
if not hasattr(item, 'outerr'):
|
||||
item.outerr = ('', '') # we accumulate outerr on the item
|
||||
item.outerr = ('', '') # we accumulate outerr on the item
|
||||
return self.resumecapture(method)
|
||||
|
||||
def resumecapture(self, method=None):
|
||||
if hasattr(self, '_capturing'):
|
||||
raise ValueError("cannot resume, already capturing with %r" %
|
||||
raise ValueError(
|
||||
"cannot resume, already capturing with %r" %
|
||||
(self._capturing,))
|
||||
if method is None:
|
||||
method = self._defaultmethod
|
||||
@@ -163,8 +213,9 @@ class CaptureManager:
|
||||
try:
|
||||
self.resumecapture(method)
|
||||
except ValueError:
|
||||
return # recursive collect, XXX refactor capturing
|
||||
# to allow for more lightweight recursive capturing
|
||||
# recursive collect, XXX refactor capturing
|
||||
# to allow for more lightweight recursive capturing
|
||||
return
|
||||
try:
|
||||
rep = __multicall__.execute()
|
||||
finally:
|
||||
@@ -205,6 +256,7 @@ class CaptureManager:
|
||||
|
||||
error_capsysfderror = "cannot use capsys and capfd at the same time"
|
||||
|
||||
|
||||
def pytest_funcarg__capsys(request):
|
||||
"""enables capturing of writes to sys.stdout/sys.stderr and makes
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
@@ -212,7 +264,8 @@ def pytest_funcarg__capsys(request):
|
||||
"""
|
||||
if "capfd" in request._funcargs:
|
||||
raise request.raiseerror(error_capsysfderror)
|
||||
return CaptureFixture(py.io.StdCapture)
|
||||
return CaptureFixture(StdCapture)
|
||||
|
||||
|
||||
def pytest_funcarg__capfd(request):
|
||||
"""enables capturing of writes to file descriptors 1 and 2 and makes
|
||||
@@ -223,26 +276,337 @@ def pytest_funcarg__capfd(request):
|
||||
request.raiseerror(error_capsysfderror)
|
||||
if not hasattr(os, 'dup'):
|
||||
pytest.skip("capfd funcarg needs os.dup")
|
||||
return CaptureFixture(py.io.StdCaptureFD)
|
||||
return CaptureFixture(StdCaptureFD)
|
||||
|
||||
|
||||
class CaptureFixture:
|
||||
def __init__(self, captureclass):
|
||||
self.capture = captureclass(now=False)
|
||||
self._capture = captureclass()
|
||||
|
||||
def _start(self):
|
||||
self.capture.startall()
|
||||
self._capture.startall()
|
||||
|
||||
def _finalize(self):
|
||||
if hasattr(self, 'capture'):
|
||||
outerr = self._outerr = self.capture.reset()
|
||||
del self.capture
|
||||
if hasattr(self, '_capture'):
|
||||
outerr = self._outerr = self._capture.reset()
|
||||
del self._capture
|
||||
return outerr
|
||||
|
||||
def readouterr(self):
|
||||
try:
|
||||
return self.capture.readouterr()
|
||||
return self._capture.readouterr()
|
||||
except AttributeError:
|
||||
return self._outerr
|
||||
|
||||
def close(self):
|
||||
self._finalize()
|
||||
|
||||
|
||||
class FDCapture:
|
||||
""" Capture IO to/from a given os-level filedescriptor. """
|
||||
|
||||
def __init__(self, targetfd, tmpfile=None, patchsys=False):
|
||||
""" save targetfd descriptor, and open a new
|
||||
temporary file there. If no tmpfile is
|
||||
specified a tempfile.Tempfile() will be opened
|
||||
in text mode.
|
||||
"""
|
||||
self.targetfd = targetfd
|
||||
if tmpfile is None and targetfd != 0:
|
||||
f = tempfile.TemporaryFile('wb+')
|
||||
tmpfile = dupfile(f, encoding="UTF-8")
|
||||
f.close()
|
||||
self.tmpfile = tmpfile
|
||||
self._savefd = os.dup(self.targetfd)
|
||||
if patchsys:
|
||||
self._oldsys = getattr(sys, patchsysdict[targetfd])
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
os.fstat(self._savefd)
|
||||
except OSError:
|
||||
raise ValueError(
|
||||
"saved filedescriptor not valid, "
|
||||
"did you call start() twice?")
|
||||
if self.targetfd == 0 and not self.tmpfile:
|
||||
fd = os.open(os.devnull, os.O_RDONLY)
|
||||
os.dup2(fd, 0)
|
||||
os.close(fd)
|
||||
if hasattr(self, '_oldsys'):
|
||||
setattr(sys, patchsysdict[self.targetfd], DontReadFromInput())
|
||||
else:
|
||||
os.dup2(self.tmpfile.fileno(), self.targetfd)
|
||||
if hasattr(self, '_oldsys'):
|
||||
setattr(sys, patchsysdict[self.targetfd], self.tmpfile)
|
||||
|
||||
def done(self):
|
||||
""" unpatch and clean up, returns the self.tmpfile (file object)
|
||||
"""
|
||||
os.dup2(self._savefd, self.targetfd)
|
||||
os.close(self._savefd)
|
||||
if self.targetfd != 0:
|
||||
self.tmpfile.seek(0)
|
||||
if hasattr(self, '_oldsys'):
|
||||
setattr(sys, patchsysdict[self.targetfd], self._oldsys)
|
||||
return self.tmpfile
|
||||
|
||||
def writeorg(self, data):
|
||||
""" write a string to the original file descriptor
|
||||
"""
|
||||
tempfp = tempfile.TemporaryFile()
|
||||
try:
|
||||
os.dup2(self._savefd, tempfp.fileno())
|
||||
tempfp.write(data)
|
||||
finally:
|
||||
tempfp.close()
|
||||
|
||||
|
||||
def dupfile(f, mode=None, buffering=0, raising=False, encoding=None):
|
||||
""" return a new open file object that's a duplicate of f
|
||||
|
||||
mode is duplicated if not given, 'buffering' controls
|
||||
buffer size (defaulting to no buffering) and 'raising'
|
||||
defines whether an exception is raised when an incompatible
|
||||
file object is passed in (if raising is False, the file
|
||||
object itself will be returned)
|
||||
"""
|
||||
try:
|
||||
fd = f.fileno()
|
||||
mode = mode or f.mode
|
||||
except AttributeError:
|
||||
if raising:
|
||||
raise
|
||||
return f
|
||||
newfd = os.dup(fd)
|
||||
if sys.version_info >= (3, 0):
|
||||
if encoding is not None:
|
||||
mode = mode.replace("b", "")
|
||||
buffering = True
|
||||
return os.fdopen(newfd, mode, buffering, encoding, closefd=True)
|
||||
else:
|
||||
f = os.fdopen(newfd, mode, buffering)
|
||||
if encoding is not None:
|
||||
return EncodedFile(f, encoding)
|
||||
return f
|
||||
|
||||
|
||||
class EncodedFile(object):
|
||||
def __init__(self, _stream, encoding):
|
||||
self._stream = _stream
|
||||
self.encoding = encoding
|
||||
|
||||
def write(self, obj):
|
||||
if isinstance(obj, unicode):
|
||||
obj = obj.encode(self.encoding)
|
||||
self._stream.write(obj)
|
||||
|
||||
def writelines(self, linelist):
|
||||
data = ''.join(linelist)
|
||||
self.write(data)
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self._stream, name)
|
||||
|
||||
|
||||
class Capture(object):
|
||||
def reset(self):
|
||||
""" reset sys.stdout/stderr and return captured output as strings. """
|
||||
if hasattr(self, '_reset'):
|
||||
raise ValueError("was already reset")
|
||||
self._reset = True
|
||||
outfile, errfile = self.done(save=False)
|
||||
out, err = "", ""
|
||||
if outfile and not outfile.closed:
|
||||
out = outfile.read()
|
||||
outfile.close()
|
||||
if errfile and errfile != outfile and not errfile.closed:
|
||||
err = errfile.read()
|
||||
errfile.close()
|
||||
return out, err
|
||||
|
||||
def suspend(self):
|
||||
""" return current snapshot captures, memorize tempfiles. """
|
||||
outerr = self.readouterr()
|
||||
outfile, errfile = self.done()
|
||||
return outerr
|
||||
|
||||
|
||||
class StdCaptureFD(Capture):
|
||||
""" This class allows to capture writes to FD1 and FD2
|
||||
and may connect a NULL file to FD0 (and prevent
|
||||
reads from sys.stdin). If any of the 0,1,2 file descriptors
|
||||
is invalid it will not be captured.
|
||||
"""
|
||||
def __init__(self, out=True, err=True, in_=True, patchsys=True):
|
||||
self._options = {
|
||||
"out": out,
|
||||
"err": err,
|
||||
"in_": in_,
|
||||
"patchsys": patchsys,
|
||||
}
|
||||
self._save()
|
||||
|
||||
def _save(self):
|
||||
in_ = self._options['in_']
|
||||
out = self._options['out']
|
||||
err = self._options['err']
|
||||
patchsys = self._options['patchsys']
|
||||
if in_:
|
||||
try:
|
||||
self.in_ = FDCapture(
|
||||
0, tmpfile=None,
|
||||
patchsys=patchsys)
|
||||
except OSError:
|
||||
pass
|
||||
if out:
|
||||
tmpfile = None
|
||||
if hasattr(out, 'write'):
|
||||
tmpfile = out
|
||||
try:
|
||||
self.out = FDCapture(
|
||||
1, tmpfile=tmpfile,
|
||||
patchsys=patchsys)
|
||||
self._options['out'] = self.out.tmpfile
|
||||
except OSError:
|
||||
pass
|
||||
if err:
|
||||
if hasattr(err, 'write'):
|
||||
tmpfile = err
|
||||
else:
|
||||
tmpfile = None
|
||||
try:
|
||||
self.err = FDCapture(
|
||||
2, tmpfile=tmpfile,
|
||||
patchsys=patchsys)
|
||||
self._options['err'] = self.err.tmpfile
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def startall(self):
|
||||
if hasattr(self, 'in_'):
|
||||
self.in_.start()
|
||||
if hasattr(self, 'out'):
|
||||
self.out.start()
|
||||
if hasattr(self, 'err'):
|
||||
self.err.start()
|
||||
|
||||
def resume(self):
|
||||
""" resume capturing with original temp files. """
|
||||
self.startall()
|
||||
|
||||
def done(self, save=True):
|
||||
""" return (outfile, errfile) and stop capturing. """
|
||||
outfile = errfile = None
|
||||
if hasattr(self, 'out') and not self.out.tmpfile.closed:
|
||||
outfile = self.out.done()
|
||||
if hasattr(self, 'err') and not self.err.tmpfile.closed:
|
||||
errfile = self.err.done()
|
||||
if hasattr(self, 'in_'):
|
||||
self.in_.done()
|
||||
if save:
|
||||
self._save()
|
||||
return outfile, errfile
|
||||
|
||||
def readouterr(self):
|
||||
""" return snapshot value of stdout/stderr capturings. """
|
||||
out = self._readsnapshot('out')
|
||||
err = self._readsnapshot('err')
|
||||
return out, err
|
||||
|
||||
def _readsnapshot(self, name):
|
||||
if hasattr(self, name):
|
||||
f = getattr(self, name).tmpfile
|
||||
else:
|
||||
return ''
|
||||
|
||||
f.seek(0)
|
||||
res = f.read()
|
||||
enc = getattr(f, "encoding", None)
|
||||
if enc:
|
||||
res = py.builtin._totext(res, enc, "replace")
|
||||
f.truncate(0)
|
||||
f.seek(0)
|
||||
return res
|
||||
|
||||
|
||||
class StdCapture(Capture):
|
||||
""" This class allows to capture writes to sys.stdout|stderr "in-memory"
|
||||
and will raise errors on tries to read from sys.stdin. It only
|
||||
modifies sys.stdout|stderr|stdin attributes and does not
|
||||
touch underlying File Descriptors (use StdCaptureFD for that).
|
||||
"""
|
||||
def __init__(self, out=True, err=True, in_=True):
|
||||
self._oldout = sys.stdout
|
||||
self._olderr = sys.stderr
|
||||
self._oldin = sys.stdin
|
||||
if out and not hasattr(out, 'file'):
|
||||
out = TextIO()
|
||||
self.out = out
|
||||
if err:
|
||||
if not hasattr(err, 'write'):
|
||||
err = TextIO()
|
||||
self.err = err
|
||||
self.in_ = in_
|
||||
|
||||
def startall(self):
|
||||
if self.out:
|
||||
sys.stdout = self.out
|
||||
if self.err:
|
||||
sys.stderr = self.err
|
||||
if self.in_:
|
||||
sys.stdin = self.in_ = DontReadFromInput()
|
||||
|
||||
def done(self, save=True):
|
||||
""" return (outfile, errfile) and stop capturing. """
|
||||
outfile = errfile = None
|
||||
if self.out and not self.out.closed:
|
||||
sys.stdout = self._oldout
|
||||
outfile = self.out
|
||||
outfile.seek(0)
|
||||
if self.err and not self.err.closed:
|
||||
sys.stderr = self._olderr
|
||||
errfile = self.err
|
||||
errfile.seek(0)
|
||||
if self.in_:
|
||||
sys.stdin = self._oldin
|
||||
return outfile, errfile
|
||||
|
||||
def resume(self):
|
||||
""" resume capturing with original temp files. """
|
||||
self.startall()
|
||||
|
||||
def readouterr(self):
|
||||
""" return snapshot value of stdout/stderr capturings. """
|
||||
out = err = ""
|
||||
if self.out:
|
||||
out = self.out.getvalue()
|
||||
self.out.truncate(0)
|
||||
self.out.seek(0)
|
||||
if self.err:
|
||||
err = self.err.getvalue()
|
||||
self.err.truncate(0)
|
||||
self.err.seek(0)
|
||||
return out, err
|
||||
|
||||
|
||||
class DontReadFromInput:
|
||||
"""Temporary stub class. Ideally when stdin is accessed, the
|
||||
capturing should be turned off, with possibly all data captured
|
||||
so far sent to the screen. This should be configurable, though,
|
||||
because in automated test runs it is better to crash than
|
||||
hang indefinitely.
|
||||
"""
|
||||
def read(self, *args):
|
||||
raise IOError("reading from stdin while output is captured")
|
||||
readline = read
|
||||
readlines = read
|
||||
__iter__ = read
|
||||
|
||||
def fileno(self):
|
||||
raise ValueError("redirected Stdin is pseudofile, has no fileno()")
|
||||
|
||||
def isatty(self):
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
""" command line options, ini-file and conftest.py processing. """
|
||||
|
||||
import py
|
||||
# DON't import pytest here because it causes import cycle troubles
|
||||
import sys, os
|
||||
from _pytest import hookspec # the extension point definitions
|
||||
from _pytest.core import PluginManager
|
||||
@@ -22,7 +23,7 @@ class cmdline: # compatibility namespace
|
||||
main = staticmethod(main)
|
||||
|
||||
class UsageError(Exception):
|
||||
""" error in py.test usage or invocation"""
|
||||
""" error in pytest usage or invocation"""
|
||||
|
||||
_preinit = []
|
||||
|
||||
@@ -128,8 +129,8 @@ class Parser:
|
||||
|
||||
:opts: option names, can be short or long options.
|
||||
:attrs: same attributes which the ``add_option()`` function of the
|
||||
`optparse library
|
||||
<http://docs.python.org/library/optparse.html#module-optparse>`_
|
||||
`argparse library
|
||||
<http://docs.python.org/2/library/argparse.html>`_
|
||||
accepts.
|
||||
|
||||
After command line parsing options are available on the pytest config
|
||||
@@ -225,7 +226,7 @@ class Argument:
|
||||
help = attrs['help']
|
||||
if '%default' in help:
|
||||
py.std.warnings.warn(
|
||||
'py.test now uses argparse. "%default" should be'
|
||||
'pytest now uses argparse. "%default" should be'
|
||||
' changed to "%(default)s" ',
|
||||
FutureWarning,
|
||||
stacklevel=3)
|
||||
@@ -448,7 +449,7 @@ class DropShorterLongHelpFormatter(py.std.argparse.HelpFormatter):
|
||||
|
||||
class Conftest(object):
|
||||
""" the single place for accessing values and interacting
|
||||
towards conftest modules from py.test objects.
|
||||
towards conftest modules from pytest objects.
|
||||
"""
|
||||
def __init__(self, onimport=None, confcutdir=None):
|
||||
self._path2confmods = {}
|
||||
@@ -808,7 +809,7 @@ class Config(object):
|
||||
|
||||
def getvalueorskip(self, name, path=None):
|
||||
""" (deprecated) return getvalue(name) or call
|
||||
py.test.skip if no value exists. """
|
||||
pytest.skip if no value exists. """
|
||||
__tracebackhide__ = True
|
||||
try:
|
||||
val = self.getvalue(name, path)
|
||||
|
||||
@@ -4,6 +4,7 @@ pytest PluginManager, basic initialization and tracing.
|
||||
import sys
|
||||
import inspect
|
||||
import py
|
||||
# don't import pytest to avoid circular imports
|
||||
|
||||
assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: "
|
||||
"%s is too old, remove or upgrade 'py'" % (py.__version__))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
""" generate a single-file self-contained version of py.test """
|
||||
""" generate a single-file self-contained version of pytest """
|
||||
import py
|
||||
import sys
|
||||
|
||||
@@ -55,7 +55,7 @@ def pytest_addoption(parser):
|
||||
group = parser.getgroup("debugconfig")
|
||||
group.addoption("--genscript", action="store", default=None,
|
||||
dest="genscript", metavar="path",
|
||||
help="create standalone py.test script at given target path.")
|
||||
help="create standalone pytest script at given target path.")
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
genscript = config.getvalue("genscript")
|
||||
@@ -70,7 +70,7 @@ def pytest_cmdline_main(config):
|
||||
"or below due to 'argparse' dependency. Use python2.6 "
|
||||
"to generate a python2.5/6 compatible script", red=True)
|
||||
script = generate_script(
|
||||
'import py; raise SystemExit(py.test.cmdline.main())',
|
||||
'import pytest; raise SystemExit(pytest.cmdline.main())',
|
||||
deps,
|
||||
)
|
||||
genscript = py.path.local(genscript)
|
||||
|
||||
@@ -12,7 +12,9 @@ def pytest_addoption(parser):
|
||||
help="show help message and configuration info")
|
||||
group._addoption('-p', action="append", dest="plugins", default = [],
|
||||
metavar="name",
|
||||
help="early-load given plugin (multi-allowed).")
|
||||
help="early-load given plugin (multi-allowed). "
|
||||
"To avoid loading of plugins, use the `no:` prefix, e.g. "
|
||||
"`no:doctest`.")
|
||||
group.addoption('--traceconfig', '--trace-config',
|
||||
action="store_true", default=False,
|
||||
help="trace considerations of conftest.py files."),
|
||||
@@ -46,7 +48,7 @@ def pytest_unconfigure(config):
|
||||
def pytest_cmdline_main(config):
|
||||
if config.option.version:
|
||||
p = py.path.local(pytest.__file__)
|
||||
sys.stderr.write("This is py.test version %s, imported from %s\n" %
|
||||
sys.stderr.write("This is pytest version %s, imported from %s\n" %
|
||||
(pytest.__version__, p))
|
||||
plugininfo = getpluginversioninfo(config)
|
||||
if plugininfo:
|
||||
@@ -82,6 +84,8 @@ def showhelp(config):
|
||||
#tw.sep("=")
|
||||
tw.line("to see available markers type: py.test --markers")
|
||||
tw.line("to see available fixtures type: py.test --fixtures")
|
||||
tw.line("(shown according to specified file_or_dir or current dir "
|
||||
"if not specified)")
|
||||
return
|
||||
|
||||
tw.line("conftest.py options:")
|
||||
|
||||
@@ -11,8 +11,8 @@ def pytest_addhooks(pluginmanager):
|
||||
|
||||
def pytest_namespace():
|
||||
"""return dict of name->object to be made globally available in
|
||||
the py.test/pytest namespace. This hook is called before command
|
||||
line options are parsed.
|
||||
the pytest namespace. This hook is called before command line options
|
||||
are parsed.
|
||||
"""
|
||||
|
||||
def pytest_cmdline_parse(pluginmanager, args):
|
||||
|
||||
@@ -130,36 +130,36 @@ class LogXML(object):
|
||||
self.skipped += 1
|
||||
else:
|
||||
fail = Junit.failure(message="test failure")
|
||||
fail.append(unicode(report.longrepr))
|
||||
fail.append(bin_xml_escape(report.longrepr))
|
||||
self.append(fail)
|
||||
self.failed += 1
|
||||
self._write_captured_output(report)
|
||||
|
||||
def append_collect_failure(self, report):
|
||||
#msg = str(report.longrepr.reprtraceback.extraline)
|
||||
self.append(Junit.failure(unicode(report.longrepr),
|
||||
self.append(Junit.failure(bin_xml_escape(report.longrepr),
|
||||
message="collection failure"))
|
||||
self.errors += 1
|
||||
|
||||
def append_collect_skipped(self, report):
|
||||
#msg = str(report.longrepr.reprtraceback.extraline)
|
||||
self.append(Junit.skipped(unicode(report.longrepr),
|
||||
self.append(Junit.skipped(bin_xml_escape(report.longrepr),
|
||||
message="collection skipped"))
|
||||
self.skipped += 1
|
||||
|
||||
def append_error(self, report):
|
||||
self.append(Junit.error(unicode(report.longrepr),
|
||||
self.append(Junit.error(bin_xml_escape(report.longrepr),
|
||||
message="test setup failure"))
|
||||
self.errors += 1
|
||||
|
||||
def append_skipped(self, report):
|
||||
if hasattr(report, "wasxfail"):
|
||||
self.append(Junit.skipped(unicode(report.wasxfail),
|
||||
self.append(Junit.skipped(bin_xml_escape(report.wasxfail),
|
||||
message="expected test failure"))
|
||||
else:
|
||||
filename, lineno, skipreason = report.longrepr
|
||||
if skipreason.startswith("Skipped: "):
|
||||
skipreason = skipreason[9:]
|
||||
skipreason = bin_xml_escape(skipreason[9:])
|
||||
self.append(
|
||||
Junit.skipped("%s:%s: %s" % report.longrepr,
|
||||
type="pytest.skip",
|
||||
@@ -193,7 +193,7 @@ class LogXML(object):
|
||||
|
||||
def pytest_internalerror(self, excrepr):
|
||||
self.errors += 1
|
||||
data = py.xml.escape(excrepr)
|
||||
data = bin_xml_escape(excrepr)
|
||||
self.tests.append(
|
||||
Junit.testcase(
|
||||
Junit.error(data, message="internal error"),
|
||||
|
||||
@@ -63,7 +63,7 @@ def pytest_namespace():
|
||||
return dict(collect=collect)
|
||||
|
||||
def pytest_configure(config):
|
||||
py.test.config = config # compatibiltiy
|
||||
pytest.config = config # compatibiltiy
|
||||
if config.option.exitfirst:
|
||||
config.option.maxfail = 1
|
||||
|
||||
@@ -80,8 +80,9 @@ def wrap_session(config, doit):
|
||||
initstate = 2
|
||||
doit(config, session)
|
||||
except pytest.UsageError:
|
||||
msg = sys.exc_info()[1].args[0]
|
||||
sys.stderr.write("ERROR: %s\n" %(msg,))
|
||||
args = sys.exc_info()[1].args
|
||||
for msg in args:
|
||||
sys.stderr.write("ERROR: %s\n" %(msg,))
|
||||
session.exitstatus = EXIT_USAGEERROR
|
||||
except KeyboardInterrupt:
|
||||
excinfo = py.code.ExceptionInfo()
|
||||
@@ -538,9 +539,12 @@ class Session(FSCollector):
|
||||
self.ihook.pytest_collectreport(report=rep)
|
||||
self.trace.root.indent -= 1
|
||||
if self._notfound:
|
||||
errors = []
|
||||
for arg, exc in self._notfound:
|
||||
line = "(no name %r in any of %r)" % (arg, exc.args[0])
|
||||
raise pytest.UsageError("not found: %s\n%s" %(arg, line))
|
||||
errors.append("not found: %s\n%s" % (arg, line))
|
||||
#XXX: test this
|
||||
raise pytest.UsageError(*errors)
|
||||
if not genitems:
|
||||
return rep.result
|
||||
else:
|
||||
@@ -561,8 +565,7 @@ class Session(FSCollector):
|
||||
# we are inside a make_report hook so
|
||||
# we cannot directly pass through the exception
|
||||
self._notfound.append((arg, sys.exc_info()[1]))
|
||||
self.trace.root.indent -= 1
|
||||
break
|
||||
|
||||
self.trace.root.indent -= 1
|
||||
|
||||
def _collect(self, arg):
|
||||
|
||||
@@ -157,10 +157,10 @@ def pytest_configure(config):
|
||||
|
||||
class MarkGenerator:
|
||||
""" Factory for :class:`MarkDecorator` objects - exposed as
|
||||
a ``py.test.mark`` singleton instance. Example::
|
||||
a ``pytest.mark`` singleton instance. Example::
|
||||
|
||||
import py
|
||||
@py.test.mark.slowtest
|
||||
@pytest.mark.slowtest
|
||||
def test_function():
|
||||
pass
|
||||
|
||||
@@ -169,7 +169,7 @@ class MarkGenerator:
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name[0] == "_":
|
||||
raise AttributeError(name)
|
||||
raise AttributeError("Marker name must NOT start with underscore")
|
||||
if hasattr(self, '_config'):
|
||||
self._check(name)
|
||||
return MarkDecorator(name)
|
||||
@@ -198,14 +198,32 @@ class MarkDecorator:
|
||||
:ref:`retrieved by hooks as item keywords <excontrolskip>`.
|
||||
MarkDecorator instances are often created like this::
|
||||
|
||||
mark1 = py.test.mark.NAME # simple MarkDecorator
|
||||
mark2 = py.test.mark.NAME(name1=value) # parametrized MarkDecorator
|
||||
mark1 = pytest.mark.NAME # simple MarkDecorator
|
||||
mark2 = pytest.mark.NAME(name1=value) # parametrized MarkDecorator
|
||||
|
||||
and can then be applied as decorators to test functions::
|
||||
|
||||
@mark2
|
||||
def test_function():
|
||||
pass
|
||||
|
||||
When a MarkDecorator instance is called it does the following:
|
||||
1. If called with a single class as its only positional argument and no
|
||||
additional keyword arguments, it attaches itself to the class so it
|
||||
gets applied automatically to all test cases found in that class.
|
||||
2. If called with a single function as its only positional argument and
|
||||
no additional keyword arguments, it attaches a MarkInfo object to the
|
||||
function, containing all the arguments already stored internally in
|
||||
the MarkDecorator.
|
||||
3. When called in any other case, it performs a 'fake construction' call,
|
||||
i.e. it returns a new MarkDecorator instance with the original
|
||||
MarkDecorator's content updated with the arguments passed to this
|
||||
call.
|
||||
|
||||
Note: The rules above prevent MarkDecorator objects from storing only a
|
||||
single function or class reference as their positional argument with no
|
||||
additional keyword or positional arguments.
|
||||
|
||||
"""
|
||||
def __init__(self, name, args=None, kwargs=None):
|
||||
self.name = name
|
||||
@@ -224,7 +242,7 @@ class MarkDecorator:
|
||||
def __call__(self, *args, **kwargs):
|
||||
""" if passed a single callable argument: decorate it with mark info.
|
||||
otherwise add *args/**kwargs in-place to mark information. """
|
||||
if args:
|
||||
if args and not kwargs:
|
||||
func = args[0]
|
||||
if len(args) == 1 and (istestfunc(func) or
|
||||
hasattr(func, '__bases__')):
|
||||
|
||||
@@ -8,7 +8,7 @@ def pytest_runtest_makereport(__multicall__, item, call):
|
||||
SkipTest = getattr(sys.modules.get('nose', None), 'SkipTest', None)
|
||||
if SkipTest:
|
||||
if call.excinfo and call.excinfo.errisinstance(SkipTest):
|
||||
# let's substitute the excinfo with a py.test.skip one
|
||||
# let's substitute the excinfo with a pytest.skip one
|
||||
call2 = call.__class__(lambda:
|
||||
pytest.skip(str(call.excinfo.value)), call.when)
|
||||
call.excinfo = call2.excinfo
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
""" (disabled by default) support for testing py.test and py.test plugins. """
|
||||
""" (disabled by default) support for testing pytest and pytest plugins. """
|
||||
|
||||
import py, pytest
|
||||
import sys, os
|
||||
@@ -137,7 +137,7 @@ class HookRecorder:
|
||||
break
|
||||
print_("NONAMEMATCH", name, "with", call)
|
||||
else:
|
||||
py.test.fail("could not find %r check %r" % (name, check))
|
||||
pytest.fail("could not find %r check %r" % (name, check))
|
||||
|
||||
def popcall(self, name):
|
||||
__tracebackhide__ = True
|
||||
@@ -147,7 +147,7 @@ class HookRecorder:
|
||||
return call
|
||||
lines = ["could not find call %r, in:" % (name,)]
|
||||
lines.extend([" %s" % str(x) for x in self.calls])
|
||||
py.test.fail("\n".join(lines))
|
||||
pytest.fail("\n".join(lines))
|
||||
|
||||
def getcall(self, name):
|
||||
l = self.getcalls(name)
|
||||
@@ -467,12 +467,12 @@ class TmpTestdir:
|
||||
|
||||
def _getpybinargs(self, scriptname):
|
||||
if not self.request.config.getvalue("notoolsonpath"):
|
||||
# XXX we rely on script refering to the correct environment
|
||||
# XXX we rely on script referring to the correct environment
|
||||
# we cannot use "(py.std.sys.executable,script)"
|
||||
# becaue on windows the script is e.g. a py.test.exe
|
||||
# because on windows the script is e.g. a py.test.exe
|
||||
return (py.std.sys.executable, _pytest_fullpath,) # noqa
|
||||
else:
|
||||
py.test.skip("cannot run %r with --no-tools-on-path" % scriptname)
|
||||
pytest.skip("cannot run %r with --no-tools-on-path" % scriptname)
|
||||
|
||||
def runpython(self, script, prepend=True):
|
||||
if prepend:
|
||||
@@ -509,14 +509,14 @@ class TmpTestdir:
|
||||
|
||||
def spawn_pytest(self, string, expect_timeout=10.0):
|
||||
if self.request.config.getvalue("notoolsonpath"):
|
||||
py.test.skip("--no-tools-on-path prevents running pexpect-spawn tests")
|
||||
pytest.skip("--no-tools-on-path prevents running pexpect-spawn tests")
|
||||
basetemp = self.tmpdir.mkdir("pexpect")
|
||||
invoke = " ".join(map(str, self._getpybinargs("py.test")))
|
||||
cmd = "%s --basetemp=%s %s" % (invoke, basetemp, string)
|
||||
return self.spawn(cmd, expect_timeout=expect_timeout)
|
||||
|
||||
def spawn(self, cmd, expect_timeout=10.0):
|
||||
pexpect = py.test.importorskip("pexpect", "3.0")
|
||||
pexpect = pytest.importorskip("pexpect", "3.0")
|
||||
if hasattr(sys, 'pypy_version_info') and '64' in py.std.platform.machine():
|
||||
pytest.skip("pypy-64 bit not supported")
|
||||
if sys.platform == "darwin":
|
||||
@@ -688,4 +688,4 @@ class LineMatcher:
|
||||
show(" and:", repr(nextline))
|
||||
extralines.append(nextline)
|
||||
else:
|
||||
py.test.fail("remains unmatched: %r, see stderr" % (line,))
|
||||
pytest.fail("remains unmatched: %r, see stderr" % (line,))
|
||||
|
||||
@@ -35,11 +35,13 @@ def getimfunc(func):
|
||||
|
||||
|
||||
class FixtureFunctionMarker:
|
||||
def __init__(self, scope, params, autouse=False, yieldctx=False):
|
||||
def __init__(self, scope, params,
|
||||
autouse=False, yieldctx=False, ids=None):
|
||||
self.scope = scope
|
||||
self.params = params
|
||||
self.autouse = autouse
|
||||
self.yieldctx = yieldctx
|
||||
self.ids = ids
|
||||
|
||||
def __call__(self, function):
|
||||
if inspect.isclass(function):
|
||||
@@ -49,7 +51,7 @@ class FixtureFunctionMarker:
|
||||
return function
|
||||
|
||||
|
||||
def fixture(scope="function", params=None, autouse=False):
|
||||
def fixture(scope="function", params=None, autouse=False, ids=None):
|
||||
""" (return a) decorator to mark a fixture factory function.
|
||||
|
||||
This decorator can be used (with or or without parameters) to define
|
||||
@@ -71,6 +73,10 @@ def fixture(scope="function", params=None, autouse=False):
|
||||
can see it. If False (the default) then an explicit
|
||||
reference is needed to activate the fixture.
|
||||
|
||||
:arg ids: list of string ids each corresponding to the params
|
||||
so that they are part of the test id. If no ids are provided
|
||||
they will be generated automatically from the params.
|
||||
|
||||
"""
|
||||
if callable(scope) and params is None and autouse == False:
|
||||
# direct decoration
|
||||
@@ -78,9 +84,9 @@ def fixture(scope="function", params=None, autouse=False):
|
||||
"function", params, autouse)(scope)
|
||||
if params is not None and not isinstance(params, (list, tuple)):
|
||||
params = list(params)
|
||||
return FixtureFunctionMarker(scope, params, autouse)
|
||||
return FixtureFunctionMarker(scope, params, autouse, ids=ids)
|
||||
|
||||
def yield_fixture(scope="function", params=None, autouse=False):
|
||||
def yield_fixture(scope="function", params=None, autouse=False, ids=None):
|
||||
""" (return a) decorator to mark a yield-fixture factory function
|
||||
(EXPERIMENTAL).
|
||||
|
||||
@@ -94,7 +100,8 @@ def yield_fixture(scope="function", params=None, autouse=False):
|
||||
return FixtureFunctionMarker(
|
||||
"function", params, autouse, yieldctx=True)(scope)
|
||||
else:
|
||||
return FixtureFunctionMarker(scope, params, autouse, yieldctx=True)
|
||||
return FixtureFunctionMarker(scope, params, autouse,
|
||||
yieldctx=True, ids=ids)
|
||||
|
||||
defaultfuncargprefixmarker = fixture()
|
||||
|
||||
@@ -365,22 +372,22 @@ def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
|
||||
# collect funcargs of all callspecs into a list of values
|
||||
arg2params = {}
|
||||
arg2scope = {}
|
||||
arg2fixturedefs = metafunc._arg2fixturedefs
|
||||
for param_index, callspec in enumerate(metafunc._calls):
|
||||
for callspec in metafunc._calls:
|
||||
for argname, argvalue in callspec.funcargs.items():
|
||||
arg2params.setdefault(argname, []).append(argvalue)
|
||||
if argname not in arg2scope:
|
||||
scopenum = callspec._arg2scopenum.get(argname, scopenum_function)
|
||||
arg2scope[argname] = scopes[scopenum]
|
||||
callspec.indices[argname] = param_index
|
||||
|
||||
for argname in callspec.funcargs:
|
||||
assert argname not in callspec.params
|
||||
callspec.params.update(callspec.funcargs)
|
||||
callspec.params[argname] = argvalue
|
||||
arg2params_list = arg2params.setdefault(argname, [])
|
||||
callspec.indices[argname] = len(arg2params_list)
|
||||
arg2params_list.append(argvalue)
|
||||
if argname not in arg2scope:
|
||||
scopenum = callspec._arg2scopenum.get(argname,
|
||||
scopenum_function)
|
||||
arg2scope[argname] = scopes[scopenum]
|
||||
callspec.funcargs.clear()
|
||||
|
||||
# register artificial FixtureDef's so that later at test execution
|
||||
# time we can rely on a proper FixtureDef to exist for fixture setup.
|
||||
arg2fixturedefs = metafunc._arg2fixturedefs
|
||||
for argname, valuelist in arg2params.items():
|
||||
# if we have a scope that is higher than function we need
|
||||
# to make sure we only ever create an according fixturedef on
|
||||
@@ -478,7 +485,7 @@ class Module(pytest.File, PyCollector):
|
||||
fin = getattr(self.obj, 'teardown_module', None)
|
||||
if fin is not None:
|
||||
#XXX: nose compat hack, move to nose plugin
|
||||
# if it takes a positional arg, its probably a py.test style one
|
||||
# if it takes a positional arg, it's probably a pytest style one
|
||||
# so we pass the current module object
|
||||
if inspect.getargspec(fin)[0]:
|
||||
finalizer = lambda: fin(self.obj)
|
||||
@@ -955,6 +962,22 @@ def raises(ExpectedException, *args, **kwargs):
|
||||
|
||||
>>> raises(ZeroDivisionError, "f(0)")
|
||||
<ExceptionInfo ...>
|
||||
|
||||
Performance note:
|
||||
-----------------
|
||||
|
||||
Similar to caught exception objects in Python, explicitly clearing local
|
||||
references to returned ``py.code.ExceptionInfo`` objects can help the Python
|
||||
interpreter speed up its garbage collection.
|
||||
|
||||
Clearing those references breaks a reference cycle (``ExceptionInfo`` -->
|
||||
caught exception --> frame stack raising the exception --> current frame
|
||||
stack --> local variables --> ``ExceptionInfo``) which makes Python keep all
|
||||
objects referenced from that cycle (including all local variables in the
|
||||
current frame) alive until the next cyclic garbage collection run. See the
|
||||
official Python ``try`` statement documentation for more detailed
|
||||
information.
|
||||
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
if ExpectedException is AssertionError:
|
||||
@@ -1004,7 +1027,7 @@ class RaisesContext(object):
|
||||
return issubclass(self.excinfo.type, self.ExpectedException)
|
||||
|
||||
#
|
||||
# the basic py.test Function item
|
||||
# the basic pytest Function item
|
||||
#
|
||||
|
||||
class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
|
||||
@@ -1218,7 +1241,7 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||
on all function invocations.
|
||||
|
||||
:arg marker: a :py:class:`_pytest.mark.MarkDecorator` object
|
||||
created by a call to ``py.test.mark.NAME(...)``.
|
||||
created by a call to ``pytest.mark.NAME(...)``.
|
||||
"""
|
||||
try:
|
||||
self.node.keywords[marker.markname] = marker
|
||||
@@ -1522,7 +1545,8 @@ class FixtureManager:
|
||||
self._nodename2fixtureinfo = {}
|
||||
|
||||
def getfixtureinfo(self, node, func, cls, funcargs=True):
|
||||
key = (node, func.__name__)
|
||||
# node is the "collection node" for "func"
|
||||
key = (node, func)
|
||||
try:
|
||||
return self._nodename2fixtureinfo[key]
|
||||
except KeyError:
|
||||
@@ -1623,7 +1647,8 @@ class FixtureManager:
|
||||
for fixturedef in faclist:
|
||||
if fixturedef.params is not None:
|
||||
metafunc.parametrize(argname, fixturedef.params,
|
||||
indirect=True, scope=fixturedef.scope)
|
||||
indirect=True, scope=fixturedef.scope,
|
||||
ids=fixturedef.ids)
|
||||
|
||||
def pytest_collection_modifyitems(self, items):
|
||||
# separate parametrized setups
|
||||
@@ -1660,7 +1685,7 @@ class FixtureManager:
|
||||
fixturedef = FixtureDef(self, nodeid, name, obj,
|
||||
marker.scope, marker.params,
|
||||
yieldctx=marker.yieldctx,
|
||||
unittest=unittest)
|
||||
unittest=unittest, ids=marker.ids)
|
||||
faclist = self._arg2fixturedefs.setdefault(name, [])
|
||||
if fixturedef.has_location:
|
||||
faclist.append(fixturedef)
|
||||
@@ -1728,7 +1753,7 @@ def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
|
||||
class FixtureDef:
|
||||
""" A container for a factory definition. """
|
||||
def __init__(self, fixturemanager, baseid, argname, func, scope, params,
|
||||
yieldctx, unittest=False):
|
||||
yieldctx, unittest=False, ids=None):
|
||||
self._fixturemanager = fixturemanager
|
||||
self.baseid = baseid or ''
|
||||
self.has_location = baseid is not None
|
||||
@@ -1741,6 +1766,7 @@ class FixtureDef:
|
||||
self.argnames = getfuncargnames(func, startindex=startindex)
|
||||
self.yieldctx = yieldctx
|
||||
self.unittest = unittest
|
||||
self.ids = ids
|
||||
self._finalizer = []
|
||||
|
||||
def addfinalizer(self, finalizer):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
""" basic collect and runtest protocol implementations """
|
||||
|
||||
import py, sys
|
||||
import py
|
||||
import pytest
|
||||
import sys
|
||||
from time import time
|
||||
from py._code.code import TerminalRepr
|
||||
|
||||
@@ -196,7 +198,7 @@ def pytest_runtest_makereport(item, call):
|
||||
if not isinstance(excinfo, py.code.ExceptionInfo):
|
||||
outcome = "failed"
|
||||
longrepr = excinfo
|
||||
elif excinfo.errisinstance(py.test.skip.Exception):
|
||||
elif excinfo.errisinstance(pytest.skip.Exception):
|
||||
outcome = "skipped"
|
||||
r = excinfo._getreprcrash()
|
||||
longrepr = (str(r.path), r.lineno, r.message)
|
||||
@@ -314,11 +316,10 @@ class SetupState(object):
|
||||
""" attach a finalizer to the given colitem.
|
||||
if colitem is None, this will add a finalizer that
|
||||
is called at the end of teardown_all().
|
||||
if colitem is a tuple, it will be used as a key
|
||||
and needs an explicit call to _callfinalizers(key) later on.
|
||||
"""
|
||||
assert hasattr(finalizer, '__call__')
|
||||
#assert colitem in self.stack
|
||||
assert colitem and not isinstance(colitem, tuple)
|
||||
assert callable(finalizer)
|
||||
#assert colitem in self.stack # some unit tests don't setup stack :/
|
||||
self._finalizers.setdefault(colitem, []).append(finalizer)
|
||||
|
||||
def _pop_and_teardown(self):
|
||||
@@ -418,7 +419,7 @@ class Skipped(OutcomeException):
|
||||
__module__ = 'builtins'
|
||||
|
||||
class Failed(OutcomeException):
|
||||
""" raised from an explicit call to py.test.fail() """
|
||||
""" raised from an explicit call to pytest.fail() """
|
||||
__module__ = 'builtins'
|
||||
|
||||
class Exit(KeyboardInterrupt):
|
||||
@@ -438,7 +439,7 @@ exit.Exception = Exit
|
||||
|
||||
def skip(msg=""):
|
||||
""" skip an executing test with the given message. Note: it's usually
|
||||
better to use the py.test.mark.skipif marker to declare a test to be
|
||||
better to use the pytest.mark.skipif marker to declare a test to be
|
||||
skipped under certain conditions like mismatching platforms or
|
||||
dependencies. See the pytest_skipping plugin for details.
|
||||
"""
|
||||
|
||||
@@ -37,7 +37,7 @@ def pytest_namespace():
|
||||
return dict(xfail=xfail)
|
||||
|
||||
class XFailed(pytest.fail.Exception):
|
||||
""" raised from an explicit call to py.test.xfail() """
|
||||
""" raised from an explicit call to pytest.xfail() """
|
||||
|
||||
def xfail(reason=""):
|
||||
""" xfail an executing test or setup functions with the given reason."""
|
||||
@@ -129,7 +129,7 @@ def pytest_runtest_setup(item):
|
||||
return
|
||||
evalskip = MarkEvaluator(item, 'skipif')
|
||||
if evalskip.istrue():
|
||||
py.test.skip(evalskip.getexplanation())
|
||||
pytest.skip(evalskip.getexplanation())
|
||||
item._evalxfail = MarkEvaluator(item, 'xfail')
|
||||
check_xfail_no_run(item)
|
||||
|
||||
@@ -141,7 +141,7 @@ def check_xfail_no_run(item):
|
||||
evalxfail = item._evalxfail
|
||||
if evalxfail.istrue():
|
||||
if not evalxfail.get('run', True):
|
||||
py.test.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
||||
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
||||
|
||||
def pytest_runtest_makereport(__multicall__, item, call):
|
||||
if not isinstance(item, pytest.Function):
|
||||
@@ -150,16 +150,16 @@ def pytest_runtest_makereport(__multicall__, item, call):
|
||||
if hasattr(item, '_unexpectedsuccess'):
|
||||
rep = __multicall__.execute()
|
||||
if rep.when == "call":
|
||||
# we need to translate into how py.test encodes xpass
|
||||
# we need to translate into how pytest encodes xpass
|
||||
rep.wasxfail = "reason: " + repr(item._unexpectedsuccess)
|
||||
rep.outcome = "failed"
|
||||
return rep
|
||||
if not (call.excinfo and
|
||||
call.excinfo.errisinstance(py.test.xfail.Exception)):
|
||||
call.excinfo.errisinstance(pytest.xfail.Exception)):
|
||||
evalxfail = getattr(item, '_evalxfail', None)
|
||||
if not evalxfail:
|
||||
return
|
||||
if call.excinfo and call.excinfo.errisinstance(py.test.xfail.Exception):
|
||||
if call.excinfo and call.excinfo.errisinstance(pytest.xfail.Exception):
|
||||
if not item.config.getvalue("runxfail"):
|
||||
rep = __multicall__.execute()
|
||||
rep.wasxfail = "reason: " + call.excinfo.value.msg
|
||||
|
||||
@@ -259,7 +259,7 @@ class TerminalReporter:
|
||||
if hasattr(sys, 'pypy_version_info'):
|
||||
verinfo = ".".join(map(str, sys.pypy_version_info[:3]))
|
||||
msg += "[pypy-%s-%s]" % (verinfo, sys.pypy_version_info[3])
|
||||
msg += " -- pytest-%s" % (py.test.__version__)
|
||||
msg += " -- py-%s -- pytest-%s" % (py.__version__, pytest.__version__)
|
||||
if self.verbosity > 0 or self.config.option.debug or \
|
||||
getattr(self.config.option, 'pastebin', None):
|
||||
msg += " -- " + str(sys.executable)
|
||||
|
||||
@@ -2,10 +2,10 @@ import sys
|
||||
|
||||
if __name__ == '__main__':
|
||||
import cProfile
|
||||
import py
|
||||
import pytest
|
||||
import pstats
|
||||
script = sys.argv[1] if len(sys.argv) > 1 else "empty.py"
|
||||
stats = cProfile.run('py.test.cmdline.main([%r])' % script, 'prof')
|
||||
stats = cProfile.run('pytest.cmdline.main([%r])' % script, 'prof')
|
||||
p = pstats.Stats("prof")
|
||||
p.strip_dirs()
|
||||
p.sort_stats('cumulative')
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
/*
|
||||
* sphinxdoc.css_t
|
||||
* ~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- sphinxdoc theme. Originally created by
|
||||
* Armin Ronacher for Werkzeug.
|
||||
*
|
||||
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'Verdana', sans-serif;
|
||||
font-size: 1.1em;
|
||||
letter-spacing: -0.01em;
|
||||
line-height: 150%;
|
||||
text-align: center;
|
||||
background-color: #BFD1D4;
|
||||
color: black;
|
||||
padding: 0;
|
||||
border: 1px solid #aaa;
|
||||
|
||||
margin: 0px 80px 0px 80px;
|
||||
min-width: 740px;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: white;
|
||||
text-align: left;
|
||||
background-image: url(contents.png);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 240px 0 0;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.body {
|
||||
margin: 0;
|
||||
padding: 0.5em 20px 20px 20px;
|
||||
}
|
||||
|
||||
div.related {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
background-image: url(navigation.png);
|
||||
height: 2em;
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
div.related ul li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 2em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.related ul li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
div.related ul li a {
|
||||
margin: 0;
|
||||
padding: 0 5px 0 5px;
|
||||
line-height: 1.75em;
|
||||
color: #EE9816;
|
||||
}
|
||||
|
||||
div.related ul li a:hover {
|
||||
color: #3CA8E7;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
margin: 0;
|
||||
padding: 0.5em 15px 15px 0;
|
||||
width: 210px;
|
||||
float: right;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4 {
|
||||
margin: 1em 0 0.5em 0;
|
||||
font-size: 1em;
|
||||
padding: 0.1em 0 0.1em 0.5em;
|
||||
color: white;
|
||||
border: 1px solid #86989B;
|
||||
background-color: #AFC1C4;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
padding-left: 1.5em;
|
||||
margin-top: 7px;
|
||||
padding: 0;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
background-color: #E3EFF1;
|
||||
color: #86989B;
|
||||
padding: 3px 8px 3px 0;
|
||||
clear: both;
|
||||
font-size: 0.8em;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #86989B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
p {
|
||||
margin: 0.8em 0 0.5em 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #CA7900;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #2491CF;
|
||||
}
|
||||
|
||||
div.body a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
padding: 0.7em 0 0.3em 0;
|
||||
font-size: 1.5em;
|
||||
color: #11557C;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 1.3em 0 0.2em 0;
|
||||
font-size: 1.35em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1em 0 -0.3em 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
|
||||
color: black!important;
|
||||
}
|
||||
|
||||
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
|
||||
display: none;
|
||||
margin: 0 0 0 0.3em;
|
||||
padding: 0 0.2em 0 0.2em;
|
||||
color: #aaa!important;
|
||||
}
|
||||
|
||||
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
|
||||
h5:hover a.anchor, h6:hover a.anchor {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
|
||||
h5 a.anchor:hover, h6 a.anchor:hover {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f!important;
|
||||
font-size: 1em;
|
||||
margin-left: 6px;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none!important;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #ccc;
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
cite, code, tt {
|
||||
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
||||
'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.95em;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #f2f2f2;
|
||||
border-bottom: 1px solid #ddd;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname, tt.xref {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #abc;
|
||||
margin: 2em;
|
||||
}
|
||||
|
||||
a tt {
|
||||
border: 0;
|
||||
color: #CA7900;
|
||||
}
|
||||
|
||||
a tt:hover {
|
||||
color: #2491CF;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
||||
'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.95em;
|
||||
letter-spacing: 0.015em;
|
||||
line-height: 120%;
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
pre a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
div.quotebar {
|
||||
background-color: #f8f8f8;
|
||||
max-width: 250px;
|
||||
float: right;
|
||||
padding: 2px 7px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
margin: 0 -0.5em 0 -0.5em;
|
||||
}
|
||||
|
||||
table td, table th {
|
||||
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||
}
|
||||
|
||||
div.admonition, div.warning {
|
||||
font-size: 0.9em;
|
||||
margin: 1em 0 1em 0;
|
||||
border: 1px solid #86989B;
|
||||
background-color: #f7f7f7;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.admonition p, div.warning p {
|
||||
margin: 0.5em 1em 0.5em 1em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.admonition pre, div.warning pre {
|
||||
margin: 0.4em 1em 0.4em 1em;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title,
|
||||
div.warning p.admonition-title {
|
||||
margin: 0;
|
||||
padding: 0.1em 0 0.1em 0.5em;
|
||||
color: white;
|
||||
border-bottom: 1px solid #86989B;
|
||||
font-weight: bold;
|
||||
background-color: #AFC1C4;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
border: 1px solid #940000;
|
||||
}
|
||||
|
||||
div.warning p.admonition-title {
|
||||
background-color: #CF0000;
|
||||
border-bottom-color: #940000;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol,
|
||||
div.warning ul, div.warning ol {
|
||||
margin: 0.1em 0.5em 0.5em 3em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.versioninfo {
|
||||
margin: 1em 0 0 0;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #DDEAF0;
|
||||
padding: 8px;
|
||||
line-height: 1.3em;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'Verdana', sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
17
doc/en/_templates/globaltoc.html
Normal file
17
doc/en/_templates/globaltoc.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Contents</a></li>
|
||||
<li><a href="{{ pathto('getting-started') }}">Install</a></li>
|
||||
<li><a href="{{ pathto('example/index') }}">Examples</a></li>
|
||||
<li><a href="{{ pathto('customize') }}">Customize</a></li>
|
||||
<li><a href="{{ pathto('contact') }}">Contact</a></li>
|
||||
<li><a href="{{ pathto('talks') }}">Talks/Posts</a></li>
|
||||
<li><a href="{{ pathto('changelog') }}">Changelog</a></li>
|
||||
</ul>
|
||||
|
||||
{%- if display_toc %}
|
||||
<hr>
|
||||
{{ toc }}
|
||||
{%- endif %}
|
||||
@@ -1,22 +0,0 @@
|
||||
<h3>Download</h3>
|
||||
{% if version.endswith('(hg)') %}
|
||||
<p>This documentation is for version <b>{{ version }}</b>, which is
|
||||
not released yet.</p>
|
||||
<p>You can use it from the
|
||||
<a href="http://bitbucket.org/hpk42/pytest">Bitbucket Repo</a> or look for
|
||||
released versions in the <a href="http://pypi.python.org/pypi/pytest">Python
|
||||
Package Index</a>.</p>
|
||||
{% else %}
|
||||
<p><b><a href="{{ pathto('announce/index')}}">{{ release }} release</a></b>
|
||||
[<a href="{{ pathto('changelog') }}">Changelog</a>]</p>
|
||||
<p>
|
||||
<a href="http://pypi.python.org/pypi/pytest">pytest/PyPI</a>
|
||||
</p>
|
||||
<pre>easy_install pytest</pre>
|
||||
<pre>pip install pytest</pre>
|
||||
{% endif %}
|
||||
|
||||
<h3>Questions? Suggestions?</h3>
|
||||
|
||||
<p><a href="{{ pathto('contact') }}">contact channels</a>
|
||||
</p>
|
||||
@@ -1,13 +1,5 @@
|
||||
{% extends "!layout.html" %}
|
||||
|
||||
{% block relbaritems %}
|
||||
{{ super() }}
|
||||
<g:plusone></g:plusone>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footer %}
|
||||
{{ super() }}
|
||||
<script type="text/javascript">
|
||||
@@ -23,5 +15,4 @@
|
||||
})();
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
11
doc/en/_templates/links.html
Normal file
11
doc/en/_templates/links.html
Normal file
@@ -0,0 +1,11 @@
|
||||
<h3>Useful Links</h3>
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">The pytest Website</a></li>
|
||||
<li><a href="{{ pathto('contributing') }}">Contribution Guide</a></li>
|
||||
<li><a href="https://pypi.python.org/pypi/pytest">pytest @ PyPI</a></li>
|
||||
<li><a href="https://bitbucket.org/hpk42/pytest/">pytest @ Bitbucket</a></li>
|
||||
<li><a href="http://pytest.org/latest/plugins_index/index.html">3rd party plugins (beta)</a></li>
|
||||
<li><a href="https://bitbucket.org/hpk42/pytest/issues?status=new&status=open">Issue Tracker</a></li>
|
||||
<li><a href="http://pytest.org/latest/pytest.pdf">PDF Documentation</a>
|
||||
</ul>
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
{%- if pagename != "search" %}
|
||||
<div id="searchbox" style="display: none">
|
||||
<form class="search" action="{{ pathto('search') }}" method="get">
|
||||
<input type="text" name="q" size="18" />
|
||||
<input type="submit" value="{{ _('Search') }}" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
{%- endif %}
|
||||
|
||||
<h3>quicklinks</h3>
|
||||
<div style="text-align: left; font-size: 100%; vertical-align: middle;">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ pathto('index') }}">home</a>
|
||||
</td><td>
|
||||
<a href="{{ pathto('contents') }}">TOC/contents</a>
|
||||
</td></tr><tr><td>
|
||||
<a href="{{ pathto('getting-started') }}">install</a>
|
||||
</td><td>
|
||||
<a href="{{ pathto('changelog') }}">changelog</a>
|
||||
</td></tr><tr><td>
|
||||
<a href="{{ pathto('example/index') }}">examples</a>
|
||||
</td><td>
|
||||
<a href="{{ pathto('customize') }}">customize</a>
|
||||
</td></tr><tr><td>
|
||||
<a href="https://bitbucket.org/hpk42/pytest/issues?status=new&status=open">issues[bb]</a>
|
||||
</td><td>
|
||||
<a href="{{ pathto('contact') }}">contact</a>
|
||||
</td></tr><tr><td>
|
||||
<a href="{{ pathto('talks') }}">Talks/Posts</a>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
{% extends "basic/localtoc.html" %}
|
||||
|
||||
5
doc/en/_templates/sidebarintro.html
Normal file
5
doc/en/_templates/sidebarintro.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<h3>About pytest</h3>
|
||||
<p>
|
||||
pytest is a mature full-featured Python testing tool that helps
|
||||
you write better programs.
|
||||
</p>
|
||||
3
doc/en/_themes/.gitignore
vendored
Normal file
3
doc/en/_themes/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
*.pyo
|
||||
.DS_Store
|
||||
37
doc/en/_themes/LICENSE
Normal file
37
doc/en/_themes/LICENSE
Normal file
@@ -0,0 +1,37 @@
|
||||
Copyright (c) 2010 by Armin Ronacher.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms of the theme, with or
|
||||
without modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
We kindly ask you to only use these themes in an unmodified manner just
|
||||
for Flask and Flask-related products, not for unrelated projects. If you
|
||||
like the visual style and want to use it for your own projects, please
|
||||
consider making some larger changes to the themes (such as changing
|
||||
font faces, sizes, colors or margins).
|
||||
|
||||
THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
31
doc/en/_themes/README
Normal file
31
doc/en/_themes/README
Normal file
@@ -0,0 +1,31 @@
|
||||
Flask Sphinx Styles
|
||||
===================
|
||||
|
||||
This repository contains sphinx styles for Flask and Flask related
|
||||
projects. To use this style in your Sphinx documentation, follow
|
||||
this guide:
|
||||
|
||||
1. put this folder as _themes into your docs folder. Alternatively
|
||||
you can also use git submodules to check out the contents there.
|
||||
2. add this to your conf.py:
|
||||
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
html_theme_path = ['_themes']
|
||||
html_theme = 'flask'
|
||||
|
||||
The following themes exist:
|
||||
|
||||
- 'flask' - the standard flask documentation theme for large
|
||||
projects
|
||||
- 'flask_small' - small one-page theme. Intended to be used by
|
||||
very small addon libraries for flask.
|
||||
|
||||
The following options exist for the flask_small theme:
|
||||
|
||||
[options]
|
||||
index_logo = '' filename of a picture in _static
|
||||
to be used as replacement for the
|
||||
h1 in the index.rst file.
|
||||
index_logo_height = 120px height of the index logo
|
||||
github_fork = '' repository name on github for the
|
||||
"fork me" badge
|
||||
24
doc/en/_themes/flask/layout.html
Normal file
24
doc/en/_themes/flask/layout.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{%- extends "basic/layout.html" %}
|
||||
{%- block extrahead %}
|
||||
{{ super() }}
|
||||
{% if theme_touch_icon %}
|
||||
<link rel="apple-touch-icon" href="{{ pathto('_static/' ~ theme_touch_icon, 1) }}" />
|
||||
{% endif %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9">
|
||||
{% endblock %}
|
||||
{%- block relbar2 %}{% endblock %}
|
||||
{% block header %}
|
||||
{{ super() }}
|
||||
{% if pagename == 'index' %}
|
||||
<div class=indexwrapper>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{%- block footer %}
|
||||
<div class="footer">
|
||||
© Copyright {{ copyright }}.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
|
||||
</div>
|
||||
{% if pagename == 'index' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endblock %}
|
||||
19
doc/en/_themes/flask/relations.html
Normal file
19
doc/en/_themes/flask/relations.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="{{ pathto(master_doc) }}">Documentation overview</a><ul>
|
||||
{%- for parent in parents %}
|
||||
<li><a href="{{ parent.link|e }}">{{ parent.title }}</a><ul>
|
||||
{%- endfor %}
|
||||
{%- if prev %}
|
||||
<li>Previous: <a href="{{ prev.link|e }}" title="{{ _('previous chapter')
|
||||
}}">{{ prev.title }}</a></li>
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<li>Next: <a href="{{ next.link|e }}" title="{{ _('next chapter')
|
||||
}}">{{ next.title }}</a></li>
|
||||
{%- endif %}
|
||||
{%- for parent in parents %}
|
||||
</ul></li>
|
||||
{%- endfor %}
|
||||
</ul></li>
|
||||
</ul>
|
||||
555
doc/en/_themes/flask/static/flasky.css_t
Normal file
555
doc/en/_themes/flask/static/flasky.css_t
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* flasky.css_t
|
||||
* ~~~~~~~~~~~~
|
||||
*
|
||||
* :copyright: Copyright 2010 by Armin Ronacher.
|
||||
* :license: Flask Design License, see LICENSE for details.
|
||||
*/
|
||||
|
||||
{% set page_width = '1020px' %}
|
||||
{% set sidebar_width = '220px' %}
|
||||
{% set link_color = '#490' %}
|
||||
{% set link_hover_color = '#9c0' %}
|
||||
{% set base_font = 'sans-serif' %}
|
||||
{% set header_font = 'sans-serif' %}
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: {{ base_font }};
|
||||
font-size: 17px;
|
||||
background-color: white;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: {{ page_width }};
|
||||
margin: 30px auto 0 auto;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 {{ sidebar_width }};
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
width: {{ sidebar_width }};
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
|
||||
img.floatingflask {
|
||||
padding: 0 0 10px 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
width: {{ page_width }};
|
||||
margin: 20px auto 30px auto;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
div.related {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.logo {
|
||||
padding: 0 0 20px 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: {{ header_font }};
|
||||
color: #444;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo a,
|
||||
div.sphinxsidebar h3 a,
|
||||
div.sphinxsidebar p.logo a:hover,
|
||||
div.sphinxsidebar h3 a:hover {
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #555;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #ccc;
|
||||
font-family: {{ base_font }};
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: {{ link_color }};
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: {{ link_hover_color }};
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a.reference.internal em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: {{ header_font }};
|
||||
font-weight: normal;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
{% if theme_index_logo %}
|
||||
div.indexwrapper h1 {
|
||||
text-indent: -999999px;
|
||||
background: url({{ theme_index_logo }}) no-repeat center center;
|
||||
height: {{ theme_index_logo_height }};
|
||||
}
|
||||
{% else %}
|
||||
div.indexwrapper div.body h1 {
|
||||
font-size: 200%;
|
||||
}
|
||||
{% endif %}
|
||||
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
|
||||
div.body h2 { font-size: 180%; }
|
||||
div.body h3 { font-size: 150%; }
|
||||
div.body h4 { font-size: 130%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #ddd;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
color: #444;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
background: #fafafa;
|
||||
margin: 20px -30px;
|
||||
padding: 10px 30px;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.admonition tt.xref, div.admonition a tt {
|
||||
border-bottom: 1px solid #fafafa;
|
||||
}
|
||||
|
||||
dd div.admonition {
|
||||
margin-left: -60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
font-family: {{ header_font }};
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.admonition p.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.highlight {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background: #FAF3E8;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre, tt {
|
||||
font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
padding-right: 0.08em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #888;
|
||||
-moz-box-shadow: 2px 2px 4px #eee;
|
||||
-webkit-box-shadow: 2px 2px 4px #eee;
|
||||
box-shadow: 2px 2px 4px #eee;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
border: 1px solid #888;
|
||||
padding: 0.25em 0.7em;
|
||||
}
|
||||
|
||||
table.field-list, table.footnote {
|
||||
border: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
border: 1px solid #eee;
|
||||
background: #fdfdfd;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
table.footnote + table.footnote {
|
||||
margin-top: -15px;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.field-list th {
|
||||
padding: 0 0.8em 0 0;
|
||||
}
|
||||
|
||||
table.field-list td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.footnote td.label {
|
||||
width: 0px;
|
||||
padding: 0.3em 0 0.3em 0.5em;
|
||||
}
|
||||
|
||||
table.footnote td {
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin: 10px 0 10px 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #eee;
|
||||
padding: 7px 30px;
|
||||
margin: 15px -30px;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
dl pre, blockquote pre, li pre {
|
||||
margin-left: -60px;
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
dl dl pre {
|
||||
margin-left: -90px;
|
||||
padding-left: 90px;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
/* padding: 1px 2px; */
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted {{ link_color }};
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
border-bottom: 1px solid {{ link_hover_color }};
|
||||
}
|
||||
|
||||
a.footnote-reference {
|
||||
text-decoration: none;
|
||||
font-size: 0.7em;
|
||||
vertical-align: top;
|
||||
border-bottom: 1px dotted {{ link_color }};
|
||||
}
|
||||
|
||||
a.footnote-reference:hover {
|
||||
border-bottom: 1px solid {{ link_hover_color }};
|
||||
}
|
||||
|
||||
a:hover tt {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 870px) {
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 875px) {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 102.5%;
|
||||
margin: 50px -30px -20px -30px;
|
||||
padding: 10px 20px;
|
||||
background: #333;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
|
||||
div.sphinxsidebar h3 a, div.sphinxsidebar ul {
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.related {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 10px 0 20px 0;
|
||||
}
|
||||
|
||||
div.related ul,
|
||||
div.related ul li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.body {
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rtd_doc_footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* misc. */
|
||||
|
||||
.revsys-inline {
|
||||
display: none!important;
|
||||
}
|
||||
9
doc/en/_themes/flask/theme.conf
Normal file
9
doc/en/_themes/flask/theme.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = flasky.css
|
||||
pygments_style = flask_theme_support.FlaskyStyle
|
||||
|
||||
[options]
|
||||
index_logo = ''
|
||||
index_logo_height = 120px
|
||||
touch_icon =
|
||||
86
doc/en/_themes/flask_theme_support.py
Normal file
86
doc/en/_themes/flask_theme_support.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# flasky extensions. flasky pygments style based on tango style
|
||||
from pygments.style import Style
|
||||
from pygments.token import Keyword, Name, Comment, String, Error, \
|
||||
Number, Operator, Generic, Whitespace, Punctuation, Other, Literal
|
||||
|
||||
|
||||
class FlaskyStyle(Style):
|
||||
background_color = "#f8f8f8"
|
||||
default_style = ""
|
||||
|
||||
styles = {
|
||||
# No corresponding class for the following:
|
||||
#Text: "", # class: ''
|
||||
Whitespace: "underline #f8f8f8", # class: 'w'
|
||||
Error: "#a40000 border:#ef2929", # class: 'err'
|
||||
Other: "#000000", # class 'x'
|
||||
|
||||
Comment: "italic #8f5902", # class: 'c'
|
||||
Comment.Preproc: "noitalic", # class: 'cp'
|
||||
|
||||
Keyword: "bold #004461", # class: 'k'
|
||||
Keyword.Constant: "bold #004461", # class: 'kc'
|
||||
Keyword.Declaration: "bold #004461", # class: 'kd'
|
||||
Keyword.Namespace: "bold #004461", # class: 'kn'
|
||||
Keyword.Pseudo: "bold #004461", # class: 'kp'
|
||||
Keyword.Reserved: "bold #004461", # class: 'kr'
|
||||
Keyword.Type: "bold #004461", # class: 'kt'
|
||||
|
||||
Operator: "#582800", # class: 'o'
|
||||
Operator.Word: "bold #004461", # class: 'ow' - like keywords
|
||||
|
||||
Punctuation: "bold #000000", # class: 'p'
|
||||
|
||||
# because special names such as Name.Class, Name.Function, etc.
|
||||
# are not recognized as such later in the parsing, we choose them
|
||||
# to look the same as ordinary variables.
|
||||
Name: "#000000", # class: 'n'
|
||||
Name.Attribute: "#c4a000", # class: 'na' - to be revised
|
||||
Name.Builtin: "#004461", # class: 'nb'
|
||||
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
||||
Name.Class: "#000000", # class: 'nc' - to be revised
|
||||
Name.Constant: "#000000", # class: 'no' - to be revised
|
||||
Name.Decorator: "#888", # class: 'nd' - to be revised
|
||||
Name.Entity: "#ce5c00", # class: 'ni'
|
||||
Name.Exception: "bold #cc0000", # class: 'ne'
|
||||
Name.Function: "#000000", # class: 'nf'
|
||||
Name.Property: "#000000", # class: 'py'
|
||||
Name.Label: "#f57900", # class: 'nl'
|
||||
Name.Namespace: "#000000", # class: 'nn' - to be revised
|
||||
Name.Other: "#000000", # class: 'nx'
|
||||
Name.Tag: "bold #004461", # class: 'nt' - like a keyword
|
||||
Name.Variable: "#000000", # class: 'nv' - to be revised
|
||||
Name.Variable.Class: "#000000", # class: 'vc' - to be revised
|
||||
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
||||
Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
|
||||
|
||||
Number: "#990000", # class: 'm'
|
||||
|
||||
Literal: "#000000", # class: 'l'
|
||||
Literal.Date: "#000000", # class: 'ld'
|
||||
|
||||
String: "#4e9a06", # class: 's'
|
||||
String.Backtick: "#4e9a06", # class: 'sb'
|
||||
String.Char: "#4e9a06", # class: 'sc'
|
||||
String.Doc: "italic #8f5902", # class: 'sd' - like a comment
|
||||
String.Double: "#4e9a06", # class: 's2'
|
||||
String.Escape: "#4e9a06", # class: 'se'
|
||||
String.Heredoc: "#4e9a06", # class: 'sh'
|
||||
String.Interpol: "#4e9a06", # class: 'si'
|
||||
String.Other: "#4e9a06", # class: 'sx'
|
||||
String.Regex: "#4e9a06", # class: 'sr'
|
||||
String.Single: "#4e9a06", # class: 's1'
|
||||
String.Symbol: "#4e9a06", # class: 'ss'
|
||||
|
||||
Generic: "#000000", # class: 'g'
|
||||
Generic.Deleted: "#a40000", # class: 'gd'
|
||||
Generic.Emph: "italic #000000", # class: 'ge'
|
||||
Generic.Error: "#ef2929", # class: 'gr'
|
||||
Generic.Heading: "bold #000080", # class: 'gh'
|
||||
Generic.Inserted: "#00A000", # class: 'gi'
|
||||
Generic.Output: "#888", # class: 'go'
|
||||
Generic.Prompt: "#745334", # class: 'gp'
|
||||
Generic.Strong: "bold #000000", # class: 'gs'
|
||||
Generic.Subheading: "bold #800080", # class: 'gu'
|
||||
Generic.Traceback: "bold #a40000", # class: 'gt'
|
||||
}
|
||||
@@ -5,6 +5,8 @@ Release announcements
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
release-2.5.2
|
||||
release-2.5.1
|
||||
release-2.5.0
|
||||
release-2.4.2
|
||||
release-2.4.1
|
||||
|
||||
47
doc/en/announce/release-2.5.1.txt
Normal file
47
doc/en/announce/release-2.5.1.txt
Normal file
@@ -0,0 +1,47 @@
|
||||
pytest-2.5.1: fixes and new home page styling
|
||||
===========================================================================
|
||||
|
||||
pytest is a mature Python testing tool with more than a 1000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
The 2.5.1 release maintains the "zero-reported-bugs" promise by fixing
|
||||
the three bugs reported since the last release a few days ago. It also
|
||||
features a new home page styling implemented by Tobias Bieniek, based on
|
||||
the flask theme from Armin Ronacher:
|
||||
|
||||
http://pytest.org
|
||||
|
||||
If you have anything more to improve styling and docs,
|
||||
we'd be very happy to merge further pull requests.
|
||||
|
||||
On the coding side, the release also contains a little enhancement to
|
||||
fixture decorators allowing to directly influence generation of test
|
||||
ids, thanks to Floris Bruynooghe. Other thanks for helping with
|
||||
this release go to Anatoly Bubenkoff and Ronny Pfannschmidt.
|
||||
|
||||
As usual, you can upgrade from pypi via::
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
have fun and a nice remaining "bug-free" time of the year :)
|
||||
holger krekel
|
||||
|
||||
2.5.1
|
||||
-----------------------------------
|
||||
|
||||
- merge new documentation styling PR from Tobias Bieniek.
|
||||
|
||||
- fix issue403: allow parametrize of multiple same-name functions within
|
||||
a collection node. Thanks Andreas Kloeckner and Alex Gaynor for reporting
|
||||
and analysis.
|
||||
|
||||
- Allow parameterized fixtures to specify the ID of the parameters by
|
||||
adding an ids argument to pytest.fixture() and pytest.yield_fixture().
|
||||
Thanks Floris Bruynooghe.
|
||||
|
||||
- fix issue404 by always using the binary xml escape in the junitxml
|
||||
plugin. Thanks Ronny Pfannschmidt.
|
||||
|
||||
- fix issue407: fix addoption docstring to point to argparse instead of
|
||||
optparse. Thanks Daniel D. Wright.
|
||||
|
||||
64
doc/en/announce/release-2.5.2.txt
Normal file
64
doc/en/announce/release-2.5.2.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
pytest-2.5.2: fixes
|
||||
===========================================================================
|
||||
|
||||
pytest is a mature Python testing tool with more than a 1000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
The 2.5.2 release fixes a few bugs with two maybe-bugs remaining and
|
||||
actively being worked on (and waiting for the bug reporter's input).
|
||||
We also have a new contribution guide thanks to Piotr Banaszkiewicz
|
||||
and others.
|
||||
|
||||
See docs at:
|
||||
|
||||
http://pytest.org
|
||||
|
||||
As usual, you can upgrade from pypi via::
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to the following people who contributed to this release:
|
||||
|
||||
Anatoly Bubenkov
|
||||
Ronny Pfannschmidt
|
||||
Floris Bruynooghe
|
||||
Bruno Oliveira
|
||||
Andreas Pelme
|
||||
Jurko Gospodnetić
|
||||
Piotr Banaszkiewicz
|
||||
Simon Liedtke
|
||||
lakka
|
||||
Lukasz Balcerzak
|
||||
Philippe Muller
|
||||
Daniel Hahler
|
||||
|
||||
have fun,
|
||||
holger krekel
|
||||
|
||||
2.5.2
|
||||
-----------------------------------
|
||||
|
||||
- fix issue409 -- better interoperate with cx_freeze by not
|
||||
trying to import from collections.abc which causes problems
|
||||
for py27/cx_freeze. Thanks Wolfgang L. for reporting and tracking it down.
|
||||
|
||||
- fixed docs and code to use "pytest" instead of "py.test" almost everywhere.
|
||||
Thanks Jurko Gospodnetic for the complete PR.
|
||||
|
||||
- fix issue425: mention at end of "py.test -h" that --markers
|
||||
and --fixtures work according to specified test path (or current dir)
|
||||
|
||||
- fix issue413: exceptions with unicode attributes are now printed
|
||||
correctly also on python2 and with pytest-xdist runs. (the fix
|
||||
requires py-1.4.20)
|
||||
|
||||
- copy, cleanup and integrate py.io capture
|
||||
from pylib 1.4.20.dev2 (rev 13d9af95547e)
|
||||
|
||||
- address issue416: clarify docs as to conftest.py loading semantics
|
||||
|
||||
- fix issue429: comparing byte strings with non-ascii chars in assert
|
||||
expressions now work better. Thanks Floris Bruynooghe.
|
||||
|
||||
- make capfd/capsys.capture private, its unused and shouldnt be exposed
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
.. _apiref:
|
||||
|
||||
py.test reference documentation
|
||||
pytest reference documentation
|
||||
================================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
@@ -10,7 +10,7 @@ The writing and reporting of assertions in tests
|
||||
Asserting with the ``assert`` statement
|
||||
---------------------------------------------------------
|
||||
|
||||
``py.test`` allows you to use the standard python ``assert`` for verifying
|
||||
``pytest`` allows you to use the standard python ``assert`` for verifying
|
||||
expectations and values in Python tests. For example, you can write the
|
||||
following::
|
||||
|
||||
@@ -26,7 +26,7 @@ you will see the return value of the function call::
|
||||
|
||||
$ py.test test_assert1.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_assert1.py F
|
||||
@@ -42,7 +42,7 @@ you will see the return value of the function call::
|
||||
test_assert1.py:5: AssertionError
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
py.test has support for showing the values of the most common subexpressions
|
||||
``pytest`` has support for showing the values of the most common subexpressions
|
||||
including calls, attributes, comparisons, and binary and unary
|
||||
operators. (See :ref:`tbreportdemo`). This allows you to use the
|
||||
idiomatic python constructs without boilerplate code while not losing
|
||||
@@ -102,7 +102,7 @@ Making use of context-sensitive comparisons
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
py.test has rich support for providing context-sensitive information
|
||||
``pytest`` has rich support for providing context-sensitive information
|
||||
when it encounters comparisons. For example::
|
||||
|
||||
# content of test_assert2.py
|
||||
@@ -116,7 +116,7 @@ if you run this module::
|
||||
|
||||
$ py.test test_assert2.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_assert2.py F
|
||||
@@ -175,21 +175,21 @@ now, given this test module::
|
||||
f2 = Foo(2)
|
||||
assert f1 == f2
|
||||
|
||||
you can run the test module and get the custom output defined in
|
||||
you can run the test module and get the custom output defined in
|
||||
the conftest file::
|
||||
|
||||
$ py.test -q test_foocompare.py
|
||||
F
|
||||
================================= FAILURES =================================
|
||||
_______________________________ test_compare _______________________________
|
||||
|
||||
|
||||
def test_compare():
|
||||
f1 = Foo(1)
|
||||
f2 = Foo(2)
|
||||
> assert f1 == f2
|
||||
E assert Comparing Foo instances:
|
||||
E vals: 1 != 2
|
||||
|
||||
|
||||
test_foocompare.py:8: AssertionError
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
@@ -205,33 +205,33 @@ Advanced assertion introspection
|
||||
Reporting details about a failing assertion is achieved either by rewriting
|
||||
assert statements before they are run or re-evaluating the assert expression and
|
||||
recording the intermediate values. Which technique is used depends on the
|
||||
location of the assert, py.test's configuration, and Python version being used
|
||||
to run py.test. Note that for assert statements with a manually provided
|
||||
location of the assert, ``pytest`` configuration, and Python version being used
|
||||
to run ``pytest``. Note that for assert statements with a manually provided
|
||||
message, i.e. ``assert expr, message``, no assertion introspection takes place
|
||||
and the manually provided message will be rendered in tracebacks.
|
||||
|
||||
By default, if the Python version is greater than or equal to 2.6, py.test
|
||||
By default, if the Python version is greater than or equal to 2.6, ``pytest``
|
||||
rewrites assert statements in test modules. Rewritten assert statements put
|
||||
introspection information into the assertion failure message. py.test only
|
||||
introspection information into the assertion failure message. ``pytest`` only
|
||||
rewrites test modules directly discovered by its test collection process, so
|
||||
asserts in supporting modules which are not themselves test modules will not be
|
||||
rewritten.
|
||||
|
||||
.. note::
|
||||
|
||||
py.test rewrites test modules on import. It does this by using an import hook
|
||||
to write a new pyc files. Most of the time this works transparently. However,
|
||||
if you are messing with import yourself, the import hook may interfere. If
|
||||
this is the case, simply use ``--assert=reinterp`` or
|
||||
``pytest`` rewrites test modules on import. It does this by using an import
|
||||
hook to write a new pyc files. Most of the time this works transparently.
|
||||
However, if you are messing with import yourself, the import hook may
|
||||
interfere. If this is the case, simply use ``--assert=reinterp`` or
|
||||
``--assert=plain``. Additionally, rewriting will fail silently if it cannot
|
||||
write new pycs, i.e. in a read-only filesystem or a zipfile.
|
||||
|
||||
If an assert statement has not been rewritten or the Python version is less than
|
||||
2.6, py.test falls back on assert reinterpretation. In assert reinterpretation,
|
||||
py.test walks the frame of the function containing the assert statement to
|
||||
discover sub-expression results of the failing assert statement. You can force
|
||||
py.test to always use assertion reinterpretation by passing the
|
||||
``--assert=reinterp`` option.
|
||||
2.6, ``pytest`` falls back on assert reinterpretation. In assert
|
||||
reinterpretation, ``pytest`` walks the frame of the function containing the
|
||||
assert statement to discover sub-expression results of the failing assert
|
||||
statement. You can force ``pytest`` to always use assertion reinterpretation by
|
||||
passing the ``--assert=reinterp`` option.
|
||||
|
||||
Assert reinterpretation has a caveat not present with assert rewriting: If
|
||||
evaluating the assert expression has side effects you may get a warning that the
|
||||
@@ -250,7 +250,7 @@ easy to rewrite the assertion and avoid any trouble::
|
||||
|
||||
All assert introspection can be turned off by passing ``--assert=plain``.
|
||||
|
||||
For further information, Benjamin Peterson wrote up `Behind the scenes of py.test's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
|
||||
For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
Add assert rewriting as an alternate introspection technique.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
Setting up bash completion
|
||||
==========================
|
||||
|
||||
When using bash as your shell, ``py.test`` can use argcomplete
|
||||
When using bash as your shell, ``pytest`` can use argcomplete
|
||||
(https://argcomplete.readthedocs.org/) for auto-completion.
|
||||
For this ``argcomplete`` needs to be installed **and** enabled.
|
||||
|
||||
@@ -16,11 +16,11 @@ For global activation of all argcomplete enabled python applications run::
|
||||
|
||||
sudo activate-global-python-argcomplete
|
||||
|
||||
For permanent (but not global) ``py.test`` activation, use::
|
||||
For permanent (but not global) ``pytest`` activation, use::
|
||||
|
||||
register-python-argcomplete py.test >> ~/.bashrc
|
||||
|
||||
For one-time activation of argcomplete for ``py.test`` only, use::
|
||||
For one-time activation of argcomplete for ``pytest`` only, use::
|
||||
|
||||
eval "$(register-python-argcomplete py.test)"
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ a test.
|
||||
Setting capturing methods or disabling capturing
|
||||
-------------------------------------------------
|
||||
|
||||
There are two ways in which ``py.test`` can perform capturing:
|
||||
There are two ways in which ``pytest`` can perform capturing:
|
||||
|
||||
* file descriptor (FD) level capturing (default): All writes going to the
|
||||
operating system file descriptors 1 and 2 will be captured.
|
||||
@@ -49,7 +49,7 @@ One primary benefit of the default capturing of stdout/stderr output
|
||||
is that you can use print statements for debugging::
|
||||
|
||||
# content of test_module.py
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
print ("setting up %s" % function)
|
||||
|
||||
@@ -64,7 +64,7 @@ of the failing function and hide the other one::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py .F
|
||||
@@ -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 0x29437d0>
|
||||
setting up <function test_func2 at 0x1ec25f0>
|
||||
==================== 1 failed, 1 passed in 0.01 seconds ====================
|
||||
|
||||
Accessing captured output from a test function
|
||||
@@ -105,7 +105,7 @@ and capturing will be continued. After the test
|
||||
function finishes the original streams will
|
||||
be restored. Using ``capsys`` this way frees your
|
||||
test from having to care about setting/resetting
|
||||
output streams and also interacts well with py.test's
|
||||
output streams and also interacts well with pytest's
|
||||
own per-test capturing.
|
||||
|
||||
If you want to capture on ``fd`` level you can use
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# The short X.Y version.
|
||||
version = "2.4.2"
|
||||
release = "2.4.2"
|
||||
version = "2.5.2"
|
||||
release = "2.5.2"
|
||||
|
||||
import sys, os
|
||||
|
||||
@@ -54,7 +54,7 @@ master_doc = 'contents'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pytest'
|
||||
copyright = u'2012, holger krekel'
|
||||
copyright = u'2013, holger krekel'
|
||||
|
||||
|
||||
|
||||
@@ -105,14 +105,19 @@ pygments_style = 'sphinx'
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
sys.path.append(os.path.abspath('_themes'))
|
||||
html_theme_path = ['_themes']
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'sphinxdoc'
|
||||
html_theme = 'flask'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
html_theme_options = {}
|
||||
html_theme_options = {
|
||||
'index_logo': None
|
||||
}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
@@ -150,6 +155,23 @@ html_static_path = ['_static']
|
||||
#html_sidebars = {}
|
||||
#html_sidebars = {'index': 'indexsidebar.html'}
|
||||
|
||||
html_sidebars = {
|
||||
'index': [
|
||||
'sidebarintro.html',
|
||||
'globaltoc.html',
|
||||
'links.html',
|
||||
'sourcelink.html',
|
||||
'searchbox.html'
|
||||
],
|
||||
'**': [
|
||||
'globaltoc.html',
|
||||
'relations.html',
|
||||
'links.html',
|
||||
'sourcelink.html',
|
||||
'searchbox.html'
|
||||
]
|
||||
}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
@@ -198,7 +220,7 @@ htmlhelp_basename = 'pytestdoc'
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('contents', 'pytest.tex', u'pytest Documentation',
|
||||
u'holger krekel, http://merlinux.eu', 'manual'),
|
||||
u'holger krekel, trainer and consultant, http://merlinux.eu', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
@@ -240,7 +262,7 @@ man_pages = [
|
||||
epub_title = u'pytest'
|
||||
epub_author = u'holger krekel at merlinux eu'
|
||||
epub_publisher = u'holger krekel at merlinux eu'
|
||||
epub_copyright = u'2012, holger krekel et alii'
|
||||
epub_copyright = u'2013, holger krekel et alii'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
|
||||
@@ -18,6 +18,9 @@ Contact channels
|
||||
|
||||
- `pytest-commit at python.org (mailing list)`_: for commits and new issues
|
||||
|
||||
- :doc:`contribution guide <contributing>` for help on submitting pull
|
||||
requests to bitbucket (including using git via gitifyhg).
|
||||
|
||||
- #pylib on irc.freenode.net IRC channel for random questions.
|
||||
|
||||
- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
|
||||
|
||||
@@ -14,9 +14,10 @@ Full pytest documentation
|
||||
overview
|
||||
apiref
|
||||
plugins
|
||||
plugins_index/index
|
||||
example/index
|
||||
talks
|
||||
develop
|
||||
contributing
|
||||
funcarg_compare.txt
|
||||
announce/index
|
||||
|
||||
|
||||
3
doc/en/contributing.txt
Normal file
3
doc/en/contributing.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
.. _contributing:
|
||||
|
||||
.. include:: ../../CONTRIBUTING.rst
|
||||
@@ -17,7 +17,7 @@ which were registered by installed plugins.
|
||||
How test configuration is read from configuration INI-files
|
||||
-------------------------------------------------------------
|
||||
|
||||
py.test searches for the first matching ini-style configuration file
|
||||
``pytest`` searches for the first matching ini-style configuration file
|
||||
in the directories of command line argument and the directories above.
|
||||
It looks for file basenames in this order::
|
||||
|
||||
@@ -26,8 +26,8 @@ It looks for file basenames in this order::
|
||||
setup.cfg
|
||||
|
||||
Searching stops when the first ``[pytest]`` section is found in any of
|
||||
these files. There is no merging of configuration values from multiple
|
||||
files. Example::
|
||||
these files. There is no merging of configuration values from multiple
|
||||
files. Example::
|
||||
|
||||
py.test path/to/testdir
|
||||
|
||||
@@ -41,7 +41,7 @@ will look in the following dirs for a config file::
|
||||
path/to/setup.cfg
|
||||
... # up until root of filesystem
|
||||
|
||||
If argument is provided to a py.test run, the current working directory
|
||||
If argument is provided to a ``pytest`` run, the current working directory
|
||||
is used to start the search.
|
||||
|
||||
.. _`how to change command line options defaults`:
|
||||
@@ -51,7 +51,7 @@ How to change command line options defaults
|
||||
------------------------------------------------
|
||||
|
||||
It can be tedious to type the same series of command line options
|
||||
every time you use py.test . For example, if you always want to see
|
||||
every time you use ``pytest``. For example, if you always want to see
|
||||
detailed info on skipped and xfailed tests, as well as have terser "dot"
|
||||
progress output, you can write it into a configuration file::
|
||||
|
||||
@@ -60,7 +60,7 @@ progress output, you can write it into a configuration file::
|
||||
[pytest]
|
||||
addopts = -rsxX -q
|
||||
|
||||
From now on, running ``py.test`` will add the specified options.
|
||||
From now on, running ``pytest`` will add the specified options.
|
||||
|
||||
Builtin configuration file options
|
||||
----------------------------------------------
|
||||
@@ -105,7 +105,7 @@ Builtin configuration file options
|
||||
[pytest]
|
||||
norecursedirs = .svn _build tmp*
|
||||
|
||||
This would tell py.test to not look into typical subversion or
|
||||
This would tell ``pytest`` to not look into typical subversion or
|
||||
sphinx-build directories or into any ``tmp`` prefixed directory.
|
||||
|
||||
.. confval:: python_files
|
||||
@@ -122,7 +122,7 @@ Builtin configuration file options
|
||||
|
||||
One or more name prefixes determining which test functions
|
||||
and methods are considered as test modules. Note that this
|
||||
has no effect on methods that live on a ``unittest.TestCase``
|
||||
has no effect on methods that live on a ``unittest.TestCase``
|
||||
derived class.
|
||||
|
||||
See :ref:`change naming conventions` for examples.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
=================================================
|
||||
Feedback and contribute to py.test
|
||||
=================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
contact.txt
|
||||
|
||||
.. _checkout:
|
||||
|
||||
Working from version control or a tarball
|
||||
=================================================
|
||||
|
||||
To follow development or start experiments, checkout the
|
||||
complete code and documentation source with mercurial_::
|
||||
|
||||
hg clone https://bitbucket.org/hpk42/pytest/
|
||||
|
||||
You can also go to the python package index and
|
||||
download and unpack a TAR file::
|
||||
|
||||
http://pypi.python.org/pypi/pytest/
|
||||
|
||||
Activating a checkout with setuptools
|
||||
--------------------------------------------
|
||||
|
||||
With a working Distribute_ or setuptools_ installation you can type::
|
||||
|
||||
python setup.py develop
|
||||
|
||||
in order to work inline with the tools and the lib of your checkout.
|
||||
|
||||
If this command complains that it could not find the required version
|
||||
of "py" then you need to use the development pypi repository::
|
||||
|
||||
python setup.py develop -i http://pypi.testrun.org
|
||||
|
||||
|
||||
.. include:: links.inc
|
||||
@@ -44,7 +44,7 @@ then you can just invoke ``py.test`` without command line options::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
mymodule.py .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
import py
|
||||
|
||||
def otherfunc(a,b):
|
||||
|
||||
@@ -28,7 +28,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
|
||||
|
||||
$ py.test -v -m webtest
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_server.py:3: test_send_http PASSED
|
||||
@@ -37,10 +37,10 @@ You can then restrict a test run to only run tests marked with ``webtest``::
|
||||
================== 1 passed, 2 deselected in 0.01 seconds ==================
|
||||
|
||||
Or the inverse, running all tests except the webtest ones::
|
||||
|
||||
|
||||
$ py.test -v -m "not webtest"
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_server.py:6: test_something_quick PASSED
|
||||
@@ -61,7 +61,7 @@ select tests based on their names::
|
||||
|
||||
$ py.test -v -k http # running with the above defined example module
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_server.py:3: test_send_http PASSED
|
||||
@@ -73,7 +73,7 @@ And you can also run all tests except the ones that match the keyword::
|
||||
|
||||
$ py.test -k "not send_http" -v
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_server.py:6: test_something_quick PASSED
|
||||
@@ -86,7 +86,7 @@ Or to select "http" and "quick" tests::
|
||||
|
||||
$ py.test -k "http or quick" -v
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_server.py:3: test_send_http PASSED
|
||||
@@ -150,8 +150,8 @@ For an example on how to add and work with markers from a plugin, see
|
||||
* asking for existing markers via ``py.test --markers`` gives good output
|
||||
|
||||
* typos in function markers are treated as an error if you use
|
||||
the ``--strict`` option. Later versions of py.test are probably
|
||||
going to treat non-registered markers as an error.
|
||||
the ``--strict`` option. Future versions of ``pytest`` are probably
|
||||
going to start treating non-registered markers as errors at some point.
|
||||
|
||||
.. _`scoped-marking`:
|
||||
|
||||
@@ -266,18 +266,18 @@ the test needs::
|
||||
|
||||
$ py.test -E stage2
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_someenv.py s
|
||||
|
||||
======================== 1 skipped in 0.01 seconds =========================
|
||||
|
||||
|
||||
and here is one that specifies exactly the environment needed::
|
||||
|
||||
$ py.test -E stage1
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_someenv.py .
|
||||
@@ -301,7 +301,7 @@ The ``--markers`` option always gives you a list of available markers::
|
||||
|
||||
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||
|
||||
|
||||
|
||||
Reading markers which were set from multiple places
|
||||
----------------------------------------------------
|
||||
|
||||
@@ -337,7 +337,7 @@ test function. From a conftest file we can read it like this::
|
||||
|
||||
Let's run this without capturing output and see what we get::
|
||||
|
||||
$ py.test -q -s
|
||||
$ py.test -q -s
|
||||
glob args=('function',) kwargs={'x': 3}
|
||||
glob args=('class',) kwargs={'x': 2}
|
||||
glob args=('module',) kwargs={'x': 1}
|
||||
@@ -352,7 +352,7 @@ marking platform specific tests with pytest
|
||||
Consider you have a test suite which marks tests for particular platforms,
|
||||
namely ``pytest.mark.osx``, ``pytest.mark.win32`` etc. and you
|
||||
also have tests that run on all platforms and have no specific
|
||||
marker. If you now want to have a way to only run the tests
|
||||
marker. If you now want to have a way to only run the tests
|
||||
for your particular platform, you could use the following plugin::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -395,12 +395,12 @@ then you will see two test skipped and two executed tests as expected::
|
||||
|
||||
$ py.test -rs # this option reports skip reasons
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_plat.py s.s.
|
||||
========================= short test summary info ==========================
|
||||
SKIP [2] /tmp/doc-exec-62/conftest.py:12: cannot run on platform linux2
|
||||
SKIP [2] /tmp/doc-exec-65/conftest.py:12: cannot run on platform linux2
|
||||
|
||||
=================== 2 passed, 2 skipped in 0.01 seconds ====================
|
||||
|
||||
@@ -408,7 +408,7 @@ Note that if you specify a platform via the marker-command line option like this
|
||||
|
||||
$ py.test -m linux2
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_plat.py .
|
||||
@@ -416,7 +416,7 @@ Note that if you specify a platform via the marker-command line option like this
|
||||
=================== 3 tests deselected by "-m 'linux2'" ====================
|
||||
================== 1 passed, 3 deselected in 0.01 seconds ==================
|
||||
|
||||
then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests.
|
||||
then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests.
|
||||
|
||||
Automatically adding markers based on test names
|
||||
--------------------------------------------------------
|
||||
@@ -435,7 +435,7 @@ at this test module::
|
||||
|
||||
def test_interface_complex():
|
||||
assert 0
|
||||
|
||||
|
||||
def test_event_simple():
|
||||
assert 0
|
||||
|
||||
@@ -446,7 +446,7 @@ We want to dynamically define two markers and can do it in a
|
||||
``conftest.py`` plugin::
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
|
||||
import pytest
|
||||
def pytest_collection_modifyitems(items):
|
||||
for item in items:
|
||||
@@ -459,7 +459,7 @@ We can now use the ``-m option`` to select one set::
|
||||
|
||||
$ py.test -m interface --tb=short
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -480,7 +480,7 @@ or to select both "event" and "interface" tests::
|
||||
|
||||
$ py.test -m "interface or event" --tb=short
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_module.py FFF
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
module containing a parametrized tests testing cross-python
|
||||
serialization via the pickle module.
|
||||
"""
|
||||
import py, pytest
|
||||
import py
|
||||
import pytest
|
||||
|
||||
pythonlist = ['python2.4', 'python2.5', 'python2.6', 'python2.7', 'python2.8']
|
||||
@pytest.fixture(params=pythonlist)
|
||||
@@ -18,7 +19,7 @@ class Python:
|
||||
def __init__(self, version, picklefile):
|
||||
self.pythonpath = py.path.local.sysfind(version)
|
||||
if not self.pythonpath:
|
||||
py.test.skip("%r not found" %(version,))
|
||||
pytest.skip("%r not found" %(version,))
|
||||
self.picklefile = picklefile
|
||||
def dumps(self, obj):
|
||||
dumpfile = self.picklefile.dirpath("dump.py")
|
||||
|
||||
@@ -27,10 +27,10 @@ now execute the test specification::
|
||||
|
||||
nonpython $ py.test test_simple.yml
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_simple.yml .F
|
||||
test_simple.yml F.
|
||||
|
||||
================================= FAILURES =================================
|
||||
______________________________ usecase: hello ______________________________
|
||||
@@ -56,11 +56,11 @@ consulted when reporting in ``verbose`` mode::
|
||||
|
||||
nonpython $ py.test -v
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_simple.yml:1: usecase: ok PASSED
|
||||
test_simple.yml:1: usecase: hello FAILED
|
||||
test_simple.yml:1: usecase: ok PASSED
|
||||
|
||||
================================= FAILURES =================================
|
||||
______________________________ usecase: hello ______________________________
|
||||
@@ -74,10 +74,10 @@ interesting to just look at the collection tree::
|
||||
|
||||
nonpython $ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
<YamlFile 'test_simple.yml'>
|
||||
<YamlItem 'ok'>
|
||||
<YamlItem 'hello'>
|
||||
<YamlItem 'ok'>
|
||||
|
||||
============================= in 0.03 seconds =============================
|
||||
============================= in 0.02 seconds =============================
|
||||
|
||||
@@ -6,7 +6,7 @@ Parametrizing tests
|
||||
|
||||
.. currentmodule:: _pytest.python
|
||||
|
||||
py.test allows to easily parametrize test functions.
|
||||
``pytest`` allows to easily parametrize test functions.
|
||||
For basic docs, see :ref:`parametrize-basics`.
|
||||
|
||||
In the following we provide some examples using
|
||||
@@ -55,13 +55,13 @@ let's run the full monty::
|
||||
....F
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_compute[4] ______________________________
|
||||
|
||||
|
||||
param1 = 4
|
||||
|
||||
|
||||
def test_compute(param1):
|
||||
> assert param1 < 4
|
||||
E assert 4 < 4
|
||||
|
||||
|
||||
test_compute.py:3: AssertionError
|
||||
1 failed, 4 passed in 0.01 seconds
|
||||
|
||||
@@ -106,7 +106,7 @@ this is a fully self-contained example which you can run with::
|
||||
|
||||
$ py.test test_scenarios.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_scenarios.py ....
|
||||
@@ -118,7 +118,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
|
||||
|
||||
$ py.test --collect-only test_scenarios.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
<Module 'test_scenarios.py'>
|
||||
<Class 'TestSampleWithScenarios'>
|
||||
@@ -182,7 +182,7 @@ Let's first see how it looks like at collection time::
|
||||
|
||||
$ py.test test_backends.py --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
<Module 'test_backends.py'>
|
||||
<Function 'test_db_initialized[d1]'>
|
||||
@@ -197,7 +197,7 @@ And then when we run the test::
|
||||
================================= FAILURES =================================
|
||||
_________________________ test_db_initialized[d2] __________________________
|
||||
|
||||
db = <conftest.DB2 instance at 0x1992c20>
|
||||
db = <conftest.DB2 instance at 0x1e5f050>
|
||||
|
||||
def test_db_initialized(db):
|
||||
# a dummy test
|
||||
@@ -253,7 +253,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 0x13483b0>, a = 1, b = 2
|
||||
self = <test_parametrize.TestClass instance at 0x246c4d0>, a = 1, b = 2
|
||||
|
||||
def test_equals(self, a, b):
|
||||
> assert a == b
|
||||
@@ -281,8 +281,8 @@ Running it results in some skips if we don't have all the python interpreters in
|
||||
. $ py.test -rs -q multipython.py
|
||||
............sss............sss............sss............ssssssssssssssssss
|
||||
========================= short test summary info ==========================
|
||||
SKIP [27] /home/hpk/p/pytest/doc/en/example/multipython.py:21: 'python2.8' not found
|
||||
48 passed, 27 skipped in 1.41 seconds
|
||||
SKIP [27] /home/hpk/p/pytest/doc/en/example/multipython.py:22: 'python2.8' not found
|
||||
48 passed, 27 skipped in 1.30 seconds
|
||||
|
||||
Indirect parametrization of optional implementations/imports
|
||||
--------------------------------------------------------------------
|
||||
@@ -290,7 +290,7 @@ Indirect parametrization of optional implementations/imports
|
||||
If you want to compare the outcomes of several implementations of a given
|
||||
API, you can write test functions that receive the already imported implementations
|
||||
and get skipped in case the implementation is not importable/available. Let's
|
||||
say we have a "base" implementation and the other (possibly optimized ones)
|
||||
say we have a "base" implementation and the other (possibly optimized ones)
|
||||
need to provide similar results::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -329,12 +329,12 @@ If you run this with reporting for skips enabled::
|
||||
|
||||
$ py.test -rs test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s
|
||||
========================= short test summary info ==========================
|
||||
SKIP [1] /tmp/doc-exec-64/conftest.py:10: could not import 'opt2'
|
||||
SKIP [1] /tmp/doc-exec-67/conftest.py:10: could not import 'opt2'
|
||||
|
||||
=================== 1 passed, 1 skipped in 0.01 seconds ====================
|
||||
|
||||
@@ -342,13 +342,13 @@ You'll see that we don't have a ``opt2`` module and thus the second test run
|
||||
of our ``test_func1`` was skipped. A few notes:
|
||||
|
||||
- the fixture functions in the ``conftest.py`` file are "session-scoped" because we
|
||||
don't need to import more than once
|
||||
don't need to import more than once
|
||||
|
||||
- if you have multiple test functions and a skipped import, you will see
|
||||
the ``[1]`` count increasing in the report
|
||||
|
||||
- you can put :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>` style
|
||||
parametrization on the test functions to parametrize input/output
|
||||
parametrization on the test functions to parametrize input/output
|
||||
values as well.
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ You can set the :confval:`norecursedirs` option in an ini-file, for example your
|
||||
[pytest]
|
||||
norecursedirs = .svn _build tmp*
|
||||
|
||||
This would tell py.test to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
|
||||
This would tell ``pytest`` to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
|
||||
|
||||
.. _`change naming conventions`:
|
||||
|
||||
@@ -28,7 +28,7 @@ the :confval:`python_files`, :confval:`python_classes` and
|
||||
python_classes=Check
|
||||
python_functions=check
|
||||
|
||||
This would make py.test look for ``check_`` prefixes in
|
||||
This would make ``pytest`` look for ``check_`` prefixes in
|
||||
Python filenames, ``Check`` prefixes in classes and ``check`` prefixes
|
||||
in functions and classes. For example, if we have::
|
||||
|
||||
@@ -43,7 +43,7 @@ then the test collection looks like this::
|
||||
|
||||
$ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
<Module 'check_myapp.py'>
|
||||
<Class 'CheckMyApp'>
|
||||
@@ -54,7 +54,7 @@ then the test collection looks like this::
|
||||
============================= in 0.01 seconds =============================
|
||||
|
||||
.. note::
|
||||
|
||||
|
||||
the ``python_functions`` and ``python_classes`` has no effect
|
||||
for ``unittest.TestCase`` test discovery because pytest delegates
|
||||
detection of test case methods to unittest code.
|
||||
@@ -62,7 +62,7 @@ then the test collection looks like this::
|
||||
Interpreting cmdline arguments as Python packages
|
||||
-----------------------------------------------------
|
||||
|
||||
You can use the ``--pyargs`` option to make py.test try
|
||||
You can use the ``--pyargs`` option to make ``pytest`` try
|
||||
interpreting arguments as python package names, deriving
|
||||
their file system path and then running the test. For
|
||||
example if you have unittest2 installed you can type::
|
||||
@@ -88,7 +88,7 @@ You can always peek at the collection tree without running tests like this::
|
||||
|
||||
. $ py.test --collect-only pythoncollection.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 3 items
|
||||
<Module 'pythoncollection.py'>
|
||||
<Function 'test_function'>
|
||||
@@ -104,7 +104,7 @@ customizing test collection to find all .py files
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
You can easily instruct py.test to discover tests from every python file::
|
||||
You can easily instruct ``pytest`` to discover tests from every python file::
|
||||
|
||||
|
||||
# content of pytest.ini
|
||||
@@ -112,8 +112,8 @@ You can easily instruct py.test to discover tests from every python file::
|
||||
python_files = *.py
|
||||
|
||||
However, many projects will have a ``setup.py`` which they don't want to be imported. Moreover, there may files only importable by a specific python version.
|
||||
For such cases you can dynamically define files to be ignored by listing
|
||||
them in a ``conftest.py`` file::
|
||||
For such cases you can dynamically define files to be ignored by listing
|
||||
them in a ``conftest.py`` file::
|
||||
|
||||
# content of conftest.py
|
||||
import sys
|
||||
@@ -136,12 +136,12 @@ and a setup.py dummy file like this::
|
||||
# content of setup.py
|
||||
0/0 # will raise exeption if imported
|
||||
|
||||
then a pytest run on python2 will find the one test when run with a python2
|
||||
then a pytest run on python2 will find the one test when run with a python2
|
||||
interpreters and will leave out the setup.py file::
|
||||
|
||||
|
||||
$ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
<Module 'pkg/module_py2.py'>
|
||||
<Function 'test_only_on_python2'>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
.. _`tbreportdemo`:
|
||||
|
||||
Demo of Python failure reports with py.test
|
||||
|
||||
Demo of Python failure reports with pytest
|
||||
==================================================
|
||||
|
||||
Here is a nice run of several tens of failures
|
||||
and how py.test presents things (unfortunately
|
||||
and how ``pytest`` presents things (unfortunately
|
||||
not showing the nice colors here in the HTML that you
|
||||
get on the terminal - we are working on that):
|
||||
|
||||
@@ -13,7 +13,7 @@ get on the terminal - we are working on that):
|
||||
|
||||
assertion $ py.test failure_demo.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 39 items
|
||||
|
||||
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
@@ -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 0x1d5e7d0>
|
||||
self = <failure_demo.TestFailing object at 0x29e5210>
|
||||
|
||||
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 0x1cfcb90>()
|
||||
E + and 43 = <function g at 0x1cfcc08>()
|
||||
E + where 42 = <function f at 0x296a9b0>()
|
||||
E + and 43 = <function g at 0x296aa28>()
|
||||
|
||||
failure_demo.py:28: AssertionError
|
||||
____________________ TestFailing.test_simple_multiline _____________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0x1d0fed0>
|
||||
self = <failure_demo.TestFailing object at 0x29cef50>
|
||||
|
||||
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 0x1d4bc10>
|
||||
self = <failure_demo.TestFailing object at 0x29be250>
|
||||
|
||||
def test_not(self):
|
||||
def f():
|
||||
return 42
|
||||
> assert not f()
|
||||
E assert not 42
|
||||
E + where 42 = <function f at 0x1d071b8>()
|
||||
E + where 42 = <function f at 0x296ac08>()
|
||||
|
||||
failure_demo.py:38: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_text _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x1d0bed0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29c3990>
|
||||
|
||||
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 0x1d0de10>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2acef90>
|
||||
|
||||
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 0x1d5e110>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29f1f50>
|
||||
|
||||
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 0x1ec06d0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29e58d0>
|
||||
|
||||
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 0x1d0d950>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29cee50>
|
||||
|
||||
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 0x1d61c50>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29c3810>
|
||||
|
||||
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 0x1d4be10>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29e50d0>
|
||||
|
||||
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 0x1ec0ad0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29c5dd0>
|
||||
|
||||
def test_eq_dict(self):
|
||||
> assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
|
||||
@@ -194,7 +194,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 0x1d0bbd0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29e2690>
|
||||
|
||||
def test_eq_set(self):
|
||||
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
|
||||
@@ -210,7 +210,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 0x1d4bd10>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29ceb50>
|
||||
|
||||
def test_eq_longer_list(self):
|
||||
> assert [1,2] == [1,2,3]
|
||||
@@ -220,7 +220,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 0x1ec0650>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29c3050>
|
||||
|
||||
def test_in_list(self):
|
||||
> assert 1 in [0, 2, 3, 4, 5]
|
||||
@@ -229,7 +229,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 0x1d0bad0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29e5b10>
|
||||
|
||||
def test_not_in_text_multiline(self):
|
||||
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
|
||||
@@ -247,7 +247,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 0x1d0d410>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29f1610>
|
||||
|
||||
def test_not_in_text_single(self):
|
||||
text = 'single foo line'
|
||||
@@ -260,7 +260,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 0x1ec0610>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29cea50>
|
||||
|
||||
def test_not_in_text_single_long(self):
|
||||
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
|
||||
@@ -273,7 +273,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 0x1d5ed50>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x29e2a10>
|
||||
|
||||
def test_not_in_text_single_long_term(self):
|
||||
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
|
||||
@@ -292,7 +292,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 0x1d0da50>.b
|
||||
E + where 1 = <failure_demo.Foo object at 0x29c77d0>.b
|
||||
|
||||
failure_demo.py:101: AssertionError
|
||||
_________________________ test_attribute_instance __________________________
|
||||
@@ -302,8 +302,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 0x1d0b8d0>.b
|
||||
E + where <failure_demo.Foo object at 0x1d0b8d0> = <class 'failure_demo.Foo'>()
|
||||
E + where 1 = <failure_demo.Foo object at 0x29e5f10>.b
|
||||
E + where <failure_demo.Foo object at 0x29e5f10> = <class 'failure_demo.Foo'>()
|
||||
|
||||
failure_demo.py:107: AssertionError
|
||||
__________________________ test_attribute_failure __________________________
|
||||
@@ -319,7 +319,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:116:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
self = <failure_demo.Foo object at 0x1d5eb90>
|
||||
self = <failure_demo.Foo object at 0x29e6b10>
|
||||
|
||||
def _get_b(self):
|
||||
> raise Exception('Failed to get attrib')
|
||||
@@ -335,15 +335,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 0x1d15c10>.b
|
||||
E + where <failure_demo.Foo object at 0x1d15c10> = <class 'failure_demo.Foo'>()
|
||||
E + and 2 = <failure_demo.Bar object at 0x1d15290>.b
|
||||
E + where <failure_demo.Bar object at 0x1d15290> = <class 'failure_demo.Bar'>()
|
||||
E + where 1 = <failure_demo.Foo object at 0x29c3b10>.b
|
||||
E + where <failure_demo.Foo object at 0x29c3b10> = <class 'failure_demo.Foo'>()
|
||||
E + and 2 = <failure_demo.Bar object at 0x29c3350>.b
|
||||
E + where <failure_demo.Bar object at 0x29c3350> = <class 'failure_demo.Bar'>()
|
||||
|
||||
failure_demo.py:124: AssertionError
|
||||
__________________________ TestRaises.test_raises __________________________
|
||||
|
||||
self = <failure_demo.TestRaises instance at 0x1ee2248>
|
||||
self = <failure_demo.TestRaises instance at 0x2aec878>
|
||||
|
||||
def test_raises(self):
|
||||
s = 'qwe'
|
||||
@@ -355,10 +355,10 @@ get on the terminal - we are working on that):
|
||||
> int(s)
|
||||
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||
|
||||
<0-codegen /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:976>:1: ValueError
|
||||
<0-codegen /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:999>:1: ValueError
|
||||
______________________ TestRaises.test_raises_doesnt _______________________
|
||||
|
||||
self = <failure_demo.TestRaises instance at 0x1d14b48>
|
||||
self = <failure_demo.TestRaises instance at 0x2aafef0>
|
||||
|
||||
def test_raises_doesnt(self):
|
||||
> raises(IOError, "int('3')")
|
||||
@@ -367,7 +367,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:136: Failed
|
||||
__________________________ TestRaises.test_raise ___________________________
|
||||
|
||||
self = <failure_demo.TestRaises instance at 0x1ed9cb0>
|
||||
self = <failure_demo.TestRaises instance at 0x2ae5758>
|
||||
|
||||
def test_raise(self):
|
||||
> raise ValueError("demo error")
|
||||
@@ -376,7 +376,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:139: ValueError
|
||||
________________________ TestRaises.test_tupleerror ________________________
|
||||
|
||||
self = <failure_demo.TestRaises instance at 0x1eeb200>
|
||||
self = <failure_demo.TestRaises instance at 0x29cf4d0>
|
||||
|
||||
def test_tupleerror(self):
|
||||
> a,b = [1]
|
||||
@@ -385,7 +385,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 0x1eebdd0>
|
||||
self = <failure_demo.TestRaises instance at 0x29cf9e0>
|
||||
|
||||
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
|
||||
l = [1,2,3]
|
||||
@@ -398,7 +398,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 0x1edf758>
|
||||
self = <failure_demo.TestRaises instance at 0x29d9ea8>
|
||||
|
||||
def test_some_error(self):
|
||||
> if namenotexi:
|
||||
@@ -426,7 +426,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 0x1ed0128>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x29ca8c0>
|
||||
|
||||
def test_complex_error(self):
|
||||
def f():
|
||||
@@ -455,7 +455,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 0x1ec7f38>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x2ae2ea8>
|
||||
|
||||
def test_z1_unpack_error(self):
|
||||
l = []
|
||||
@@ -465,7 +465,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 0x1ee47a0>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x29da518>
|
||||
|
||||
def test_z2_type_error(self):
|
||||
l = 3
|
||||
@@ -475,19 +475,19 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:183: TypeError
|
||||
______________________ TestMoreErrors.test_startswith ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors instance at 0x1eea2d8>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x29b8440>
|
||||
|
||||
def test_startswith(self):
|
||||
s = "123"
|
||||
g = "456"
|
||||
> assert s.startswith(g)
|
||||
E assert <built-in method startswith of str object at 0x1d63a58>('456')
|
||||
E + where <built-in method startswith of str object at 0x1d63a58> = '123'.startswith
|
||||
E assert <built-in method startswith of str object at 0x29ea328>('456')
|
||||
E + where <built-in method startswith of str object at 0x29ea328> = '123'.startswith
|
||||
|
||||
failure_demo.py:188: AssertionError
|
||||
__________________ TestMoreErrors.test_startswith_nested ___________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors instance at 0x1ef08c0>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x2ae4e18>
|
||||
|
||||
def test_startswith_nested(self):
|
||||
def f():
|
||||
@@ -495,15 +495,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 0x1d63a58>('456')
|
||||
E + where <built-in method startswith of str object at 0x1d63a58> = '123'.startswith
|
||||
E + where '123' = <function f at 0x1d07500>()
|
||||
E + and '456' = <function g at 0x1cf2b18>()
|
||||
E assert <built-in method startswith of str object at 0x29ea328>('456')
|
||||
E + where <built-in method startswith of str object at 0x29ea328> = '123'.startswith
|
||||
E + where '123' = <function f at 0x29595f0>()
|
||||
E + and '456' = <function g at 0x2ab5320>()
|
||||
|
||||
failure_demo.py:195: AssertionError
|
||||
_____________________ TestMoreErrors.test_global_func ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors instance at 0x1ed4a70>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x2abf320>
|
||||
|
||||
def test_global_func(self):
|
||||
> assert isinstance(globf(42), float)
|
||||
@@ -513,18 +513,18 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:198: AssertionError
|
||||
_______________________ TestMoreErrors.test_instance _______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors instance at 0x1edf998>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x2aaf050>
|
||||
|
||||
def test_instance(self):
|
||||
self.x = 6*7
|
||||
> assert self.x != 42
|
||||
E assert 42 != 42
|
||||
E + where 42 = <failure_demo.TestMoreErrors instance at 0x1edf998>.x
|
||||
E + where 42 = <failure_demo.TestMoreErrors instance at 0x2aaf050>.x
|
||||
|
||||
failure_demo.py:202: AssertionError
|
||||
_______________________ TestMoreErrors.test_compare ________________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors instance at 0x1edf3f8>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x2aedbd8>
|
||||
|
||||
def test_compare(self):
|
||||
> assert globf(10) < 5
|
||||
@@ -534,7 +534,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 0x1ef15f0>
|
||||
self = <failure_demo.TestMoreErrors instance at 0x29f2098>
|
||||
|
||||
def test_try_finally(self):
|
||||
x = 1
|
||||
@@ -543,4 +543,4 @@ get on the terminal - we are working on that):
|
||||
E assert 1 == 0
|
||||
|
||||
failure_demo.py:210: AssertionError
|
||||
======================== 39 failed in 0.23 seconds =========================
|
||||
======================== 39 failed in 0.20 seconds =========================
|
||||
|
||||
@@ -41,9 +41,9 @@ Let's run this without supplying our new option::
|
||||
F
|
||||
================================= FAILURES =================================
|
||||
_______________________________ test_answer ________________________________
|
||||
|
||||
|
||||
cmdopt = 'type1'
|
||||
|
||||
|
||||
def test_answer(cmdopt):
|
||||
if cmdopt == "type1":
|
||||
print ("first")
|
||||
@@ -51,7 +51,7 @@ Let's run this without supplying our new option::
|
||||
print ("second")
|
||||
> assert 0 # to see what was printed
|
||||
E assert 0
|
||||
|
||||
|
||||
test_sample.py:6: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
first
|
||||
@@ -63,9 +63,9 @@ And now with supplying a command line option::
|
||||
F
|
||||
================================= FAILURES =================================
|
||||
_______________________________ test_answer ________________________________
|
||||
|
||||
|
||||
cmdopt = 'type2'
|
||||
|
||||
|
||||
def test_answer(cmdopt):
|
||||
if cmdopt == "type1":
|
||||
print ("first")
|
||||
@@ -73,7 +73,7 @@ And now with supplying a command line option::
|
||||
print ("second")
|
||||
> assert 0 # to see what was printed
|
||||
E assert 0
|
||||
|
||||
|
||||
test_sample.py:6: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
second
|
||||
@@ -108,7 +108,7 @@ directory with the above conftest.py::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 0 items
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
@@ -152,12 +152,12 @@ and when running it will see a skipped "slow" test::
|
||||
|
||||
$ py.test -rs # "-rs" means report details on the little 's'
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s
|
||||
========================= short test summary info ==========================
|
||||
SKIP [1] /tmp/doc-exec-67/conftest.py:9: need --runslow option to run
|
||||
SKIP [1] /tmp/doc-exec-70/conftest.py:9: need --runslow option to run
|
||||
|
||||
=================== 1 passed, 1 skipped in 0.01 seconds ====================
|
||||
|
||||
@@ -165,7 +165,7 @@ Or run it including the ``slow`` marked test::
|
||||
|
||||
$ py.test --runslow
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py ..
|
||||
@@ -193,7 +193,7 @@ Example::
|
||||
def test_something():
|
||||
checkconfig(42)
|
||||
|
||||
The ``__tracebackhide__`` setting influences py.test showing
|
||||
The ``__tracebackhide__`` setting influences ``pytest`` showing
|
||||
of tracebacks: the ``checkconfig`` function will not be shown
|
||||
unless the ``--fulltrace`` command line option is specified.
|
||||
Let's run our little function::
|
||||
@@ -202,15 +202,15 @@ Let's run our little function::
|
||||
F
|
||||
================================= FAILURES =================================
|
||||
______________________________ test_something ______________________________
|
||||
|
||||
|
||||
def test_something():
|
||||
> checkconfig(42)
|
||||
E Failed: not configured: 42
|
||||
|
||||
|
||||
test_checkconfig.py:8: Failed
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
Detect if running from within a py.test run
|
||||
Detect if running from within a pytest run
|
||||
--------------------------------------------------------------
|
||||
|
||||
.. regendoc:wipe
|
||||
@@ -245,10 +245,10 @@ Adding info to test report header
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
It's easy to present extra information in a py.test run::
|
||||
It's easy to present extra information in a ``pytest`` run::
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
|
||||
def pytest_report_header(config):
|
||||
return "project deps: mylib-1.1"
|
||||
|
||||
@@ -256,7 +256,7 @@ which will add the string to the test header accordingly::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
project deps: mylib-1.1
|
||||
collected 0 items
|
||||
|
||||
@@ -279,7 +279,7 @@ which will add info only when run with "--v"::
|
||||
|
||||
$ py.test -v
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
info1: did you know that ...
|
||||
did you?
|
||||
collecting ... collected 0 items
|
||||
@@ -290,7 +290,7 @@ and nothing when run plainly::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 0 items
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
@@ -322,7 +322,7 @@ Now we can profile which test functions execute the slowest::
|
||||
|
||||
$ py.test --durations=3
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 3 items
|
||||
|
||||
test_some_are_slow.py ...
|
||||
@@ -383,7 +383,7 @@ If we run this::
|
||||
|
||||
$ py.test -rx
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 4 items
|
||||
|
||||
test_step.py .Fx.
|
||||
@@ -391,7 +391,7 @@ If we run this::
|
||||
================================= FAILURES =================================
|
||||
____________________ TestUserHandling.test_modification ____________________
|
||||
|
||||
self = <test_step.TestUserHandling instance at 0x192ea28>
|
||||
self = <test_step.TestUserHandling instance at 0x2768dd0>
|
||||
|
||||
def test_modification(self):
|
||||
> assert 0
|
||||
@@ -401,7 +401,7 @@ If we run this::
|
||||
========================= short test summary info ==========================
|
||||
XFAIL test_step.py::TestUserHandling::()::test_deletion
|
||||
reason: previous test failed (test_modification)
|
||||
============== 1 failed, 2 passed, 1 xfailed in 0.02 seconds ===============
|
||||
============== 1 failed, 2 passed, 1 xfailed in 0.01 seconds ===============
|
||||
|
||||
We'll see that ``test_deletion`` was not executed because ``test_modification``
|
||||
failed. It is reported as an "expected failure".
|
||||
@@ -448,12 +448,12 @@ the ``db`` fixture::
|
||||
# content of b/test_error.py
|
||||
def test_root(db): # no db here, will error out
|
||||
pass
|
||||
|
||||
|
||||
We can run this::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 7 items
|
||||
|
||||
test_step.py .Fx.
|
||||
@@ -463,17 +463,17 @@ We can run this::
|
||||
|
||||
================================== ERRORS ==================================
|
||||
_______________________ ERROR at setup of test_root ________________________
|
||||
file /tmp/doc-exec-67/b/test_error.py, line 1
|
||||
file /tmp/doc-exec-70/b/test_error.py, line 1
|
||||
def test_root(db): # no db here, will error out
|
||||
fixture 'db' not found
|
||||
available fixtures: monkeypatch, capsys, tmpdir, capfd, pytestconfig, recwarn
|
||||
available fixtures: pytestconfig, capfd, monkeypatch, capsys, recwarn, tmpdir
|
||||
use 'py.test --fixtures [testpath]' for help on them.
|
||||
|
||||
/tmp/doc-exec-67/b/test_error.py:1
|
||||
/tmp/doc-exec-70/b/test_error.py:1
|
||||
================================= FAILURES =================================
|
||||
____________________ TestUserHandling.test_modification ____________________
|
||||
|
||||
self = <test_step.TestUserHandling instance at 0x2099a28>
|
||||
self = <test_step.TestUserHandling instance at 0x238fdd0>
|
||||
|
||||
def test_modification(self):
|
||||
> assert 0
|
||||
@@ -482,20 +482,20 @@ We can run this::
|
||||
test_step.py:9: AssertionError
|
||||
_________________________________ test_a1 __________________________________
|
||||
|
||||
db = <conftest.DB instance at 0x20a1518>
|
||||
db = <conftest.DB instance at 0x23f9998>
|
||||
|
||||
def test_a1(db):
|
||||
> assert 0, db # to show value
|
||||
E AssertionError: <conftest.DB instance at 0x20a1518>
|
||||
E AssertionError: <conftest.DB instance at 0x23f9998>
|
||||
|
||||
a/test_db.py:2: AssertionError
|
||||
_________________________________ test_a2 __________________________________
|
||||
|
||||
db = <conftest.DB instance at 0x20a1518>
|
||||
db = <conftest.DB instance at 0x23f9998>
|
||||
|
||||
def test_a2(db):
|
||||
> assert 0, db # to show value
|
||||
E AssertionError: <conftest.DB instance at 0x20a1518>
|
||||
E AssertionError: <conftest.DB instance at 0x23f9998>
|
||||
|
||||
a/test_db2.py:2: AssertionError
|
||||
========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.03 seconds ==========
|
||||
@@ -512,7 +512,7 @@ post-process test reports / failures
|
||||
---------------------------------------
|
||||
|
||||
If you want to postprocess test reports and need access to the executing
|
||||
environment you can implement a hook that gets called when the test
|
||||
environment you can implement a hook that gets called when the test
|
||||
"report" object is about to be created. Here we write out all failing
|
||||
test calls and also access a fixture (if it was used by the test) in
|
||||
case you want to query/look at it during your post processing. In our
|
||||
@@ -529,7 +529,7 @@ case we just write some informations out to a ``failures`` file::
|
||||
rep = __multicall__.execute()
|
||||
|
||||
# we only look at actual failing test calls, not setup/teardown
|
||||
if rep.when == "call" and rep.failed:
|
||||
if rep.when == "call" and rep.failed:
|
||||
mode = "a" if os.path.exists("failures") else "w"
|
||||
with open("failures", mode) as f:
|
||||
# let's also access a fixture for the fun of it
|
||||
@@ -537,7 +537,7 @@ case we just write some informations out to a ``failures`` file::
|
||||
extra = " (%s)" % item.funcargs["tmpdir"]
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
|
||||
f.write(rep.nodeid + extra + "\n")
|
||||
return rep
|
||||
|
||||
@@ -545,15 +545,15 @@ if you then have failing tests::
|
||||
|
||||
# content of test_module.py
|
||||
def test_fail1(tmpdir):
|
||||
assert 0
|
||||
assert 0
|
||||
def test_fail2():
|
||||
assert 0
|
||||
|
||||
assert 0
|
||||
|
||||
and run them::
|
||||
|
||||
$ py.test test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -561,7 +561,7 @@ and run them::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_fail1 ________________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-281/test_fail10')
|
||||
tmpdir = local('/tmp/pytest-1012/test_fail10')
|
||||
|
||||
def test_fail1(tmpdir):
|
||||
> assert 0
|
||||
@@ -575,12 +575,12 @@ and run them::
|
||||
E assert 0
|
||||
|
||||
test_module.py:4: AssertionError
|
||||
========================= 2 failed in 0.02 seconds =========================
|
||||
========================= 2 failed in 0.01 seconds =========================
|
||||
|
||||
you will have a "failures" file which contains the failing test ids::
|
||||
|
||||
$ cat failures
|
||||
test_module.py::test_fail1 (/tmp/pytest-281/test_fail10)
|
||||
test_module.py::test_fail1 (/tmp/pytest-1012/test_fail10)
|
||||
test_module.py::test_fail2
|
||||
|
||||
Making test result information available in fixtures
|
||||
@@ -623,27 +623,27 @@ here is a little example implemented via a local plugin::
|
||||
if you then have failing tests::
|
||||
|
||||
# content of test_module.py
|
||||
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def other():
|
||||
assert 0
|
||||
|
||||
|
||||
def test_setup_fails(something, other):
|
||||
pass
|
||||
|
||||
def test_call_fails(something):
|
||||
assert 0
|
||||
assert 0
|
||||
|
||||
def test_fail2():
|
||||
assert 0
|
||||
|
||||
assert 0
|
||||
|
||||
and run it::
|
||||
|
||||
$ py.test -s test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 3 items
|
||||
|
||||
test_module.py Esetting up a test failed! test_module.py::test_setup_fails
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
A sesssion-fixture which can look at all collected tests
|
||||
A session-fixture which can look at all collected tests
|
||||
----------------------------------------------------------------
|
||||
|
||||
A session-scoped fixture effectively has access to all
|
||||
@@ -70,4 +69,4 @@ If you run this without output capturing::
|
||||
.test other
|
||||
.test_unit1 method called
|
||||
.
|
||||
4 passed in 0.02 seconds
|
||||
4 passed in 0.01 seconds
|
||||
|
||||
@@ -4,37 +4,37 @@ Some Issues and Questions
|
||||
.. note::
|
||||
|
||||
This FAQ is here only mostly for historic reasons. Checkout
|
||||
`pytest Q&A at Stackoverflow <http://stackoverflow.com/search?q=pytest>`_
|
||||
`pytest Q&A at Stackoverflow <http://stackoverflow.com/search?q=pytest>`_
|
||||
for many questions and answers related to pytest and/or use
|
||||
:ref:`contact channels` to get help.
|
||||
|
||||
On naming, nosetests, licensing and magic
|
||||
------------------------------------------------
|
||||
|
||||
How does py.test relate to nose and unittest?
|
||||
How does pytest relate to nose and unittest?
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
py.test and nose_ share basic philosophy when it comes
|
||||
``pytest`` and nose_ share basic philosophy when it comes
|
||||
to running and writing Python tests. In fact, you can run many tests
|
||||
written for nose with py.test. nose_ was originally created
|
||||
as a clone of ``py.test`` when py.test was in the ``0.8`` release
|
||||
written for nose with ``pytest``. nose_ was originally created
|
||||
as a clone of ``pytest`` when ``pytest`` was in the ``0.8`` release
|
||||
cycle. Note that starting with pytest-2.0 support for running unittest
|
||||
test suites is majorly improved.
|
||||
|
||||
how does py.test relate to twisted's trial?
|
||||
how does pytest relate to twisted's trial?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Since some time py.test has builtin support for supporting tests
|
||||
Since some time ``pytest`` has builtin support for supporting tests
|
||||
written using trial. It does not itself start a reactor, however,
|
||||
and does not handle Deferreds returned from a test in pytest style.
|
||||
and does not handle Deferreds returned from a test in pytest style.
|
||||
If you are using trial's unittest.TestCase chances are that you can
|
||||
just run your tests even if you return Deferreds. In addition,
|
||||
there also is a dedicated `pytest-twisted
|
||||
<http://pypi.python.org/pypi/pytest-twisted>`_ plugin which allows to
|
||||
return deferreds from pytest-style tests, allowing to use
|
||||
:ref:`fixtures` and other features.
|
||||
|
||||
how does py.test work with Django?
|
||||
|
||||
how does pytest work with Django?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
In 2012, some work is going into the `pytest-django plugin <http://pypi.python.org/pypi/pytest-django>`_. It substitutes the usage of Django's
|
||||
@@ -44,36 +44,36 @@ are not available from Django directly.
|
||||
.. _features: features.html
|
||||
|
||||
|
||||
What's this "magic" with py.test? (historic notes)
|
||||
What's this "magic" with pytest? (historic notes)
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Around 2007 (version ``0.8``) some people thought that py.test
|
||||
Around 2007 (version ``0.8``) some people thought that ``pytest``
|
||||
was using too much "magic". It had been part of the `pylib`_ which
|
||||
contains a lot of unreleated python library code. Around 2010 there
|
||||
was a major cleanup refactoring, which removed unused or deprecated code
|
||||
was a major cleanup refactoring, which removed unused or deprecated code
|
||||
and resulted in the new ``pytest`` PyPI package which strictly contains
|
||||
only test-related code. This relese also brought a complete pluginification
|
||||
only test-related code. This release also brought a complete pluginification
|
||||
such that the core is around 300 lines of code and everything else is
|
||||
implemented in plugins. Thus ``pytest`` today is a small, universally runnable
|
||||
implemented in plugins. Thus ``pytest`` today is a small, universally runnable
|
||||
and customizable testing framework for Python. Note, however, that
|
||||
``pytest`` uses metaprogramming techniques and reading its source is
|
||||
``pytest`` uses metaprogramming techniques and reading its source is
|
||||
thus likely not something for Python beginners.
|
||||
|
||||
A second "magic" issue was the assert statement debugging feature.
|
||||
Nowadays, py.test explicitely rewrites assert statements in test modules
|
||||
A second "magic" issue was the assert statement debugging feature.
|
||||
Nowadays, ``pytest`` explicitely rewrites assert statements in test modules
|
||||
in order to provide more useful :ref:`assert feedback <assertfeedback>`.
|
||||
This completely avoids previous issues of confusing assertion-reporting.
|
||||
This completely avoids previous issues of confusing assertion-reporting.
|
||||
It also means, that you can use Python's ``-O`` optimization without loosing
|
||||
assertions in test modules.
|
||||
|
||||
py.test contains a second mostly obsolete assert debugging technique,
|
||||
``pytest`` contains a second, mostly obsolete, assert debugging technique,
|
||||
invoked via ``--assert=reinterpret``, activated by default on
|
||||
Python-2.5: When an ``assert`` statement fails, py.test re-interprets
|
||||
Python-2.5: When an ``assert`` statement fails, ``pytest`` re-interprets
|
||||
the expression part to show intermediate values. This technique suffers
|
||||
from a caveat that the rewriting does not: If your expression has side
|
||||
effects (better to avoid them anyway!) the intermediate values may not
|
||||
be the same, confusing the reinterpreter and obfuscating the initial
|
||||
error (this is also explained at the command line if it happens).
|
||||
error (this is also explained at the command line if it happens).
|
||||
|
||||
You can also turn off all assertion interaction using the
|
||||
``--assertmode=off`` option.
|
||||
@@ -85,7 +85,7 @@ You can also turn off all assertion interaction using the
|
||||
Why a ``py.test`` instead of a ``pytest`` command?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Some of the reasons are historic, others are practical. ``py.test``
|
||||
Some of the reasons are historic, others are practical. ``pytest``
|
||||
used to be part of the ``py`` package which provided several developer
|
||||
utilities, all starting with ``py.<TAB>``, thus providing nice
|
||||
TAB-completion. If
|
||||
@@ -140,16 +140,16 @@ However, with pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
|
||||
and specify ``params`` so that all tests depending on the factory-created
|
||||
resource will run multiple times with different parameters.
|
||||
|
||||
You can also use the `pytest_generate_tests`_ hook to
|
||||
You can also use the `pytest_generate_tests`_ hook to
|
||||
implement the `parametrization scheme of your choice`_.
|
||||
|
||||
.. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests
|
||||
.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||
|
||||
py.test interaction with other packages
|
||||
pytest interaction with other packages
|
||||
---------------------------------------------------
|
||||
|
||||
Issues with py.test, multiprocess and setuptools?
|
||||
Issues with pytest, multiprocess and setuptools?
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
On windows the multiprocess package will instantiate sub processes
|
||||
|
||||
@@ -15,7 +15,7 @@ pytest fixtures: explicit, modular, scalable
|
||||
|
||||
The `purpose of test fixtures`_ is to provide a fixed baseline
|
||||
upon which tests can reliably and repeatedly execute. pytest fixtures
|
||||
offer dramatic improvements over the classic xUnit style of setup/teardown
|
||||
offer dramatic improvements over the classic xUnit style of setup/teardown
|
||||
functions:
|
||||
|
||||
* fixtures have explicit names and are activated by declaring their use
|
||||
@@ -50,7 +50,7 @@ Fixtures as Function arguments
|
||||
-----------------------------------------
|
||||
|
||||
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
|
||||
the fixture object. Fixture functions are registered by marking them with
|
||||
:py:func:`@pytest.fixture <_pytest.python.fixture>`. Let's look at a simple
|
||||
self-contained test module containing a fixture and a test function
|
||||
@@ -70,13 +70,13 @@ using it::
|
||||
assert "merlinux" in msg
|
||||
assert 0 # for demo purposes
|
||||
|
||||
Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
|
||||
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
|
||||
Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
|
||||
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 ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_smtpsimple.py F
|
||||
@@ -84,7 +84,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_ehlo _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x24a9950>
|
||||
smtp = <smtplib.SMTP instance at 0x15cc0e0>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response, msg = smtp.ehlo()
|
||||
@@ -99,7 +99,7 @@ marked ``smtp`` fixture function. Running the test looks like this::
|
||||
In the failure traceback we see that the test function was called with a
|
||||
``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
|
||||
function. The test function fails on our deliberate ``assert 0``. Here is
|
||||
an exact protocol of how py.test comes to call the test function this way:
|
||||
the exact protocol used by ``pytest`` to call the test function this way:
|
||||
|
||||
1. pytest :ref:`finds <test discovery>` the ``test_ehlo`` because
|
||||
of the ``test_`` prefix. The test function needs a function argument
|
||||
@@ -125,7 +125,7 @@ with a list of available function arguments.
|
||||
|
||||
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
|
||||
for the fixture factory. This remains and will remain supported
|
||||
but is not anymore advertised as the primary means of declaring fixture
|
||||
functions.
|
||||
|
||||
@@ -153,15 +153,15 @@ Sharing a fixture across tests in a module (or class/session)
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
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
|
||||
can add a ``scope='module'`` parameter to the
|
||||
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
|
||||
to cause the decorated ``smtp`` fixture function to only be invoked once
|
||||
per test module. Multiple test functions in a test module will thus
|
||||
each receive the same ``smtp`` fixture instance. The next example puts
|
||||
the fixture function into a separate ``conftest.py`` file so
|
||||
that tests from multiple test modules in the directory can
|
||||
that tests from multiple test modules in the directory can
|
||||
access the fixture function::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -180,7 +180,7 @@ function (in or below the directory where ``conftest.py`` is located)::
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
assert response[0] == 250
|
||||
assert response[0] == 250
|
||||
assert "merlinux" in response[1]
|
||||
assert 0 # for demo purposes
|
||||
|
||||
@@ -194,7 +194,7 @@ inspect what is going on and can now run the tests::
|
||||
|
||||
$ py.test test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -202,7 +202,7 @@ inspect what is going on and can now run the tests::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_ehlo _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x138a290>
|
||||
smtp = <smtplib.SMTP instance at 0x237b638>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -214,7 +214,7 @@ inspect what is going on and can now run the tests::
|
||||
test_module.py:6: AssertionError
|
||||
________________________________ test_noop _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x138a290>
|
||||
smtp = <smtplib.SMTP instance at 0x237b638>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -223,11 +223,11 @@ inspect what is going on and can now run the tests::
|
||||
E assert 0
|
||||
|
||||
test_module.py:11: AssertionError
|
||||
========================= 2 failed in 0.19 seconds =========================
|
||||
========================= 2 failed in 0.23 seconds =========================
|
||||
|
||||
You see the two ``assert 0`` failing and more importantly you can also see
|
||||
that the same (module-scoped) ``smtp`` object was passed into the two
|
||||
test functions because pytest shows the incoming argument values in the
|
||||
You see the two ``assert 0`` failing and more importantly you can also see
|
||||
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.
|
||||
|
||||
@@ -236,15 +236,15 @@ instance, you can simply declare it::
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def smtp(...):
|
||||
# the returned fixture value will be shared for
|
||||
# the returned fixture value will be shared for
|
||||
# all tests needing it
|
||||
|
||||
.. _`finalization`:
|
||||
|
||||
fixture finalization / executing teardown code
|
||||
|
||||
fixture finalization / executing teardown code
|
||||
-------------------------------------------------------------
|
||||
|
||||
pytest supports execution of fixture specific finalization code
|
||||
pytest supports execution of fixture specific finalization code
|
||||
when the fixture goes out of scope. By accepting a ``request`` object
|
||||
into your fixture function you can call its ``request.addfinalizer`` one
|
||||
or multiple times::
|
||||
@@ -271,12 +271,12 @@ Let's execute it::
|
||||
$ py.test -s -q --tb=no
|
||||
FFteardown smtp
|
||||
|
||||
2 failed in 0.24 seconds
|
||||
2 failed in 0.21 seconds
|
||||
|
||||
We see that the ``smtp`` instance is finalized after the two
|
||||
tests finished execution. Note that if we decorated our fixture
|
||||
function with ``scope='function'`` then fixture setup and cleanup would
|
||||
occur around each single test. In either case the test
|
||||
occur around each single test. In either case the test
|
||||
module itself does not need to change or know about these details
|
||||
of fixture setup.
|
||||
|
||||
@@ -288,7 +288,7 @@ Fixtures can introspect the requesting test context
|
||||
|
||||
Fixture function can accept the :py:class:`request <FixtureRequest>` object
|
||||
to introspect the "requesting" test function, class or module context.
|
||||
Further extending the previous ``smtp`` fixture example, let's
|
||||
Further extending the previous ``smtp`` fixture example, let's
|
||||
read an optional server URL from the test module which uses our fixture::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -299,12 +299,12 @@ read an optional server URL from the test module which uses our fixture::
|
||||
def smtp(request):
|
||||
server = getattr(request.module, "smtpserver", "merlinux.eu")
|
||||
smtp = smtplib.SMTP(server)
|
||||
|
||||
|
||||
def fin():
|
||||
print ("finalizing %s (%s)" % (smtp, server))
|
||||
smtp.close()
|
||||
|
||||
return smtp
|
||||
|
||||
return smtp
|
||||
|
||||
We use the ``request.module`` attribute to optionally obtain an
|
||||
``smtpserver`` attribute from the test module. If we just execute
|
||||
@@ -312,13 +312,13 @@ again, nothing much has changed::
|
||||
|
||||
$ py.test -s -q --tb=no
|
||||
FF
|
||||
2 failed in 0.23 seconds
|
||||
2 failed in 0.59 seconds
|
||||
|
||||
Let's quickly create another test module that actually sets the
|
||||
server URL in its module namespace::
|
||||
|
||||
|
||||
# content of test_anothersmtp.py
|
||||
|
||||
|
||||
smtpserver = "mail.python.org" # will be read by smtp fixture
|
||||
|
||||
def test_showhelo(smtp):
|
||||
@@ -346,7 +346,7 @@ Fixture functions can be parametrized in which case they will be called
|
||||
multiple times, each time executing the set of dependent tests, i. e. the
|
||||
tests that depend on this fixture. Test functions do usually not need
|
||||
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.
|
||||
|
||||
Extending the previous example, we can flag the fixture to create two
|
||||
@@ -358,7 +358,7 @@ through the special :py:class:`request <FixtureRequest>` object::
|
||||
import pytest
|
||||
import smtplib
|
||||
|
||||
@pytest.fixture(scope="module",
|
||||
@pytest.fixture(scope="module",
|
||||
params=["merlinux.eu", "mail.python.org"])
|
||||
def smtp(request):
|
||||
smtp = smtplib.SMTP(request.param)
|
||||
@@ -368,10 +368,10 @@ through the special :py:class:`request <FixtureRequest>` object::
|
||||
request.addfinalizer(fin)
|
||||
return smtp
|
||||
|
||||
The main change is the declaration of ``params`` with
|
||||
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.
|
||||
a value via ``request.param``. No test function code needs to change.
|
||||
So let's just do another run::
|
||||
|
||||
$ py.test -q test_module.py
|
||||
@@ -379,7 +379,7 @@ So let's just do another run::
|
||||
================================= FAILURES =================================
|
||||
__________________________ test_ehlo[merlinux.eu] __________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x15f7998>
|
||||
smtp = <smtplib.SMTP instance at 0x21f3e60>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -391,7 +391,7 @@ So let's just do another run::
|
||||
test_module.py:6: AssertionError
|
||||
__________________________ test_noop[merlinux.eu] __________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x15f7998>
|
||||
smtp = <smtplib.SMTP instance at 0x21f3e60>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -402,7 +402,7 @@ So let's just do another run::
|
||||
test_module.py:11: AssertionError
|
||||
________________________ test_ehlo[mail.python.org] ________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x16535f0>
|
||||
smtp = <smtplib.SMTP instance at 0x22047e8>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -412,10 +412,10 @@ So let's just do another run::
|
||||
|
||||
test_module.py:5: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
finalizing <smtplib.SMTP instance at 0x15f7998>
|
||||
finalizing <smtplib.SMTP instance at 0x21f3e60>
|
||||
________________________ test_noop[mail.python.org] ________________________
|
||||
|
||||
smtp = <smtplib.SMTP instance at 0x16535f0>
|
||||
smtp = <smtplib.SMTP instance at 0x22047e8>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -424,11 +424,11 @@ So let's just do another run::
|
||||
E assert 0
|
||||
|
||||
test_module.py:11: AssertionError
|
||||
4 failed in 6.30 seconds
|
||||
4 failed in 6.06 seconds
|
||||
|
||||
We see that our two test functions each ran twice, against the different
|
||||
``smtp`` instances. Note also, that with the ``mail.python.org``
|
||||
connection the second test fails in ``test_ehlo`` because a
|
||||
``smtp`` instances. Note also, that with the ``mail.python.org``
|
||||
connection the second test fails in ``test_ehlo`` because a
|
||||
different server string is expected than what arrived.
|
||||
|
||||
|
||||
@@ -445,7 +445,7 @@ and instantiate an object ``app`` where we stick the already defined
|
||||
``smtp`` resource into it::
|
||||
|
||||
# content of test_appsetup.py
|
||||
|
||||
|
||||
import pytest
|
||||
|
||||
class App:
|
||||
@@ -464,22 +464,22 @@ Here we declare an ``app`` fixture which receives the previously defined
|
||||
|
||||
$ py.test -v test_appsetup.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_appsetup.py:12: test_smtp_exists[merlinux.eu] PASSED
|
||||
test_appsetup.py:12: test_smtp_exists[mail.python.org] PASSED
|
||||
|
||||
========================= 2 passed in 5.63 seconds =========================
|
||||
========================= 2 passed in 6.42 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.
|
||||
need for the ``app`` fixture to be aware of the ``smtp`` parametrization
|
||||
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
|
||||
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.
|
||||
@@ -494,11 +494,11 @@ Automatic grouping of tests by fixture instances
|
||||
|
||||
pytest minimizes the number of active fixtures during test runs.
|
||||
If you have a parametrized fixture, then all the tests using it will
|
||||
first execute with one instance and then finalizers are called
|
||||
first execute with one instance and then finalizers are called
|
||||
before the next fixture instance is created. Among other things,
|
||||
this eases testing of applications which create and use global state.
|
||||
|
||||
The following example uses two parametrized funcargs, one of which is
|
||||
The following example uses two parametrized funcargs, one of which is
|
||||
scoped on a per-module basis, and all the functions perform ``print`` calls
|
||||
to show the setup/teardown flow::
|
||||
|
||||
@@ -528,7 +528,7 @@ Let's run the tests in verbose mode and with looking at the print-output::
|
||||
|
||||
$ py.test -v -s test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2 -- /home/hpk/p/pytest/.tox/regen/bin/python
|
||||
collecting ... collected 8 items
|
||||
|
||||
test_module.py:15: test_0[1] test0 1
|
||||
@@ -553,7 +553,7 @@ Let's run the tests in verbose mode and with looking at the print-output::
|
||||
========================= 8 passed in 0.01 seconds =========================
|
||||
|
||||
You can see that the parametrized module-scoped ``modarg`` resource caused
|
||||
an ordering of test execution that lead to the fewest possible "active" resources. The finalizer for the ``mod1`` parametrized resource was executed
|
||||
an ordering of test execution that lead to the fewest possible "active" resources. The finalizer for the ``mod1`` parametrized resource was executed
|
||||
before the ``mod2`` resource was setup.
|
||||
|
||||
|
||||
@@ -573,7 +573,7 @@ achieve it. We separate the creation of the fixture into a conftest.py
|
||||
file::
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
|
||||
import pytest
|
||||
import tempfile
|
||||
import os
|
||||
@@ -612,12 +612,12 @@ You can specify multiple fixtures like this::
|
||||
|
||||
@pytest.mark.usefixtures("cleandir", "anotherfixture")
|
||||
|
||||
and you may specify fixture usage at the test module level, using
|
||||
and you may specify fixture usage at the test module level, using
|
||||
a generic feature of the mark mechanism::
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("cleandir")
|
||||
|
||||
Lastly you can put fixtures required by all tests in your project
|
||||
Lastly you can put fixtures required by all tests in your project
|
||||
into an ini-file::
|
||||
|
||||
# content of pytest.ini
|
||||
@@ -626,6 +626,7 @@ into an ini-file::
|
||||
usefixtures = cleandir
|
||||
|
||||
|
||||
.. _`autouse`:
|
||||
.. _`autouse fixtures`:
|
||||
|
||||
autouse fixtures (xUnit setup on steroids)
|
||||
@@ -634,14 +635,14 @@ autouse fixtures (xUnit setup on steroids)
|
||||
.. regendoc:wipe
|
||||
|
||||
Occasionally, you may want to have fixtures get invoked automatically
|
||||
without a `usefixtures`_ or `funcargs`_ reference. As a practical
|
||||
without a `usefixtures`_ or `funcargs`_ reference. As a practical
|
||||
example, suppose we have a database fixture which has a
|
||||
begin/rollback/commit architecture and we want to automatically surround
|
||||
each test method by a transaction and a rollback. Here is a dummy
|
||||
self-contained implementation of this idea::
|
||||
|
||||
# content of test_db_transact.py
|
||||
|
||||
|
||||
import pytest
|
||||
|
||||
class DB:
|
||||
@@ -681,11 +682,11 @@ If we run it, we get two passing tests::
|
||||
|
||||
Here is how autouse fixtures work in other scopes:
|
||||
|
||||
- if an autouse fixture is defined in a test module, all its test
|
||||
functions automatically use it.
|
||||
- if an autouse fixture is defined in a test module, all its test
|
||||
functions automatically use it.
|
||||
|
||||
- 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.
|
||||
- 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 autouse
|
||||
fixture in a plugin, it will be invoked for all tests in all projects
|
||||
@@ -696,7 +697,7 @@ Here is how autouse 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
|
||||
active. The canonical way to do that is to put the transact definition
|
||||
into a conftest.py file **without** using ``autouse``::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -713,7 +714,7 @@ and then e.g. have a TestClass using it by declaring the need::
|
||||
...
|
||||
|
||||
All test methods in this TestClass will use the transaction fixture while
|
||||
other test classes or functions in the module will not use it unless
|
||||
other test classes or functions in the module will not use it unless
|
||||
they also add a ``transact`` reference.
|
||||
|
||||
Shifting (visibility of) fixture functions
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Installation and Getting Started
|
||||
===================================
|
||||
|
||||
**Pythons**: Python 2.4-3.3, Jython, PyPy
|
||||
**Pythons**: Python 2.5-3.3, Jython, PyPy
|
||||
|
||||
**Platforms**: Unix/Posix and Windows
|
||||
|
||||
@@ -23,7 +23,7 @@ Installation options::
|
||||
To check your installation has installed the correct version::
|
||||
|
||||
$ py.test --version
|
||||
This is py.test version 2.5.0, imported from /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/pytest.pyc
|
||||
This is pytest version 2.5.2, imported from /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/pytest.pyc
|
||||
|
||||
If you get an error checkout :ref:`installation issues`.
|
||||
|
||||
@@ -45,7 +45,7 @@ That's it. You can execute the test function now::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_sample.py F
|
||||
@@ -61,7 +61,7 @@ That's it. You can execute the test function now::
|
||||
test_sample.py:5: AssertionError
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
py.test found the ``test_answer`` function by following :ref:`standard test discovery rules <test discovery>`, basically detecting the ``test_`` prefixes. We got a failure report because our little ``func(3)`` call did not return ``5``.
|
||||
``pytest`` found the ``test_answer`` function by following :ref:`standard test discovery rules <test discovery>`, basically detecting the ``test_`` prefixes. We got a failure report because our little ``func(3)`` call did not return ``5``.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -123,7 +123,7 @@ run the module by passing its filename::
|
||||
================================= FAILURES =================================
|
||||
____________________________ TestClass.test_two ____________________________
|
||||
|
||||
self = <test_class.TestClass instance at 0x2a8fef0>
|
||||
self = <test_class.TestClass instance at 0x255a0e0>
|
||||
|
||||
def test_two(self):
|
||||
x = "hello"
|
||||
@@ -142,7 +142,7 @@ Going functional: requesting a unique temporary directory
|
||||
|
||||
For functional tests one often needs to create some files
|
||||
and pass them to application objects. pytest provides
|
||||
:ref:`builtinfixtures` which allow to request arbitrary
|
||||
:ref:`builtinfixtures` which allow to request arbitrary
|
||||
resources, for example a unique temporary directory::
|
||||
|
||||
# content of test_tmpdir.py
|
||||
@@ -151,7 +151,7 @@ resources, for example a unique temporary directory::
|
||||
assert 0
|
||||
|
||||
We list the name ``tmpdir`` in the test function signature and
|
||||
py.test will lookup and call a fixture factory to create the resource
|
||||
``pytest`` will lookup and call a fixture factory to create the resource
|
||||
before performing the test function call. Let's just run it::
|
||||
|
||||
$ py.test -q test_tmpdir.py
|
||||
@@ -159,7 +159,7 @@ before performing the test function call. Let's just run it::
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_needsfiles ______________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-277/test_needsfiles0')
|
||||
tmpdir = local('/tmp/pytest-1008/test_needsfiles0')
|
||||
|
||||
def test_needsfiles(tmpdir):
|
||||
print tmpdir
|
||||
@@ -168,7 +168,7 @@ before performing the test function call. Let's just run it::
|
||||
|
||||
test_tmpdir.py:3: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
/tmp/pytest-277/test_needsfiles0
|
||||
/tmp/pytest-1008/test_needsfiles0
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
Before the test runs, a unique-per-test-invocation temporary directory
|
||||
@@ -186,7 +186,7 @@ Here are a few suggestions where to go next:
|
||||
* :ref:`cmdline` for command line invocation examples
|
||||
* :ref:`good practises <goodpractises>` for virtualenv, test layout, genscript support
|
||||
* :ref:`fixtures` for providing a functional baseline to your tests
|
||||
* :ref:`apiref` for documentation and examples on using py.test
|
||||
* :ref:`apiref` for documentation and examples on using ``pytest``
|
||||
* :ref:`plugins` managing and writing plugins
|
||||
|
||||
.. _`installation issues`:
|
||||
@@ -221,7 +221,7 @@ py.test not found on Windows despite installation?
|
||||
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
|
||||
so ``py.test`` will not work correctly. You may install py.test on
|
||||
CPython and type ``py.test --genscript=mytest`` and then use
|
||||
``jython mytest`` to run py.test for your tests to run with Jython.
|
||||
``jython mytest`` to run your tests with Jython using ``pytest``.
|
||||
|
||||
:ref:`examples` for more complex examples
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ Good Integration Practises
|
||||
Work with virtual environments
|
||||
-----------------------------------------------------------
|
||||
|
||||
We recommend to use virtualenv_ environments and use pip_
|
||||
(or easy_install_) for installing your application and any dependencies
|
||||
We recommend to use virtualenv_ environments and use pip_
|
||||
(or easy_install_) for installing your application and any dependencies
|
||||
as well as the ``pytest`` package itself. This way you will get an isolated
|
||||
and reproducible environment. Given you have installed virtualenv_
|
||||
and execute it from the command line, here is an example session for unix
|
||||
@@ -27,19 +27,19 @@ We can now install pytest::
|
||||
|
||||
Due to the ``activate`` step above the ``pip`` will come from
|
||||
the virtualenv directory and install any package into the isolated
|
||||
virtual environment.
|
||||
virtual environment.
|
||||
|
||||
Choosing a test layout / import rules
|
||||
------------------------------------------
|
||||
|
||||
py.test supports two common test layouts:
|
||||
``pytest`` supports two common test layouts:
|
||||
|
||||
* putting tests into an extra directory outside your actual application
|
||||
code, useful if you have many functional tests or for other reasons
|
||||
want to keep tests separate from actual application code (often a good
|
||||
idea)::
|
||||
|
||||
setup.py # your distutils/setuptools Python package metadata
|
||||
setup.py # your distutils/setuptools Python package metadata
|
||||
mypkg/
|
||||
__init__.py
|
||||
appmodule.py
|
||||
@@ -48,11 +48,11 @@ py.test supports two common test layouts:
|
||||
...
|
||||
|
||||
|
||||
* inlining test directories into your application package, useful if you
|
||||
* inlining test directories into your application package, useful if you
|
||||
have direct relation between (unit-)test and application modules and
|
||||
want to distribute your tests along with your application::
|
||||
|
||||
setup.py # your distutils/setuptools Python package metadata
|
||||
setup.py # your distutils/setuptools Python package metadata
|
||||
mypkg/
|
||||
__init__.py
|
||||
appmodule.py
|
||||
@@ -68,11 +68,11 @@ Important notes relating to both schemes:
|
||||
pip install -e . # install package using setup.py in editable mode
|
||||
|
||||
- **avoid "__init__.py" files in your test directories**.
|
||||
This way your tests can run easily against an installed version
|
||||
of ``mypkg``, independently from if the installed version contains
|
||||
the tests or not.
|
||||
This way your tests can run easily against an installed version
|
||||
of ``mypkg``, independently from if the installed package contains
|
||||
the tests or not.
|
||||
|
||||
- With inlined tests you might put ``__init__.py`` into test
|
||||
- With inlined tests you might put ``__init__.py`` into test
|
||||
directories and make them installable as part of your application.
|
||||
Using the ``py.test --pyargs mypkg`` invocation pytest will
|
||||
discover where mypkg is installed and collect tests from there.
|
||||
@@ -87,29 +87,27 @@ Typically you can run tests by pointing to test directories or modules::
|
||||
py.test # run all tests below current dir
|
||||
...
|
||||
|
||||
Because of the above ``editable install`` mode you can change your
|
||||
Because of the above ``editable install`` mode you can change your
|
||||
source code (both tests and the app) and rerun tests at will.
|
||||
Once you are done with your work, you can `use tox`_ to make sure
|
||||
that the package is really correct and tests pass in all
|
||||
that the package is really correct and tests pass in all
|
||||
required configurations.
|
||||
|
||||
.. note::
|
||||
|
||||
You can use Python3 namespace packages (PEP420) for your application
|
||||
but pytest will still perform `package name`_ discovery based on the
|
||||
presence of ``__init__.py`` files. If you use one of the above
|
||||
two recommended file system layouts but leave away the ``__init__.py``
|
||||
files it should just work on Python3.3 and above. When using
|
||||
but pytest will still perform `test package name`_ discovery based on the
|
||||
presence of ``__init__.py`` files. If you use one of the
|
||||
two recommended file system layouts above but leave away the ``__init__.py``
|
||||
files from your directories it should just work on Python3.3 and above. From
|
||||
"inlined tests", however, you will need to use absolute imports for
|
||||
getting at your application code because the test modules will be
|
||||
imported directly, without any application context. The latter allows
|
||||
your tests to run against an installed version of your package.
|
||||
getting at your application code.
|
||||
|
||||
.. _`package name`:
|
||||
.. _`test package name`:
|
||||
|
||||
.. note::
|
||||
|
||||
If py.test finds a "a/b/test_module.py" test file while
|
||||
If ``pytest`` finds a "a/b/test_module.py" test file while
|
||||
recursing into the filesystem it determines the import name
|
||||
as follows:
|
||||
|
||||
@@ -157,17 +155,17 @@ to create a JUnitXML file that Jenkins_ can pick up and generate reports.
|
||||
.. _standalone:
|
||||
.. _`genscript method`:
|
||||
|
||||
Create a py.test standalone script
|
||||
Create a pytest standalone script
|
||||
-------------------------------------------
|
||||
|
||||
If you are a maintainer or application developer and want people
|
||||
who don't deal with python much to easily run tests you may generate
|
||||
a standalone "py.test" script::
|
||||
who don't deal with python much to easily run tests you may generate
|
||||
a standalone ``pytest`` script::
|
||||
|
||||
py.test --genscript=runtests.py
|
||||
|
||||
This generates a ``runtests.py`` script which is a fully functional basic
|
||||
``py.test`` script, running unchanged under Python2 and Python3.
|
||||
``pytest`` script, running unchanged under Python2 and Python3.
|
||||
You can tell people to download the script and then e.g. run it like this::
|
||||
|
||||
python runtests.py
|
||||
@@ -178,7 +176,7 @@ Integrating with distutils / ``python setup.py test``
|
||||
|
||||
You can integrate test runs into your distutils or
|
||||
setuptools based project. Use the `genscript method`_
|
||||
to generate a standalone py.test script::
|
||||
to generate a standalone ``pytest`` script::
|
||||
|
||||
py.test --genscript=runtests.py
|
||||
|
||||
@@ -209,7 +207,7 @@ If you now type::
|
||||
python setup.py test
|
||||
|
||||
this will execute your tests using ``runtests.py``. As this is a
|
||||
standalone version of ``py.test`` no prior installation whatsoever is
|
||||
standalone version of ``pytest`` no prior installation whatsoever is
|
||||
required for calling the test command. You can also pass additional
|
||||
arguments to the subprocess-calls such as your test directory or other
|
||||
options.
|
||||
@@ -246,7 +244,7 @@ Now if you run::
|
||||
|
||||
python setup.py test
|
||||
|
||||
this will download py.test if needed and then run py.test
|
||||
this will download ``pytest`` if needed and then run your tests
|
||||
as you would expect it to.
|
||||
|
||||
.. _`test discovery`:
|
||||
@@ -255,7 +253,7 @@ as you would expect it to.
|
||||
Conventions for Python test discovery
|
||||
-------------------------------------------------
|
||||
|
||||
``py.test`` implements the following standard test discovery:
|
||||
``pytest`` implements the following standard test discovery:
|
||||
|
||||
* collection starts from the initial command line arguments
|
||||
which may be directories, filenames or test ids.
|
||||
@@ -266,7 +264,7 @@ Conventions for Python test discovery
|
||||
|
||||
For examples of how to customize your test discovery :doc:`example/pythoncollection`.
|
||||
|
||||
Within Python modules, py.test also discovers tests using the standard
|
||||
Within Python modules, ``pytest`` also discovers tests using the standard
|
||||
:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
|
||||
|
||||
.. include:: links.inc
|
||||
|
||||
BIN
doc/en/img/pullrequest.png
Normal file
BIN
doc/en/img/pullrequest.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
@@ -1,7 +1,7 @@
|
||||
|
||||
.. _features:
|
||||
|
||||
.. note:: second training: `professional testing with Python <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_ , 25-27th November 2013, Leipzig.
|
||||
.. second training: `professional testing with Python <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_ , 25-27th November 2013, Leipzig.
|
||||
|
||||
pytest: helps you write better programs
|
||||
=============================================
|
||||
@@ -9,44 +9,43 @@ pytest: helps you write better programs
|
||||
**a mature full-featured Python testing tool**
|
||||
|
||||
- runs on Posix/Windows, Python 2.5-3.3, PyPy and Jython-2.5.1
|
||||
- **zero-reported-bugs** policy with >1000 tests against itself
|
||||
- **strict backward compatibility policy** for safe pytest upgrades
|
||||
- :ref:`comprehensive online <toc>` and `PDF documentation <pytest.pdf>`_
|
||||
- many :ref:`third party plugins <extplugins>` and
|
||||
:ref:`builtin helpers <pytest helpers>`
|
||||
- used in :ref:`many projects and organisations <projects>`, in test
|
||||
suites with up to twenty thousand tests
|
||||
- strict policy of remaining backward compatible across releases
|
||||
- many :ref:`third party plugins <extplugins>` and :ref:`builtin helpers <pytest helpers>`,
|
||||
- used in :ref:`many small and large projects and organisations <projects>`
|
||||
- comes with many :ref:`tested examples <examples>`
|
||||
|
||||
**provides easy no-boilerplate testing**
|
||||
|
||||
- makes it :ref:`easy to get started <getstarted>`,
|
||||
many :ref:`usage options <usage>`
|
||||
has many :ref:`usage options <usage>`
|
||||
- :ref:`assert with the assert statement`
|
||||
- helpful :ref:`traceback and failing assertion reporting <tbreportdemo>`
|
||||
- allows :ref:`print debugging <printdebugging>` and :ref:`the
|
||||
- :ref:`print debugging <printdebugging>` and :ref:`the
|
||||
capturing of standard output during test execution <captures>`
|
||||
|
||||
**scales from simple unit to complex functional testing**
|
||||
|
||||
- :ref:`modular parametrizeable fixtures <fixture>` (new in 2.3,
|
||||
improved in 2.4)
|
||||
continously improved)
|
||||
- :ref:`parametrized test functions <parametrized test functions>`
|
||||
- :ref:`mark`
|
||||
- :ref:`skipping` (improved in 2.4)
|
||||
- can :ref:`distribute tests to multiple CPUs <xdistcpu>` through :ref:`xdist plugin <xdist>`
|
||||
- can :ref:`continuously re-run failing tests <looponfailing>`
|
||||
- :ref:`distribute tests to multiple CPUs <xdistcpu>` through :ref:`xdist plugin <xdist>`
|
||||
- :ref:`continuously re-run failing tests <looponfailing>`
|
||||
- flexible :ref:`Python test discovery`
|
||||
|
||||
**integrates many common testing methods**:
|
||||
**integrates with other testing methods and tools**:
|
||||
|
||||
- multi-paradigm: pytest can run many ``nose``, ``unittest.py`` and
|
||||
``doctest.py`` style test suites, including running testcases made for
|
||||
- multi-paradigm: pytest can run ``nose``, ``unittest`` and
|
||||
``doctest`` style test suites, including running testcases made for
|
||||
Django and trial
|
||||
- supports :ref:`good integration practises <goodpractises>`
|
||||
- supports extended :ref:`xUnit style setup <xunitsetup>`
|
||||
- supports domain-specific :ref:`non-python tests`
|
||||
- supports the generation of testing coverage reports
|
||||
- `Javascript unit- and functional testing`_
|
||||
- supports generating `test coverage reports
|
||||
<https://pypi.python.org/pypi/pytest-cov>`_
|
||||
- supports :pep:`8` compliant coding styles in tests
|
||||
|
||||
**extensive plugin and customization system**:
|
||||
@@ -56,8 +55,6 @@ pytest: helps you write better programs
|
||||
- it is easy to add command line options or customize existing behaviour
|
||||
|
||||
|
||||
.. _`Javascript unit- and functional testing`: http://pypi.python.org/pypi/oejskit
|
||||
|
||||
.. _`easy`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ Running tests written for nose
|
||||
|
||||
.. include:: links.inc
|
||||
|
||||
py.test has basic support for running tests written for nose_.
|
||||
``pytest`` has basic support for running tests written for nose_.
|
||||
|
||||
.. _nosestyle:
|
||||
|
||||
@@ -16,7 +16,7 @@ After :ref:`installation` type::
|
||||
py.test # instead of 'nosetests'
|
||||
|
||||
and you should be able to run your nose style tests and
|
||||
make use of py.test's capabilities.
|
||||
make use of pytest's capabilities.
|
||||
|
||||
Supported nose Idioms
|
||||
----------------------
|
||||
@@ -30,10 +30,10 @@ Supported nose Idioms
|
||||
Unsupported idioms / known issues
|
||||
----------------------------------
|
||||
|
||||
- unittest-style ``setUp, tearDown, setUpClass, tearDownClass``
|
||||
- unittest-style ``setUp, tearDown, setUpClass, tearDownClass``
|
||||
are recognized only on ``unittest.TestCase`` classes but not
|
||||
on plain classes. ``nose`` supports these methods also on plain
|
||||
classes but pytest deliberately does not. As nose and pytest already
|
||||
classes but pytest deliberately does not. As nose and pytest already
|
||||
both support ``setup_class, teardown_class, setup_method, teardown_method``
|
||||
it doesn't seem useful to duplicate the unittest-API like nose does.
|
||||
If you however rather think pytest should support the unittest-spelling on
|
||||
@@ -44,9 +44,9 @@ Unsupported idioms / known issues
|
||||
``tests.test_mod``) but different file system paths
|
||||
(e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``)
|
||||
by extending sys.path/import semantics. pytest does not do that
|
||||
but there is discussion in `issue268 <https://bitbucket.org/hpk42/pytest/issue/268>`_ for adding some support. Note that
|
||||
but there is discussion in `issue268 <https://bitbucket.org/hpk42/pytest/issue/268>`_ for adding some support. Note that
|
||||
`nose2 choose to avoid this sys.path/import hackery <https://nose2.readthedocs.org/en/latest/differences.html#test-discovery-and-loading>`_.
|
||||
|
||||
|
||||
- nose-style doctests are not collected and executed correctly,
|
||||
also doctest fixtures don't work.
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ pytest supports test parametrization in several well-integrated ways:
|
||||
at the level of fixture functions <fixture-parametrize>`.
|
||||
|
||||
* `@pytest.mark.parametrize`_ allows to define parametrization at the
|
||||
function or class level, provides multiple argument/fixture sets
|
||||
function or class level, provides multiple argument/fixture sets
|
||||
for a particular test function or class.
|
||||
|
||||
* `pytest_generate_tests`_ enables implementing your own custom
|
||||
* `pytest_generate_tests`_ enables implementing your own custom
|
||||
dynamic parametrization scheme or extensions.
|
||||
|
||||
.. _parametrizemark:
|
||||
@@ -47,13 +47,13 @@ to an expected output::
|
||||
def test_eval(input, expected):
|
||||
assert eval(input) == expected
|
||||
|
||||
Here, the ``@parametrize`` decorator defines three different ``(input,output)``
|
||||
tuples so that that the ``test_eval`` function will run three times using
|
||||
Here, the ``@parametrize`` decorator defines three different ``(input,expected)``
|
||||
tuples so that the ``test_eval`` function will run three times using
|
||||
them in turn::
|
||||
|
||||
$ py.test
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..F
|
||||
@@ -100,7 +100,7 @@ Let's run this::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..x
|
||||
@@ -114,8 +114,8 @@ shows up as an "xfailed (expected to fail)" test.
|
||||
|
||||
In versions prior to 2.4 one needed to specify the argument
|
||||
names as a tuple. This remains valid but the simpler ``"name1,name2,..."``
|
||||
comma-separated-string syntax is now advertised fist because
|
||||
it's easier to write, produces less line noise.
|
||||
comma-separated-string syntax is now advertised first because
|
||||
it's easier to write and produces less line noise.
|
||||
|
||||
.. _`pytest_generate_tests`:
|
||||
|
||||
@@ -124,14 +124,14 @@ Basic ``pytest_generate_tests`` example
|
||||
|
||||
Sometimes you may want to implement your own parametrization scheme
|
||||
or implement some dynamism for determining the parameters or scope
|
||||
of a fixture. For this, you can use the ``pytest_generate_tests`` hook
|
||||
of a fixture. For this, you can use the ``pytest_generate_tests`` hook
|
||||
which is called when collecting a test function. Through the passed in
|
||||
`metafunc` object you can inspect the requesting test context and, most
|
||||
importantly, you can call ``metafunc.parametrize()`` to cause
|
||||
parametrization.
|
||||
parametrization.
|
||||
|
||||
For example, let's say we want to run a test taking string inputs which
|
||||
we want to set via a new py.test command line option. Let's first write
|
||||
we want to set via a new ``pytest`` command line option. Let's first write
|
||||
a simple test accepting a ``stringinput`` fixture function argument::
|
||||
|
||||
# content of test_strings.py
|
||||
@@ -139,7 +139,7 @@ a simple test accepting a ``stringinput`` fixture function argument::
|
||||
def test_valid_string(stringinput):
|
||||
assert stringinput.isalpha()
|
||||
|
||||
Now we add a ``conftest.py`` file containing the addition of a
|
||||
Now we add a ``conftest.py`` file containing the addition of a
|
||||
command line option and the parametrization of our test function::
|
||||
|
||||
# content of conftest.py
|
||||
@@ -150,7 +150,7 @@ command line option and the parametrization of our test function::
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'stringinput' in metafunc.fixturenames:
|
||||
metafunc.parametrize("stringinput",
|
||||
metafunc.parametrize("stringinput",
|
||||
metafunc.config.option.stringinput)
|
||||
|
||||
If we now pass two stringinput values, our test will run twice::
|
||||
@@ -170,22 +170,22 @@ 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 0x2b4b17865198>()
|
||||
E + where <built-in method isalpha of str object at 0x2b4b17865198> = '!'.isalpha
|
||||
E assert <built-in method isalpha of str object at 0x2b869b32b148>()
|
||||
E + where <built-in method isalpha of str object at 0x2b869b32b148> = '!'.isalpha
|
||||
|
||||
test_strings.py:3: AssertionError
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
As expected our test function fails.
|
||||
As expected our test function fails.
|
||||
|
||||
If you don't specify a stringinput it will be skipped because
|
||||
``metafunc.parametrize()`` will be called with an empty parameter
|
||||
listlist::
|
||||
|
||||
$ py.test -q -rs test_strings.py
|
||||
$ 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:1087: got empty parameter set, function test_valid_string at /tmp/doc-exec-24/test_strings.py:1
|
||||
SKIP [1] /home/hpk/p/pytest/.tox/regen/local/lib/python2.7/site-packages/_pytest/python.py:1110: got empty parameter set, function test_valid_string at /tmp/doc-exec-24/test_strings.py:1
|
||||
1 skipped in 0.01 seconds
|
||||
|
||||
For further examples, you might want to look at :ref:`more
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
Working with plugins and conftest files
|
||||
=============================================
|
||||
|
||||
py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types:
|
||||
``pytest`` implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic location types:
|
||||
|
||||
* `builtin plugins`_: loaded from py.test's internal ``_pytest`` directory.
|
||||
* `builtin plugins`_: loaded from pytest's internal ``_pytest`` directory.
|
||||
* `external plugins`_: modules discovered through `setuptools entry points`_
|
||||
* `conftest.py plugins`_: modules auto-discovered in test directories
|
||||
|
||||
@@ -63,8 +63,10 @@ tool, for example::
|
||||
pip install pytest-NAME
|
||||
pip uninstall pytest-NAME
|
||||
|
||||
If a plugin is installed, py.test automatically finds and integrates it,
|
||||
there is no need to activate it. Here is a initial list of known plugins:
|
||||
If a plugin is installed, ``pytest`` automatically finds and integrates it,
|
||||
there is no need to activate it. We have a :doc:`beta page listing
|
||||
all 3rd party plugins and their status <plugins_index/index>` and here
|
||||
is a little annotated list for some popular plugins:
|
||||
|
||||
.. _`django`: https://www.djangoproject.com/
|
||||
|
||||
@@ -84,14 +86,14 @@ there is no need to activate it. Here is a initial list of known plugins:
|
||||
* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_:
|
||||
to distribute tests to CPUs and remote hosts, to run in boxed
|
||||
mode which allows to survive segmentation faults, to run in
|
||||
looponfailing mode, automatically re-running failing tests
|
||||
looponfailing mode, automatically re-running failing tests
|
||||
on file changes, see also :ref:`xdist`
|
||||
|
||||
* `pytest-instafail <http://pypi.python.org/pypi/pytest-instafail>`_:
|
||||
to report failures while the test run is happening.
|
||||
|
||||
* `pytest-bdd <http://pypi.python.org/pypi/pytest-bdd>`_ and
|
||||
`pytest-konira <http://pypi.python.org/pypi/pytest-konira>`_
|
||||
`pytest-konira <http://pypi.python.org/pypi/pytest-konira>`_
|
||||
to write tests using behaviour-driven testing.
|
||||
|
||||
* `pytest-timeout <http://pypi.python.org/pypi/pytest-timeout>`_:
|
||||
@@ -122,7 +124,7 @@ If you want to write a plugin, there are many real-life examples
|
||||
you can copy from:
|
||||
|
||||
* a custom collection example plugin: :ref:`yaml plugin`
|
||||
* around 20 `builtin plugins`_ which provide py.test's own functionality
|
||||
* around 20 `builtin plugins`_ which provide pytest's own functionality
|
||||
* many `external plugins`_ providing additional features
|
||||
|
||||
All of these plugins implement the documented `well specified hooks`_
|
||||
@@ -135,10 +137,10 @@ Making your plugin installable by others
|
||||
|
||||
If you want to make your plugin externally available, you
|
||||
may define a so-called entry point for your distribution so
|
||||
that ``py.test`` finds your plugin module. Entry points are
|
||||
that ``pytest`` finds your plugin module. Entry points are
|
||||
a feature that is provided by `setuptools`_ or `Distribute`_.
|
||||
py.test looks up the ``pytest11`` entrypoint to discover its
|
||||
plugins and you can thus make your plugin available by definig
|
||||
pytest looks up the ``pytest11`` entrypoint to discover its
|
||||
plugins and you can thus make your plugin available by defining
|
||||
it in your setuptools/distribute-based setup-invocation:
|
||||
|
||||
.. sourcecode:: python
|
||||
@@ -150,7 +152,7 @@ it in your setuptools/distribute-based setup-invocation:
|
||||
name="myproject",
|
||||
packages = ['myproject']
|
||||
|
||||
# the following makes a plugin available to py.test
|
||||
# the following makes a plugin available to pytest
|
||||
entry_points = {
|
||||
'pytest11': [
|
||||
'name_of_plugin = myproject.pluginmodule',
|
||||
@@ -158,7 +160,7 @@ it in your setuptools/distribute-based setup-invocation:
|
||||
},
|
||||
)
|
||||
|
||||
If a package is installed this way, py.test will load
|
||||
If a package is installed this way, ``pytest`` will load
|
||||
``myproject.pluginmodule`` as a plugin which can define
|
||||
`well specified hooks`_.
|
||||
|
||||
@@ -167,7 +169,7 @@ If a package is installed this way, py.test will load
|
||||
Plugin discovery order at tool startup
|
||||
--------------------------------------------
|
||||
|
||||
py.test loads plugin modules at tool startup in the following way:
|
||||
``pytest`` loads plugin modules at tool startup in the following way:
|
||||
|
||||
* by loading all builtin plugins
|
||||
|
||||
@@ -177,9 +179,15 @@ py.test loads plugin modules at tool startup in the following way:
|
||||
and loading the specified plugin before actual command line parsing.
|
||||
|
||||
* by loading all :file:`conftest.py` files as inferred by the command line
|
||||
invocation (test files and all of its *parent* directories).
|
||||
Note that ``conftest.py`` files from *sub* directories are by default
|
||||
not loaded at tool startup.
|
||||
invocation:
|
||||
|
||||
- if no test paths are specified use current dir as a test path
|
||||
- if exists, load ``conftest.py`` and ``test*/conftest.py`` relative
|
||||
to the directory part of the first test path.
|
||||
|
||||
Note that pytest does not find ``conftest.py`` files in deeper nested
|
||||
sub directories at tool startup. It is usually a good idea to keep
|
||||
your conftest.py file in the top level test or project root directory.
|
||||
|
||||
* by recursively loading all plugins specified by the
|
||||
``pytest_plugins`` variable in ``conftest.py`` files
|
||||
@@ -197,7 +205,7 @@ will be loaded as well. You can also use dotted path like this::
|
||||
|
||||
pytest_plugins = "myapp.testsupport.myplugin"
|
||||
|
||||
which will import the specified module as a py.test plugin.
|
||||
which will import the specified module as a ``pytest`` plugin.
|
||||
|
||||
|
||||
Accessing another plugin by name
|
||||
@@ -243,7 +251,7 @@ how to obtain the name of a plugin.
|
||||
|
||||
.. _`builtin plugins`:
|
||||
|
||||
py.test default plugin reference
|
||||
pytest default plugin reference
|
||||
====================================
|
||||
|
||||
|
||||
@@ -277,14 +285,14 @@ in the `pytest repository <http://bitbucket.org/hpk42/pytest/>`_.
|
||||
|
||||
.. _`well specified hooks`:
|
||||
|
||||
py.test hook reference
|
||||
pytest hook reference
|
||||
====================================
|
||||
|
||||
Hook specification and validation
|
||||
-----------------------------------------
|
||||
|
||||
py.test calls hook functions to implement initialization, running,
|
||||
test execution and reporting. When py.test loads a plugin it validates
|
||||
``pytest`` calls hook functions to implement initialization, running,
|
||||
test execution and reporting. When ``pytest`` loads a plugin it validates
|
||||
that each hook function conforms to its respective hook specification.
|
||||
Each hook function name and its argument names need to match a hook
|
||||
specification. However, a hook function may accept *fewer* parameters
|
||||
@@ -327,7 +335,7 @@ the reporting hook to print information about a test run.
|
||||
Collection hooks
|
||||
------------------------------
|
||||
|
||||
py.test calls the following hooks for collecting files and directories:
|
||||
``pytest`` calls the following hooks for collecting files and directories:
|
||||
|
||||
.. autofunction:: pytest_ignore_collect
|
||||
.. autofunction:: pytest_collect_directory
|
||||
|
||||
112
doc/en/plugins_index/index.txt
Normal file
112
doc/en/plugins_index/index.txt
Normal file
@@ -0,0 +1,112 @@
|
||||
.. _plugins_index:
|
||||
|
||||
List of Third-Party Plugins
|
||||
===========================
|
||||
|
||||
========================================================================================== ======================================================================================================== ======================================================================================================== ============================================================= =============================================================================================================================================
|
||||
Name Py27 Py33 Repository Summary
|
||||
========================================================================================== ======================================================================================================== ======================================================================================================== ============================================================= =============================================================================================================================================
|
||||
`pytest-bdd-0.6.8 <http://pypi.python.org/pypi/pytest-bdd/0.6.8>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-0.6.8?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-0.6.8?py=py33&pytest=2.5.1 https://github.com/olegpidsadnyi/pytest-bdd BDD for pytest
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-0.6.8?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-0.6.8?py=py33&pytest=2.5.1
|
||||
`pytest-bdd-splinter-0.5.98 <http://pypi.python.org/pypi/pytest-bdd-splinter/0.5.98>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-splinter-0.5.98?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-splinter-0.5.98?py=py33&pytest=2.5.1 https://github.com/olegpidsadnyi/pytest-bdd-splinter Splinter subplugin for Pytest BDD plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-splinter-0.5.98?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-splinter-0.5.98?py=py33&pytest=2.5.1
|
||||
`pytest-bench-0.2.5 <http://pypi.python.org/pypi/pytest-bench/0.2.5>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-0.2.5?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-0.2.5?py=py33&pytest=2.5.1 http://github.com/concordusapps/pytest-bench Benchmark utility that plugs into pytest.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bench-0.2.5?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-0.2.5?py=py33&pytest=2.5.1
|
||||
`pytest-blockage-0.1 <http://pypi.python.org/pypi/pytest-blockage/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-0.1?py=py33&pytest=2.5.1 https://github.com/rob-b/pytest-blockage Disable network requests during a test run.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-0.1?py=py33&pytest=2.5.1
|
||||
`pytest-browsermob-proxy-0.1 <http://pypi.python.org/pypi/pytest-browsermob-proxy/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-0.1?py=py33&pytest=2.5.1 https://github.com/davehunt/pytest-browsermob-proxy BrowserMob proxy plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-0.1?py=py33&pytest=2.5.1
|
||||
`pytest-bugzilla-0.2 <http://pypi.python.org/pypi/pytest-bugzilla/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-0.2?py=py33&pytest=2.5.1 http://github.com/nibrahim/pytest_bugzilla py.test bugzilla integration plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-cache-1.0 <http://pypi.python.org/pypi/pytest-cache/1.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-1.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-1.0?py=py33&pytest=2.5.1 http://bitbucket.org/hpk42/pytest-cache/ pytest plugin with mechanisms for caching across test runs
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-cache-1.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-1.0?py=py33&pytest=2.5.1
|
||||
`pytest-capturelog-0.7 <http://pypi.python.org/pypi/pytest-capturelog/0.7>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-0.7?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-0.7?py=py33&pytest=2.5.1 http://bitbucket.org/memedough/pytest-capturelog/overview py.test plugin to capture log messages
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-0.7?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-0.7?py=py33&pytest=2.5.1
|
||||
`pytest-codecheckers-0.2 <http://pypi.python.org/pypi/pytest-codecheckers/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-0.2?py=py33&pytest=2.5.1 http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/ pytest plugin to add source code sanity checks (pep8 and friends)
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-contextfixture-0.1.1 <http://pypi.python.org/pypi/pytest-contextfixture/0.1.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-0.1.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-0.1.1?py=py33&pytest=2.5.1 http://github.com/pelme/pytest-contextfixture/ Define pytest fixtures as context managers.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-0.1.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-0.1.1?py=py33&pytest=2.5.1
|
||||
`pytest-couchdbkit-0.5.1 <http://pypi.python.org/pypi/pytest-couchdbkit/0.5.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-0.5.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-0.5.1?py=py33&pytest=2.5.1 http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit py.test extension for per-test couchdb databases using couchdbkit
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-0.5.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-0.5.1?py=py33&pytest=2.5.1
|
||||
`pytest-cov-1.6 <http://pypi.python.org/pypi/pytest-cov/1.6>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-1.6?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-1.6?py=py33&pytest=2.5.1 http://bitbucket.org/memedough/pytest-cov/overview py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-cov-1.6?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-1.6?py=py33&pytest=2.5.1
|
||||
`pytest-dbfixtures-0.4.3 <http://pypi.python.org/pypi/pytest-dbfixtures/0.4.3>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-0.4.3?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-0.4.3?py=py33&pytest=2.5.1 https://github.com/clearcode/pytest-dbfixtures dbfixtures plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-0.4.3?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-0.4.3?py=py33&pytest=2.5.1
|
||||
`pytest-django-2.5 <http://pypi.python.org/pypi/pytest-django/2.5>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-2.5?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-2.5?py=py33&pytest=2.5.1 http://pytest-django.readthedocs.org/ A Django plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-django-2.5?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-2.5?py=py33&pytest=2.5.1
|
||||
`pytest-django-lite-0.1.0 <http://pypi.python.org/pypi/pytest-django-lite/0.1.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-0.1.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-0.1.0?py=py33&pytest=2.5.1 UNKNOWN The bare minimum to integrate py.test with Django.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-0.1.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-0.1.0?py=py33&pytest=2.5.1
|
||||
`pytest-figleaf-1.0 <http://pypi.python.org/pypi/pytest-figleaf/1.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-1.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-1.0?py=py33&pytest=2.5.1 http://bitbucket.org/hpk42/pytest-figleaf py.test figleaf coverage plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-1.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-1.0?py=py33&pytest=2.5.1
|
||||
`pytest-flakes-0.2 <http://pypi.python.org/pypi/pytest-flakes/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-0.2?py=py33&pytest=2.5.1 https://github.com/fschulze/pytest-flakes pytest plugin to check source code with pyflakes
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-greendots-0.2 <http://pypi.python.org/pypi/pytest-greendots/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-0.2?py=py33&pytest=2.5.1 UNKNOWN Green progress dots
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-growl-0.2 <http://pypi.python.org/pypi/pytest-growl/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-0.2?py=py33&pytest=2.5.1 UNKNOWN Growl notifications for pytest results.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-growl-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-incremental-0.3.0 <http://pypi.python.org/pypi/pytest-incremental/0.3.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-0.3.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-0.3.0?py=py33&pytest=2.5.1 https://bitbucket.org/schettino72/pytest-incremental an incremental test runner (pytest plugin)
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-0.3.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-0.3.0?py=py33&pytest=2.5.1
|
||||
`pytest-instafail-0.1.1 <http://pypi.python.org/pypi/pytest-instafail/0.1.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-0.1.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-0.1.1?py=py33&pytest=2.5.1 https://github.com/jpvanhal/pytest-instafail py.test plugin to show failures instantly
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-0.1.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-0.1.1?py=py33&pytest=2.5.1
|
||||
`pytest-ipdb-0.1-prerelease <http://pypi.python.org/pypi/pytest-ipdb/0.1-prerelease>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-0.1-prerelease?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-0.1-prerelease?py=py33&pytest=2.5.1 https://github.com/mverteuil/pytest-ipdb A py.test plug-in to enable drop to ipdb debugger on test failure.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-0.1-prerelease?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-0.1-prerelease?py=py33&pytest=2.5.1
|
||||
`pytest-jira-0.01 <http://pypi.python.org/pypi/pytest-jira/0.01>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-0.01?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-0.01?py=py33&pytest=2.5.1 http://github.com/jlaska/pytest_jira py.test JIRA integration plugin, using markers
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-jira-0.01?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-0.01?py=py33&pytest=2.5.1
|
||||
`pytest-konira-0.2 <http://pypi.python.org/pypi/pytest-konira/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-0.2?py=py33&pytest=2.5.1 http://github.com/alfredodeza/pytest-konira Run Konira DSL tests with py.test
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-konira-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-localserver-0.3.2 <http://pypi.python.org/pypi/pytest-localserver/0.3.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-0.3.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-0.3.2?py=py33&pytest=2.5.1 http://bitbucket.org/basti/pytest-localserver/ py.test plugin to test server connections locally.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-0.3.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-0.3.2?py=py33&pytest=2.5.1
|
||||
`pytest-marker-bugzilla-0.06 <http://pypi.python.org/pypi/pytest-marker-bugzilla/0.06>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-0.06?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-0.06?py=py33&pytest=2.5.1 http://github.com/eanxgeek/pytest_marker_bugzilla py.test bugzilla integration plugin, using markers
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-0.06?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-0.06?py=py33&pytest=2.5.1
|
||||
`pytest-markfiltration-0.8 <http://pypi.python.org/pypi/pytest-markfiltration/0.8>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-0.8?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-0.8?py=py33&pytest=2.5.1 https://github.com/adamgoucher/pytest-markfiltration UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-0.8?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-0.8?py=py33&pytest=2.5.1
|
||||
`pytest-marks-0.4 <http://pypi.python.org/pypi/pytest-marks/0.4>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-0.4?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-0.4?py=py33&pytest=2.5.1 https://github.com/adamgoucher/pytest-marks UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-marks-0.4?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-0.4?py=py33&pytest=2.5.1
|
||||
`pytest-monkeyplus-1.1.0 <http://pypi.python.org/pypi/pytest-monkeyplus/1.1.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-1.1.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-1.1.0?py=py33&pytest=2.5.1 http://bitbucket.org/hsoft/pytest-monkeyplus/ pytest's monkeypatch subclass with extra functionalities
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-1.1.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-1.1.0?py=py33&pytest=2.5.1
|
||||
`pytest-mozwebqa-1.1.1 <http://pypi.python.org/pypi/pytest-mozwebqa/1.1.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-1.1.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-1.1.1?py=py33&pytest=2.5.1 https://github.com/davehunt/pytest-mozwebqa Mozilla WebQA plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-1.1.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-1.1.1?py=py33&pytest=2.5.1
|
||||
`pytest-oerp-0.2.0 <http://pypi.python.org/pypi/pytest-oerp/0.2.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-0.2.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-0.2.0?py=py33&pytest=2.5.1 http://github.com/santagada/pytest-oerp/ pytest plugin to test OpenERP modules
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-0.2.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-0.2.0?py=py33&pytest=2.5.1
|
||||
`pytest-osxnotify-0.1.4 <http://pypi.python.org/pypi/pytest-osxnotify/0.1.4>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-0.1.4?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-0.1.4?py=py33&pytest=2.5.1 https://github.com/dbader/pytest-osxnotify OS X notifications for py.test results.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-0.1.4?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-0.1.4?py=py33&pytest=2.5.1
|
||||
`pytest-paste-config-0.1 <http://pypi.python.org/pypi/pytest-paste-config/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-0.1?py=py33&pytest=2.5.1 UNKNOWN Allow setting the path to a paste config file
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-0.1?py=py33&pytest=2.5.1
|
||||
`pytest-pep8-1.0.5 <http://pypi.python.org/pypi/pytest-pep8/1.0.5>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-1.0.5?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-1.0.5?py=py33&pytest=2.5.1 http://bitbucket.org/hpk42/pytest-pep8/ pytest plugin to check PEP8 requirements
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-1.0.5?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-1.0.5?py=py33&pytest=2.5.1
|
||||
`pytest-poo-0.2 <http://pypi.python.org/pypi/pytest-poo/0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-0.2?py=py33&pytest=2.5.1 http://github.com/pelme/pytest-poo Visualize your crappy tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-poo-0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-0.2?py=py33&pytest=2.5.1
|
||||
`pytest-pydev-0.1 <http://pypi.python.org/pypi/pytest-pydev/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-0.1?py=py33&pytest=2.5.1 http://bitbucket.org/basti/pytest-pydev/ py.test plugin to connect to a remote debug server with PyDev or PyCharm.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-0.1?py=py33&pytest=2.5.1
|
||||
`pytest-qt-1.0.2 <http://pypi.python.org/pypi/pytest-qt/1.0.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-1.0.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-1.0.2?py=py33&pytest=2.5.1 http://github.com/nicoddemus/pytest-qt pytest plugin that adds fixtures for testing Qt (PyQt and PySide) applications.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-qt-1.0.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-1.0.2?py=py33&pytest=2.5.1
|
||||
`pytest-quickcheck-0.8 <http://pypi.python.org/pypi/pytest-quickcheck/0.8>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-0.8?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-0.8?py=py33&pytest=2.5.1 http://bitbucket.org/t2y/pytest-quickcheck/ pytest plugin to generate random data inspired by QuickCheck
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-0.8?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-0.8?py=py33&pytest=2.5.1
|
||||
`pytest-rage-0.1 <http://pypi.python.org/pypi/pytest-rage/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-0.1?py=py33&pytest=2.5.1 http://github.com/santagada/pytest-rage/ pytest plugin to implement PEP712
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-rage-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-0.1?py=py33&pytest=2.5.1
|
||||
`pytest-random-0.02 <http://pypi.python.org/pypi/pytest-random/0.02>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-0.02?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-0.02?py=py33&pytest=2.5.1 https://github.com/klrmn/pytest-random py.test plugin to randomize tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-random-0.02?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-random-0.02?py=py33&pytest=2.5.1
|
||||
`pytest-rerunfailures-0.03 <http://pypi.python.org/pypi/pytest-rerunfailures/0.03>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-0.03?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-0.03?py=py33&pytest=2.5.1 https://github.com/klrmn/pytest-rerunfailures py.test plugin to re-run tests to eliminate flakey failures
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-0.03?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-0.03?py=py33&pytest=2.5.1
|
||||
`pytest-runfailed-0.3 <http://pypi.python.org/pypi/pytest-runfailed/0.3>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-0.3?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-0.3?py=py33&pytest=2.5.1 http://github.com/dmerejkowsky/pytest-runfailed implement a --failed option for pytest
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-0.3?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-0.3?py=py33&pytest=2.5.1
|
||||
`pytest-runner-2.0 <http://pypi.python.org/pypi/pytest-runner/2.0>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-2.0?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-2.0?py=py33&pytest=2.5.1 https://bitbucket.org/jaraco/pytest-runner UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-runner-2.0?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-2.0?py=py33&pytest=2.5.1
|
||||
`pytest-sugar-0.2.2 <http://pypi.python.org/pypi/pytest-sugar/0.2.2>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-0.2.2?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-0.2.2?py=py33&pytest=2.5.1 http://pivotfinland.com/pytest-sugar/ py.test plugin that adds instafail, ETA and neat graphics
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-0.2.2?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-0.2.2?py=py33&pytest=2.5.1
|
||||
`pytest-timeout-0.3 <http://pypi.python.org/pypi/pytest-timeout/0.3>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-0.3?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-0.3?py=py33&pytest=2.5.1 http://bitbucket.org/flub/pytest-timeout/ pytest plugin to abort tests after a timeout
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-0.3?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-0.3?py=py33&pytest=2.5.1
|
||||
`pytest-twisted-1.4 <http://pypi.python.org/pypi/pytest-twisted/1.4>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-1.4?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-1.4?py=py33&pytest=2.5.1 https://github.com/schmir/pytest-twisted A twisted plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-1.4?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-1.4?py=py33&pytest=2.5.1
|
||||
`pytest-xdist-1.9 <http://pypi.python.org/pypi/pytest-xdist/1.9>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-1.9?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-1.9?py=py33&pytest=2.5.1 http://bitbucket.org/hpk42/pytest-xdist py.test xdist plugin for distributed testing and loop-on-failing modes
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-1.9?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-1.9?py=py33&pytest=2.5.1
|
||||
`pytest-xprocess-0.8 <http://pypi.python.org/pypi/pytest-xprocess/0.8>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-0.8?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-0.8?py=py33&pytest=2.5.1 http://bitbucket.org/hpk42/pytest-xprocess/ pytest plugin to manage external processes across test runs
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-0.8?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-0.8?py=py33&pytest=2.5.1
|
||||
`pytest-yamlwsgi-0.6 <http://pypi.python.org/pypi/pytest-yamlwsgi/0.6>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-0.6?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-0.6?py=py33&pytest=2.5.1 UNKNOWN Run tests against wsgi apps defined in yaml
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-0.6?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-0.6?py=py33&pytest=2.5.1
|
||||
`pytest-zap-0.1 <http://pypi.python.org/pypi/pytest-zap/0.1>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-0.1?py=py27&pytest=2.5.1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-0.1?py=py33&pytest=2.5.1 https://github.com/davehunt/pytest-zap OWASP ZAP plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-zap-0.1?py=py27&pytest=2.5.1 :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-0.1?py=py33&pytest=2.5.1
|
||||
|
||||
========================================================================================== ======================================================================================================== ======================================================================================================== ============================================================= =============================================================================================================================================
|
||||
|
||||
*(Updated on 2014-01-15)*
|
||||
@@ -1,9 +1,11 @@
|
||||
'''
|
||||
Script to generate the file `plugins_index.txt` with information about pytest plugins taken directly
|
||||
from a live PyPI server.
|
||||
"""
|
||||
Script to generate the file `index.txt` with information about
|
||||
pytest plugins taken directly from a live PyPI server.
|
||||
|
||||
This will evolve to include test compatibility (pythons and pytest versions) information also.
|
||||
'''
|
||||
Also includes plugin compatibility between different python and pytest versions,
|
||||
obtained from http://pytest-plugs.herokuapp.com.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from collections import namedtuple
|
||||
import datetime
|
||||
from distutils.version import LooseVersion
|
||||
@@ -11,183 +13,225 @@ import itertools
|
||||
from optparse import OptionParser
|
||||
import os
|
||||
import sys
|
||||
import xmlrpclib
|
||||
|
||||
import pytest
|
||||
|
||||
#===================================================================================================
|
||||
# iter_plugins
|
||||
#===================================================================================================
|
||||
|
||||
def get_proxy(url):
|
||||
"""
|
||||
wrapper function to obtain a xmlrpc proxy, taking in account import
|
||||
differences between python 2.X and 3.X
|
||||
|
||||
:param url: url to bind the proxy to
|
||||
:return: a ServerProxy instance
|
||||
"""
|
||||
if sys.version_info < (3, 0):
|
||||
from xmlrpclib import ServerProxy
|
||||
else:
|
||||
from xmlrpc.client import ServerProxy
|
||||
return ServerProxy(url)
|
||||
|
||||
|
||||
def iter_plugins(client, search='pytest-'):
|
||||
'''
|
||||
"""
|
||||
Returns an iterator of (name, version) from PyPI.
|
||||
|
||||
:param client: xmlrpclib.ServerProxy
|
||||
:param search: package names to search for
|
||||
'''
|
||||
for plug_data in client.search({'name' : search}):
|
||||
|
||||
:param client: ServerProxy
|
||||
:param search: package names to search for
|
||||
"""
|
||||
for plug_data in client.search({'name': search}):
|
||||
yield plug_data['name'], plug_data['version']
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# get_latest_versions
|
||||
#===================================================================================================
|
||||
def get_latest_versions(plugins):
|
||||
'''
|
||||
Returns an iterator of (name, version) from the given list of (name, version), but returning
|
||||
only the latest version of the package. Uses distutils.LooseVersion to ensure compatibility
|
||||
with PEP386.
|
||||
'''
|
||||
"""
|
||||
Returns an iterator of (name, version) from the given list of (name,
|
||||
version), but returning only the latest version of the package. Uses
|
||||
distutils.LooseVersion to ensure compatibility with PEP386.
|
||||
"""
|
||||
plugins = [(name, LooseVersion(version)) for (name, version) in plugins]
|
||||
for name, grouped_plugins in itertools.groupby(plugins, key=lambda x: x[0]):
|
||||
name, loose_version = list(grouped_plugins)[-1]
|
||||
yield name, str(loose_version)
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# obtain_plugins_table
|
||||
#===================================================================================================
|
||||
def obtain_plugins_table(plugins, client):
|
||||
'''
|
||||
Returns information to populate a table of plugins, their versions, authors, etc.
|
||||
|
||||
The returned information is a list of columns of `ColumnData` namedtuples(text, link). Link
|
||||
can be None if the text for that column should not be linked to anything.
|
||||
|
||||
|
||||
|
||||
def obtain_plugins_table(plugins, client):
|
||||
"""
|
||||
Returns information to populate a table of plugins, their versions,
|
||||
authors, etc.
|
||||
|
||||
The returned information is a list of columns of `ColumnData`
|
||||
namedtuples(text, link). Link can be None if the text for that column
|
||||
should not be linked to anything.
|
||||
|
||||
:param plugins: list of (name, version)
|
||||
:param client: xmlrpclib.ServerProxy
|
||||
'''
|
||||
:param client: ServerProxy
|
||||
"""
|
||||
rows = []
|
||||
ColumnData = namedtuple('ColumnData', 'text link')
|
||||
headers = ['Name', 'Author', 'Downloads', 'Python 2.7', 'Python 3.3', 'Summary']
|
||||
headers = ['Name', 'Py27', 'Py33', 'Repository', 'Summary']
|
||||
pytest_version = pytest.__version__
|
||||
repositories = obtain_override_repositories()
|
||||
print('*** pytest-{0} ***'.format(pytest_version))
|
||||
plugins = list(plugins)
|
||||
for index, (package_name, version) in enumerate(plugins):
|
||||
print package_name, version, '...',
|
||||
|
||||
print(package_name, version, '...', end='')
|
||||
|
||||
release_data = client.release_data(package_name, version)
|
||||
download_count = release_data['downloads']['last_month']
|
||||
image_url = '.. image:: http://pytest-plugs.herokuapp.com/status/{name}-{version}'.format(name=package_name,
|
||||
version=version)
|
||||
|
||||
common_params = dict(
|
||||
site='http://pytest-plugs.herokuapp.com',
|
||||
name=package_name,
|
||||
version=version)
|
||||
|
||||
# first row: name, images and simple links
|
||||
url = '.. image:: {site}/status/{name}-{version}'
|
||||
image_url = url.format(**common_params)
|
||||
image_url += '?py={py}&pytest={pytest}'
|
||||
row = (
|
||||
ColumnData(package_name + '-' + version, release_data['release_url']),
|
||||
ColumnData(release_data['author'], release_data['author_email']),
|
||||
ColumnData(str(download_count), None),
|
||||
ColumnData(image_url.format(py='py27', pytest=pytest_version), None),
|
||||
ColumnData(image_url.format(py='py33', pytest=pytest_version), None),
|
||||
ColumnData(package_name + '-' + version,
|
||||
release_data['release_url']),
|
||||
ColumnData(image_url.format(py='py27', pytest=pytest_version),
|
||||
None),
|
||||
ColumnData(image_url.format(py='py33', pytest=pytest_version),
|
||||
None),
|
||||
ColumnData(
|
||||
repositories.get(package_name, release_data['home_page']),
|
||||
None),
|
||||
ColumnData(release_data['summary'], None),
|
||||
)
|
||||
assert len(row) == len(headers)
|
||||
rows.append(row)
|
||||
|
||||
print 'OK (%d%%)' % ((index + 1) * 100 / len(plugins))
|
||||
|
||||
return headers, rows
|
||||
|
||||
# second row: links for images (they should be in their own line)
|
||||
url = ' :target: {site}/output/{name}-{version}'
|
||||
output_url = url.format(**common_params)
|
||||
output_url += '?py={py}&pytest={pytest}'
|
||||
|
||||
row = (
|
||||
ColumnData('', None),
|
||||
ColumnData(output_url.format(py='py27', pytest=pytest_version),
|
||||
None),
|
||||
ColumnData(output_url.format(py='py33', pytest=pytest_version),
|
||||
None),
|
||||
ColumnData('', None),
|
||||
ColumnData('', None),
|
||||
)
|
||||
assert len(row) == len(headers)
|
||||
rows.append(row)
|
||||
|
||||
print('OK (%d%%)' % ((index + 1) * 100 / len(plugins)))
|
||||
|
||||
return headers, rows
|
||||
|
||||
|
||||
def obtain_override_repositories():
|
||||
"""
|
||||
Used to override the "home_page" obtained from pypi to known
|
||||
package repositories. Used when the author didn't fill the "home_page"
|
||||
field in setup.py.
|
||||
|
||||
:return: dict of {package_name: repository_url}
|
||||
"""
|
||||
return {
|
||||
'pytest-blockage': 'https://github.com/rob-b/pytest-blockage',
|
||||
'pytest-konira': 'http://github.com/alfredodeza/pytest-konira',
|
||||
}
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# generate_plugins_index_from_table
|
||||
#===================================================================================================
|
||||
def generate_plugins_index_from_table(filename, headers, rows):
|
||||
'''
|
||||
"""
|
||||
Generates a RST file with the table data given.
|
||||
|
||||
|
||||
:param filename: output filename
|
||||
:param headers: see `obtain_plugins_table`
|
||||
:param rows: see `obtain_plugins_table`
|
||||
'''
|
||||
# creates a list of rows, each being a str containing appropriate column text and link
|
||||
"""
|
||||
# creates a list of rows, each being a str containing appropriate column
|
||||
# text and link
|
||||
table_texts = []
|
||||
for row in rows:
|
||||
column_texts = []
|
||||
for i, col_data in enumerate(row):
|
||||
text = '`%s <%s>`_' % (col_data.text, col_data.link) if col_data.link else col_data.text
|
||||
for i, col_data in enumerate(row):
|
||||
text = '`%s <%s>`_' % (
|
||||
col_data.text,
|
||||
col_data.link) if col_data.link else col_data.text
|
||||
column_texts.append(text)
|
||||
table_texts.append(column_texts)
|
||||
|
||||
|
||||
# compute max length of each column so we can build the rst table
|
||||
column_lengths = [len(x) for x in headers]
|
||||
for column_texts in table_texts:
|
||||
for i, row_text in enumerate(column_texts):
|
||||
column_lengths[i] = max(column_lengths[i], len(row_text) + 2)
|
||||
|
||||
|
||||
def get_row_limiter(char):
|
||||
return ' '.join(char * length for length in column_lengths)
|
||||
|
||||
with file(filename, 'w') as f:
|
||||
# write welcome
|
||||
print >> f, '.. _plugins_index:'
|
||||
print >> f
|
||||
print >> f, 'List of Third-Party Plugins'
|
||||
print >> f, '==========================='
|
||||
print >> f
|
||||
|
||||
# table
|
||||
print >> f, get_row_limiter('=')
|
||||
for i, header in enumerate(headers):
|
||||
print >> f, '{:^{fill}}'.format(header, fill=column_lengths[i]),
|
||||
print >> f
|
||||
print >> f, get_row_limiter('=')
|
||||
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
# write welcome
|
||||
print('.. _plugins_index:', file=f)
|
||||
print(file=f)
|
||||
print('List of Third-Party Plugins', file=f)
|
||||
print('===========================', file=f)
|
||||
print(file=f)
|
||||
|
||||
# table
|
||||
print(get_row_limiter('='), file=f)
|
||||
formatted_headers = [
|
||||
'{0:^{fill}}'.format(header, fill=column_lengths[i])
|
||||
for i, header in enumerate(headers)]
|
||||
print(*formatted_headers, file=f)
|
||||
print(get_row_limiter('='), file=f)
|
||||
|
||||
for column_texts in table_texts:
|
||||
for i, row_text in enumerate(column_texts):
|
||||
print >> f, '{:^{fill}}'.format(row_text, fill=column_lengths[i]),
|
||||
print >> f
|
||||
print >> f
|
||||
print >> f, get_row_limiter('=')
|
||||
print >> f
|
||||
print >> f, '*(Downloads are given from last month only)*'
|
||||
print >> f
|
||||
print >> f, '*(Updated on %s)*' % _get_today_as_str()
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# _get_today_as_str
|
||||
#===================================================================================================
|
||||
def _get_today_as_str():
|
||||
'''
|
||||
internal. only exists so we can patch it in testing.
|
||||
'''
|
||||
return datetime.date.today().strftime('%Y-%m-%d')
|
||||
formatted_rows = [
|
||||
'{0:^{fill}}'.format(row_text, fill=column_lengths[i])
|
||||
for i, row_text in enumerate(column_texts)
|
||||
]
|
||||
print(*formatted_rows, file=f)
|
||||
print(file=f)
|
||||
print(get_row_limiter('='), file=f)
|
||||
print(file=f)
|
||||
today = datetime.date.today().strftime('%Y-%m-%d')
|
||||
print('*(Updated on %s)*' % today, file=f)
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# generate_plugins_index
|
||||
#===================================================================================================
|
||||
def generate_plugins_index(client, filename):
|
||||
'''
|
||||
Generates an RST file with a table of the latest pytest plugins found in PyPI.
|
||||
|
||||
:param client: xmlrpclib.ServerProxy
|
||||
"""
|
||||
Generates an RST file with a table of the latest pytest plugins found in
|
||||
PyPI.
|
||||
|
||||
:param client: ServerProxy
|
||||
:param filename: output filename
|
||||
'''
|
||||
"""
|
||||
plugins = get_latest_versions(iter_plugins(client))
|
||||
headers, rows = obtain_plugins_table(plugins, client)
|
||||
generate_plugins_index_from_table(filename, headers, rows)
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# main
|
||||
#===================================================================================================
|
||||
|
||||
def main(argv):
|
||||
filename = os.path.join(os.path.dirname(__file__), 'plugins_index.txt')
|
||||
"""
|
||||
Script entry point. Configures an option parser and calls the appropriate
|
||||
internal function.
|
||||
"""
|
||||
filename = os.path.join(os.path.dirname(__file__), 'index.txt')
|
||||
url = 'http://pypi.python.org/pypi'
|
||||
|
||||
parser = OptionParser(description='Generates a restructured document of pytest plugins from PyPI')
|
||||
parser.add_option('-f', '--filename', default=filename, help='output filename [default: %default]')
|
||||
parser.add_option('-u', '--url', default=url, help='url of PyPI server to obtain data from [default: %default]')
|
||||
|
||||
parser = OptionParser(
|
||||
description='Generates a restructured document of pytest plugins from PyPI')
|
||||
parser.add_option('-f', '--filename', default=filename,
|
||||
help='output filename [default: %default]')
|
||||
parser.add_option('-u', '--url', default=url,
|
||||
help='url of PyPI server to obtain data from [default: %default]')
|
||||
(options, _) = parser.parse_args(argv[1:])
|
||||
|
||||
client = xmlrpclib.ServerProxy(options.url)
|
||||
client = get_proxy(options.url)
|
||||
generate_plugins_index(client, options.filename)
|
||||
|
||||
print
|
||||
print '%s Updated.' % options.filename
|
||||
|
||||
print()
|
||||
print('%s Updated.' % options.filename)
|
||||
return 0
|
||||
|
||||
#===================================================================================================
|
||||
# main
|
||||
#===================================================================================================
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
.. _plugins_index:
|
||||
|
||||
List of Third-Party Plugins
|
||||
===========================
|
||||
|
||||
========================================================================================== ==================================================================================== ========= ====================================================================================================== ====================================================================================================== =============================================================================================================================================
|
||||
Name Author Downloads Python 2.7 Python 3.3 Summary
|
||||
========================================================================================== ==================================================================================== ========= ====================================================================================================== ====================================================================================================== =============================================================================================================================================
|
||||
`pytest-bdd-0.6.7 <http://pypi.python.org/pypi/pytest-bdd/0.6.7>`_ `Oleg Pidsadnyi <oleg.podsadny@gmail.com>`_ 1467 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-0.6.7?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-0.6.7?py=py33&pytest=2.4.2 BDD for pytest
|
||||
`pytest-bdd-splinter-0.5.96 <http://pypi.python.org/pypi/pytest-bdd-splinter/0.5.96>`_ `Oleg Pidsadnyi <oleg.podsadny@gmail.com>`_ 3352 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-splinter-0.5.96?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-splinter-0.5.96?py=py33&pytest=2.4.2 Splinter subplugin for Pytest BDD plugin
|
||||
`pytest-bench-0.2.5 <http://pypi.python.org/pypi/pytest-bench/0.2.5>`_ `Concordus Applications <support@concordusapps.com>`_ 1560 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-0.2.5?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-0.2.5?py=py33&pytest=2.4.2 Benchmark utility that plugs into pytest.
|
||||
`pytest-blockage-0.1 <http://pypi.python.org/pypi/pytest-blockage/0.1>`_ `UNKNOWN <UNKNOWN>`_ 102 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-0.1?py=py33&pytest=2.4.2 Disable network requests during a test run.
|
||||
`pytest-browsermob-proxy-0.1 <http://pypi.python.org/pypi/pytest-browsermob-proxy/0.1>`_ `Dave Hunt <dhunt@mozilla.com>`_ 55 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-0.1?py=py33&pytest=2.4.2 BrowserMob proxy plugin for py.test.
|
||||
`pytest-bugzilla-0.2 <http://pypi.python.org/pypi/pytest-bugzilla/0.2>`_ `Noufal Ibrahim <noufal@nibrahim.net.in>`_ 89 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-0.2?py=py33&pytest=2.4.2 py.test bugzilla integration plugin
|
||||
`pytest-cache-1.0 <http://pypi.python.org/pypi/pytest-cache/1.0>`_ `Holger Krekel <holger.krekel@gmail.com>`_ 5561 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-1.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-1.0?py=py33&pytest=2.4.2 pytest plugin with mechanisms for caching across test runs
|
||||
`pytest-capturelog-0.7 <http://pypi.python.org/pypi/pytest-capturelog/0.7>`_ `Meme Dough <memedough@gmail.com>`_ 1553 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-0.7?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-0.7?py=py33&pytest=2.4.2 py.test plugin to capture log messages
|
||||
`pytest-codecheckers-0.2 <http://pypi.python.org/pypi/pytest-codecheckers/0.2>`_ `Ronny Pfannschmidt <Ronny.Pfannschmidt@gmx.de>`_ 384 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-0.2?py=py33&pytest=2.4.2 pytest plugin to add source code sanity checks (pep8 and friends)
|
||||
`pytest-contextfixture-0.1.1 <http://pypi.python.org/pypi/pytest-contextfixture/0.1.1>`_ `Andreas Pelme <andreas@pelme.se>`_ 92 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-0.1.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-0.1.1?py=py33&pytest=2.4.2 Define pytest fixtures as context managers.
|
||||
`pytest-couchdbkit-0.5.1 <http://pypi.python.org/pypi/pytest-couchdbkit/0.5.1>`_ `RonnyPfannschmidt <ronny.pfannschmidt@gmx.de>`_ 200 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-0.5.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-0.5.1?py=py33&pytest=2.4.2 py.test extension for per-test couchdb databases using couchdbkit
|
||||
`pytest-cov-1.6 <http://pypi.python.org/pypi/pytest-cov/1.6>`_ `Meme Dough <memedough@gmail.com>`_ 23291 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-1.6?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-1.6?py=py33&pytest=2.4.2 py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing
|
||||
`pytest-dbfixtures-0.4.0 <http://pypi.python.org/pypi/pytest-dbfixtures/0.4.0>`_ `Clearcode - The A Room <thearoom@clearcode.cc>`_ 6223 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-0.4.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-0.4.0?py=py33&pytest=2.4.2 dbfixtures plugin for py.test.
|
||||
`pytest-django-2.4 <http://pypi.python.org/pypi/pytest-django/2.4>`_ `Andreas Pelme <andreas@pelme.se>`_ 4809 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-2.4?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-2.4?py=py33&pytest=2.4.2 A Django plugin for py.test.
|
||||
`pytest-django-lite-0.1.0 <http://pypi.python.org/pypi/pytest-django-lite/0.1.0>`_ `David Cramer <dcramer@gmail.com>`_ 987 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-0.1.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-0.1.0?py=py33&pytest=2.4.2 The bare minimum to integrate py.test with Django.
|
||||
`pytest-figleaf-1.0 <http://pypi.python.org/pypi/pytest-figleaf/1.0>`_ `holger krekel <py-dev@codespeak.net,holger@merlinux.eu>`_ 53 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-1.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-1.0?py=py33&pytest=2.4.2 py.test figleaf coverage plugin
|
||||
`pytest-flakes-0.2 <http://pypi.python.org/pypi/pytest-flakes/0.2>`_ `Florian Schulze, Holger Krekel and Ronny Pfannschmidt <florian.schulze@gmx.net>`_ 1146 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-0.2?py=py33&pytest=2.4.2 pytest plugin to check source code with pyflakes
|
||||
`pytest-greendots-0.2 <http://pypi.python.org/pypi/pytest-greendots/0.2>`_ `UNKNOWN <UNKNOWN>`_ 139 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-0.2?py=py33&pytest=2.4.2 Green progress dots
|
||||
`pytest-growl-0.1 <http://pypi.python.org/pypi/pytest-growl/0.1>`_ `Anthony Long <antlong@gmail.com>`_ 58 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-0.1?py=py33&pytest=2.4.2 Growl notifications for pytest results.
|
||||
`pytest-incremental-0.3.0 <http://pypi.python.org/pypi/pytest-incremental/0.3.0>`_ `Eduardo Naufel Schettino <schettino72@gmail.com>`_ 180 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-0.3.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-0.3.0?py=py33&pytest=2.4.2 an incremental test runner (pytest plugin)
|
||||
`pytest-instafail-0.1.1 <http://pypi.python.org/pypi/pytest-instafail/0.1.1>`_ `Janne Vanhala <janne.vanhala@gmail.com>`_ 418 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-0.1.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-0.1.1?py=py33&pytest=2.4.2 py.test plugin to show failures instantly
|
||||
`pytest-ipdb-0.1-prerelease <http://pypi.python.org/pypi/pytest-ipdb/0.1-prerelease>`_ `Matthew de Verteuil <onceuponajooks@gmail.com>`_ 93 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-0.1-prerelease?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-0.1-prerelease?py=py33&pytest=2.4.2 A py.test plug-in to enable drop to ipdb debugger on test failure.
|
||||
`pytest-jira-0.01 <http://pypi.python.org/pypi/pytest-jira/0.01>`_ `James Laska <james.laska@gmail.com>`_ 86 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-0.01?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-0.01?py=py33&pytest=2.4.2 py.test JIRA integration plugin, using markers
|
||||
`pytest-konira-0.2 <http://pypi.python.org/pypi/pytest-konira/0.2>`_ `Alfredo Deza <alfredodeza [at] gmail.com>`_ 91 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-0.2?py=py33&pytest=2.4.2 Run Konira DSL tests with py.test
|
||||
`pytest-localserver-0.3.2 <http://pypi.python.org/pypi/pytest-localserver/0.3.2>`_ `Sebastian Rahlf <basti AT redtoad DOT de>`_ 448 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-0.3.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-0.3.2?py=py33&pytest=2.4.2 py.test plugin to test server connections locally.
|
||||
`pytest-marker-bugzilla-0.06 <http://pypi.python.org/pypi/pytest-marker-bugzilla/0.06>`_ `Eric Sammons <elsammons@gmail.com>`_ 191 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-0.06?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-0.06?py=py33&pytest=2.4.2 py.test bugzilla integration plugin, using markers
|
||||
`pytest-markfiltration-0.8 <http://pypi.python.org/pypi/pytest-markfiltration/0.8>`_ `adam goucher <adam@element34.ca>`_ 253 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-0.8?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-0.8?py=py33&pytest=2.4.2 UNKNOWN
|
||||
`pytest-marks-0.4 <http://pypi.python.org/pypi/pytest-marks/0.4>`_ `adam goucher <adam@element34.ca>`_ 225 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-0.4?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-0.4?py=py33&pytest=2.4.2 UNKNOWN
|
||||
`pytest-monkeyplus-1.1.0 <http://pypi.python.org/pypi/pytest-monkeyplus/1.1.0>`_ `Virgil Dupras <hsoft@hardcoded.net>`_ 123 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-1.1.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-1.1.0?py=py33&pytest=2.4.2 pytest's monkeypatch subclass with extra functionalities
|
||||
`pytest-mozwebqa-1.1.1 <http://pypi.python.org/pypi/pytest-mozwebqa/1.1.1>`_ `Dave Hunt <dhunt@mozilla.com>`_ 1037 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-1.1.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-1.1.1?py=py33&pytest=2.4.2 Mozilla WebQA plugin for py.test.
|
||||
`pytest-oerp-0.2.0 <http://pypi.python.org/pypi/pytest-oerp/0.2.0>`_ `Leonardo Santagada <santagada@gmail.com>`_ 144 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-0.2.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-0.2.0?py=py33&pytest=2.4.2 pytest plugin to test OpenERP modules
|
||||
`pytest-osxnotify-0.1.4 <http://pypi.python.org/pypi/pytest-osxnotify/0.1.4>`_ `Daniel Bader <mail@dbader.org>`_ 184 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-0.1.4?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-0.1.4?py=py33&pytest=2.4.2 OS X notifications for py.test results.
|
||||
`pytest-paste-config-0.1 <http://pypi.python.org/pypi/pytest-paste-config/0.1>`_ `UNKNOWN <UNKNOWN>`_ 164 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-0.1?py=py33&pytest=2.4.2 Allow setting the path to a paste config file
|
||||
`pytest-pep8-1.0.5 <http://pypi.python.org/pypi/pytest-pep8/1.0.5>`_ `Holger Krekel and Ronny Pfannschmidt <holger.krekel@gmail.com>`_ 5809 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-1.0.5?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-1.0.5?py=py33&pytest=2.4.2 pytest plugin to check PEP8 requirements
|
||||
`pytest-poo-0.2 <http://pypi.python.org/pypi/pytest-poo/0.2>`_ `Andreas Pelme <andreas@pelme.se>`_ 108 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-0.2?py=py33&pytest=2.4.2 Visualize your crappy tests
|
||||
`pytest-pydev-0.1 <http://pypi.python.org/pypi/pytest-pydev/0.1>`_ `Sebastian Rahlf <basti AT redtoad DOT de>`_ 100 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-0.1?py=py33&pytest=2.4.2 py.test plugin to connect to a remote debug server with PyDev or PyCharm.
|
||||
`pytest-qt-1.0.2 <http://pypi.python.org/pypi/pytest-qt/1.0.2>`_ `Bruno Oliveira <nicoddemus@gmail.com>`_ 129 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-1.0.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-1.0.2?py=py33&pytest=2.4.2 pytest plugin that adds fixtures for testing Qt (PyQt and PySide) applications.
|
||||
`pytest-quickcheck-0.8 <http://pypi.python.org/pypi/pytest-quickcheck/0.8>`_ `Tetsuya Morimoto <tetsuya dot morimoto at gmail dot com>`_ 345 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-0.8?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-0.8?py=py33&pytest=2.4.2 pytest plugin to generate random data inspired by QuickCheck
|
||||
`pytest-rage-0.1 <http://pypi.python.org/pypi/pytest-rage/0.1>`_ `Leonardo Santagada <santagada@gmail.com>`_ 56 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-0.1?py=py33&pytest=2.4.2 pytest plugin to implement PEP712
|
||||
`pytest-random-0.02 <http://pypi.python.org/pypi/pytest-random/0.02>`_ `Leah Klearman <lklrmn@gmail.com>`_ 116 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-0.02?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-0.02?py=py33&pytest=2.4.2 py.test plugin to randomize tests
|
||||
`pytest-rerunfailures-0.03 <http://pypi.python.org/pypi/pytest-rerunfailures/0.03>`_ `Leah Klearman <lklrmn@gmail.com>`_ 147 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-0.03?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-0.03?py=py33&pytest=2.4.2 py.test plugin to re-run tests to eliminate flakey failures
|
||||
`pytest-runfailed-0.3 <http://pypi.python.org/pypi/pytest-runfailed/0.3>`_ `Dimitri Merejkowsky <d.merej@gmail.com>`_ 88 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-0.3?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-0.3?py=py33&pytest=2.4.2 implement a --failed option for pytest
|
||||
`pytest-runner-2.0 <http://pypi.python.org/pypi/pytest-runner/2.0>`_ `Jason R. Coombs <jaraco@jaraco.com>`_ 5657 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-2.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-2.0?py=py33&pytest=2.4.2 UNKNOWN
|
||||
`pytest-sugar-0.2.2 <http://pypi.python.org/pypi/pytest-sugar/0.2.2>`_ `Teemu, Janne Vanhala <orkkiolento@gmail.com, janne.vanhala@gmail.com>`_ 348 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-0.2.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-0.2.2?py=py33&pytest=2.4.2 py.test plugin that adds instafail, ETA and neat graphics
|
||||
`pytest-timeout-0.3 <http://pypi.python.org/pypi/pytest-timeout/0.3>`_ `Floris Bruynooghe <flub@devork.be>`_ 4351 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-0.3?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-0.3?py=py33&pytest=2.4.2 pytest plugin to abort tests after a timeout
|
||||
`pytest-twisted-1.4 <http://pypi.python.org/pypi/pytest-twisted/1.4>`_ `Ralf Schmitt <ralf@brainbot.com>`_ 239 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-1.4?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-1.4?py=py33&pytest=2.4.2 A twisted plugin for py.test.
|
||||
`pytest-xdist-1.9 <http://pypi.python.org/pypi/pytest-xdist/1.9>`_ `holger krekel and contributors <pytest-dev@python.org,holger@merlinux.eu>`_ 7894 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-1.9?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-1.9?py=py33&pytest=2.4.2 py.test xdist plugin for distributed testing and loop-on-failing modes
|
||||
`pytest-xprocess-0.8 <http://pypi.python.org/pypi/pytest-xprocess/0.8>`_ `Holger Krekel <holger@merlinux.eu>`_ 96 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-0.8?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-0.8?py=py33&pytest=2.4.2 pytest plugin to manage external processes across test runs
|
||||
`pytest-yamlwsgi-0.6 <http://pypi.python.org/pypi/pytest-yamlwsgi/0.6>`_ `Ali Afshar <aafshar@gmail.com>`_ 194 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-0.6?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-0.6?py=py33&pytest=2.4.2 Run tests against wsgi apps defined in yaml
|
||||
`pytest-zap-0.1 <http://pypi.python.org/pypi/pytest-zap/0.1>`_ `Dave Hunt <dhunt@mozilla.com>`_ 63 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-0.1?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-0.1?py=py33&pytest=2.4.2 OWASP ZAP plugin for py.test.
|
||||
|
||||
========================================================================================== ==================================================================================== ========= ====================================================================================================== ====================================================================================================== =============================================================================================================================================
|
||||
|
||||
*(Downloads are given from last month only)*
|
||||
|
||||
*(Updated on 2013-12-11)*
|
||||
@@ -1,101 +0,0 @@
|
||||
import os
|
||||
import xmlrpclib
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# test_plugins_index
|
||||
#===================================================================================================
|
||||
def test_plugins_index(tmpdir, monkeypatch):
|
||||
'''
|
||||
Blackbox testing for plugins_index script. Calls main() generating a file and compares produced
|
||||
output to expected.
|
||||
|
||||
.. note:: if the test fails, a file named `test_plugins_index.obtained` will be generated in
|
||||
the same directory as this test file. Ensure the contents are correct and overwrite
|
||||
the global `expected_output` with the new contents.
|
||||
'''
|
||||
import plugins_index
|
||||
|
||||
# dummy interface to xmlrpclib.ServerProxy
|
||||
class DummyProxy(object):
|
||||
|
||||
expected_url = 'http://dummy.pypi'
|
||||
def __init__(self, url):
|
||||
assert url == self.expected_url
|
||||
|
||||
def search(self, query):
|
||||
assert query == {'name' : 'pytest-'}
|
||||
return [
|
||||
{'name': 'pytest-plugin1', 'version' : '0.8'},
|
||||
{'name': 'pytest-plugin1', 'version' : '1.0'},
|
||||
{'name': 'pytest-plugin2', 'version' : '1.2'},
|
||||
]
|
||||
|
||||
def release_data(self, package_name, version):
|
||||
results = {
|
||||
('pytest-plugin1', '1.0') : {
|
||||
'package_url' : 'http://plugin1',
|
||||
'release_url' : 'http://plugin1/1.0',
|
||||
'author' : 'someone',
|
||||
'author_email' : 'someone@py.com',
|
||||
'summary' : 'some plugin',
|
||||
'downloads': {'last_day': 1, 'last_month': 4, 'last_week': 2},
|
||||
},
|
||||
|
||||
('pytest-plugin2', '1.2') : {
|
||||
'package_url' : 'http://plugin2',
|
||||
'release_url' : 'http://plugin2/1.2',
|
||||
'author' : 'other',
|
||||
'author_email' : 'other@py.com',
|
||||
'summary' : 'some other plugin',
|
||||
'downloads': {'last_day': 10, 'last_month': 40, 'last_week': 20},
|
||||
},
|
||||
}
|
||||
|
||||
return results[(package_name, version)]
|
||||
|
||||
|
||||
monkeypatch.setattr(xmlrpclib, 'ServerProxy', DummyProxy, 'foo')
|
||||
monkeypatch.setattr(plugins_index, '_get_today_as_str', lambda: '2013-10-20')
|
||||
|
||||
output_file = str(tmpdir.join('output.txt'))
|
||||
assert plugins_index.main(['', '-f', output_file, '-u', DummyProxy.expected_url]) == 0
|
||||
|
||||
with file(output_file, 'rU') as f:
|
||||
obtained_output = f.read()
|
||||
|
||||
if obtained_output != expected_output:
|
||||
obtained_file = os.path.splitext(__file__)[0] + '.obtained'
|
||||
with file(obtained_file, 'w') as f:
|
||||
f.write(obtained_output)
|
||||
|
||||
assert obtained_output == expected_output
|
||||
|
||||
|
||||
expected_output = '''\
|
||||
.. _plugins_index:
|
||||
|
||||
List of Third-Party Plugins
|
||||
===========================
|
||||
|
||||
============================================ ============================= ========= ============================================================================================= ============================================================================================= ===================
|
||||
Name Author Downloads Python 2.7 Python 3.3 Summary
|
||||
============================================ ============================= ========= ============================================================================================= ============================================================================================= ===================
|
||||
`pytest-plugin1-1.0 <http://plugin1/1.0>`_ `someone <someone@py.com>`_ 4 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-plugin1-1.0?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-plugin1-1.0?py=py33&pytest=2.4.2 some plugin
|
||||
`pytest-plugin2-1.2 <http://plugin2/1.2>`_ `other <other@py.com>`_ 40 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-plugin2-1.2?py=py27&pytest=2.4.2 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-plugin2-1.2?py=py33&pytest=2.4.2 some other plugin
|
||||
|
||||
============================================ ============================= ========= ============================================================================================= ============================================================================================= ===================
|
||||
|
||||
*(Downloads are given from last month only)*
|
||||
|
||||
*(Updated on 2013-10-20)*
|
||||
'''
|
||||
|
||||
|
||||
#===================================================================================================
|
||||
# main
|
||||
#===================================================================================================
|
||||
if __name__ == '__main__':
|
||||
pytest.main()
|
||||
@@ -20,10 +20,10 @@
|
||||
Project examples
|
||||
==========================
|
||||
|
||||
Here are some examples of projects using py.test (please send notes via :ref:`contact`):
|
||||
Here are some examples of projects using ``pytest`` (please send notes via :ref:`contact`):
|
||||
|
||||
* `PyPy <http://pypy.org>`_, Python with a JIT compiler, running over
|
||||
`16000 tests <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_
|
||||
* `PyPy <http://pypy.org>`_, Python with a JIT compiler, running over
|
||||
`21000 tests <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_
|
||||
* the `MoinMoin <http://moinmo.in>`_ Wiki Engine
|
||||
* `sentry <https://getsentry.com/welcome/>`_, realtime app-maintenance and exception tracking
|
||||
* `tox <http://testrun.org/tox>`_, virtualenv/Hudson integration tool
|
||||
@@ -60,7 +60,7 @@ Here are some examples of projects using py.test (please send notes via :ref:`co
|
||||
* `pytest-localserver <https://bitbucket.org/basti/pytest-localserver/>`_ a plugin for pytest that provides a httpserver and smtpserver
|
||||
* `pytest-monkeyplus <http://pypi.python.org/pypi/pytest-monkeyplus/>`_ a plugin that extends monkeypatch
|
||||
|
||||
These projects help integrate py.test into other Python frameworks:
|
||||
These projects help integrate ``pytest`` into other Python frameworks:
|
||||
|
||||
* `pytest-django <http://pypi.python.org/pypi/pytest-django/>`_ for Django
|
||||
* `zope.pytest <http://packages.python.org/zope.pytest/>`_ for Zope and Grok
|
||||
@@ -68,7 +68,7 @@ These projects help integrate py.test into other Python frameworks:
|
||||
* There is `some work <https://github.com/Kotti/Kotti/blob/master/kotti/testing.py>`_ underway for Kotti, a CMS built in Pyramid/Pylons
|
||||
|
||||
|
||||
Some organisations using py.test
|
||||
Some organisations using pytest
|
||||
-----------------------------------
|
||||
|
||||
* `Square Kilometre Array, Cape Town <http://ska.ac.za/>`_
|
||||
|
||||
@@ -14,7 +14,7 @@ A *skip* means that you expect your test to pass unless the environment
|
||||
And *xfail* means that your test can run but you expect it to fail
|
||||
because there is an implementation problem.
|
||||
|
||||
py.test counts and lists *skip* and *xfail* tests separately. Detailed
|
||||
``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
|
||||
information about skipped/xfailed tests is not shown by default to avoid
|
||||
cluttering the output. You can use the ``-r`` option to see details
|
||||
corresponding to the "short" letters shown in the test progress::
|
||||
@@ -29,7 +29,7 @@ corresponding to the "short" letters shown in the test progress::
|
||||
Marking a test function to be skipped
|
||||
-------------------------------------------
|
||||
|
||||
.. versionadded:: 2.0, 2.4
|
||||
.. versionadded:: 2.0, 2.4
|
||||
|
||||
Here is an example of marking a test function to be skipped
|
||||
when run on a Python3.3 interpreter::
|
||||
@@ -104,7 +104,7 @@ you can set the ``pytestmark`` attribute of a class::
|
||||
"will not be setup or run under 'win32' platform"
|
||||
|
||||
As with the class-decorator, the ``pytestmark`` special name tells
|
||||
py.test to apply it to each test function in the class.
|
||||
``pytest`` to apply it to each test function in the class.
|
||||
|
||||
If you want to skip all test functions of a module, you must use
|
||||
the ``pytestmark`` name on the global level::
|
||||
@@ -159,7 +159,7 @@ Running it with the report-on-xfail option gives this output::
|
||||
|
||||
example $ py.test -rx xfail_demo.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 6 items
|
||||
|
||||
xfail_demo.py xxxxxx
|
||||
@@ -176,7 +176,7 @@ Running it with the report-on-xfail option gives this output::
|
||||
XFAIL xfail_demo.py::test_hello6
|
||||
reason: reason
|
||||
|
||||
======================== 6 xfailed in 0.06 seconds =========================
|
||||
======================== 6 xfailed in 0.04 seconds =========================
|
||||
|
||||
.. _`skip/xfail with parametrize`:
|
||||
|
||||
@@ -212,7 +212,7 @@ imperatively, in test or setup code::
|
||||
if not valid_config():
|
||||
pytest.xfail("failing configuration (but should work)")
|
||||
# or
|
||||
pytest.skipif("unsupported configuration")
|
||||
pytest.skip("unsupported configuration")
|
||||
|
||||
|
||||
Skipping on a missing import dependency
|
||||
@@ -255,7 +255,7 @@ because markers can then be freely imported between test modules.
|
||||
With strings you need to import not only the marker but all variables
|
||||
everything used by the marker, which violates encapsulation.
|
||||
|
||||
The reason for specifying the condition as a string was that py.test can
|
||||
The reason for specifying the condition as a string was that ``pytest`` can
|
||||
report a summary of skip conditions based purely on the condition string.
|
||||
With conditions as booleans you are required to specify a ``reason`` string.
|
||||
|
||||
|
||||
5
doc/en/status.txt
Normal file
5
doc/en/status.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
pytest development status
|
||||
================================
|
||||
|
||||
https://drone.io/bitbucket.org/hpk42/pytest
|
||||
|
||||
@@ -18,9 +18,12 @@ Basic usage and fixtures:
|
||||
- `pytest introduction from Brian Okken (January 2013)
|
||||
<http://pythontesting.net/framework/pytest-introduction/>`_
|
||||
|
||||
- `3-part blog series about pytest from Daniel Greenfeld (January
|
||||
2014) <http://pydanny.com/pytest-no-boilerplate-testing.html>`_
|
||||
|
||||
- `pycon australia 2012 pytest talk from Brianna Laugher
|
||||
<http://2012.pycon-au.org/schedule/52/view_talk?day=sunday>`_ (`video <http://www.youtube.com/watch?v=DTNejE9EraI>`_, `slides <http://www.slideshare.net/pfctdayelise/funcargs-other-fun-with-pytest>`_, `code <https://gist.github.com/3386951>`_)
|
||||
- `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_
|
||||
- `pycon 2012 US talk video from Holger Krekel <http://www.youtube.com/watch?v=9LVqBQcFmyw>`_
|
||||
- `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_
|
||||
|
||||
|
||||
@@ -39,8 +42,8 @@ Test parametrization:
|
||||
|
||||
Assertion introspection:
|
||||
|
||||
- `(07/2011) Behind the scenes of py.test's new assertion rewriting
|
||||
<http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_
|
||||
- `(07/2011) Behind the scenes of pytest's new assertion rewriting
|
||||
<http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_
|
||||
|
||||
Distributed testing:
|
||||
|
||||
@@ -48,11 +51,11 @@ Distributed testing:
|
||||
|
||||
Plugin specific examples:
|
||||
|
||||
- `skipping slow tests by default in py.test`_ (blog entry)
|
||||
- `skipping slow tests by default in pytest`_ (blog entry)
|
||||
|
||||
- `many examples in the docs for plugins`_
|
||||
|
||||
.. _`skipping slow tests by default in py.test`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||
.. _`skipping slow tests by default in pytest`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||
.. _`many examples in the docs for plugins`: plugin/index.html
|
||||
.. _`monkeypatch plugin`: plugin/monkeypatch.html
|
||||
.. _`application setup in test functions with funcargs`: funcargs.html#appsetup
|
||||
@@ -69,14 +72,14 @@ Older conference talks and tutorials
|
||||
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
||||
|
||||
- testing terminology
|
||||
- basic py.test usage, file system layout
|
||||
- basic pytest usage, file system layout
|
||||
- test function arguments (funcargs_) and test fixtures
|
||||
- existing plugins
|
||||
- distributed testing
|
||||
|
||||
- `ep2009-pytest.pdf`_ 60 minute py.test talk, highlighting unique features and a roadmap (July 2009)
|
||||
- `ep2009-pytest.pdf`_ 60 minute pytest talk, highlighting unique features and a roadmap (July 2009)
|
||||
|
||||
- `pycon2009-pytest-introduction.zip`_ slides and files, extended version of py.test basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features.
|
||||
- `pycon2009-pytest-introduction.zip`_ slides and files, extended version of pytest basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features.
|
||||
|
||||
- `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ writing conftest.py files
|
||||
You may put conftest.py files containing project-specific
|
||||
configuration in your project's root directory, it's usually
|
||||
best to put it just into the same directory level as your
|
||||
topmost ``__init__.py``. In fact, ``py.test`` performs
|
||||
topmost ``__init__.py``. In fact, ``pytest`` performs
|
||||
an "upwards" search starting from the directory that you specify
|
||||
to be tested and will lookup configuration values right-to-left.
|
||||
You may have options that reside e.g. in your home directory
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
=======================================
|
||||
py.test documentation index
|
||||
pytest documentation index
|
||||
=======================================
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ customize_: configuration, customization, extensions
|
||||
|
||||
changelog_: history of changes covering last releases
|
||||
|
||||
**Continuous Integration of py.test's own tests and plugins with Hudson**:
|
||||
**Continuous Integration of pytest's own tests and plugins with Hudson**:
|
||||
|
||||
`http://hudson.testrun.org/view/pytest`_
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
Mission
|
||||
====================================
|
||||
|
||||
py.test strives to make testing a fun and no-boilerplate effort.
|
||||
``pytest`` strives to make testing a fun and no-boilerplate effort.
|
||||
|
||||
The tool is distributed as part of the `py` package which contains supporting APIs that
|
||||
are also usable independently. The project independent ``py.test`` command line tool helps you to:
|
||||
The tool is distributed as a `pytest` package. Its project independent
|
||||
``py.test`` command line tool helps you to:
|
||||
|
||||
* rapidly collect and run tests
|
||||
* run unit- or doctests, functional or integration tests
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pytest_django plugin (EXTERNAL)
|
||||
==========================================
|
||||
|
||||
pytest_django is a plugin for py.test that provides a set of useful tools for testing Django applications, checkout Ben Firshman's `pytest_django github page`_.
|
||||
pytest_django is a plugin for ``pytest`` that provides a set of useful tools for testing Django applications, checkout Ben Firshman's `pytest_django github page`_.
|
||||
|
||||
.. _`pytest_django github page`: http://github.com/bfirsh/pytest_django/tree/master
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ command line options
|
||||
|
||||
|
||||
``--genscript=path``
|
||||
create standalone py.test script at given target path.
|
||||
create standalone ``pytest`` script at given target path.
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
=========================================
|
||||
@@ -21,7 +21,7 @@ Start improving this plugin in 30 seconds
|
||||
|
||||
1. Download `pytest_genscript.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_genscript.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
3. a subsequent ``pytest`` run will use your local version
|
||||
|
||||
Checkout customize_, other plugins_ or `get in contact`_.
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ command line options
|
||||
``--traceconfig``
|
||||
trace considerations of conftest.py files.
|
||||
``--nomagic``
|
||||
don't reinterpret asserts, no traceback cutting.
|
||||
don't reinterpret asserts, no traceback cutting.
|
||||
``--debug``
|
||||
generate and show internal debugging information.
|
||||
``--help-config``
|
||||
@@ -31,7 +31,7 @@ Start improving this plugin in 30 seconds
|
||||
|
||||
1. Download `pytest_helpconfig.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_helpconfig.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
3. a subsequent ``pytest`` run will use your local version
|
||||
|
||||
Checkout customize_, other plugins_ or `get in contact`_.
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
.. _`capturelog`: capturelog.html
|
||||
.. _`junitxml`: junitxml.html
|
||||
.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_skipping.py
|
||||
.. _`checkout the py.test development version`: ../../install.html#checkout
|
||||
.. _`checkout the pytest development version`: ../../install.html#checkout
|
||||
.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_helpconfig.py
|
||||
.. _`oejskit`: oejskit.html
|
||||
.. _`doctest`: doctest.html
|
||||
|
||||
@@ -7,7 +7,7 @@ nose-compatibility plugin: allow to run nose test suites natively.
|
||||
:local:
|
||||
|
||||
This is an experimental plugin for allowing to run tests written
|
||||
in 'nosetests style with py.test.
|
||||
in 'nosetests' style with ``pytest``.
|
||||
|
||||
Usage
|
||||
-------------
|
||||
@@ -17,7 +17,7 @@ type::
|
||||
py.test # instead of 'nosetests'
|
||||
|
||||
and you should be able to run nose style tests and at the same
|
||||
time can make full use of py.test's capabilities.
|
||||
time can make full use of pytest's capabilities.
|
||||
|
||||
Supported nose Idioms
|
||||
----------------------
|
||||
@@ -40,7 +40,7 @@ If you find other issues or have suggestions please run::
|
||||
|
||||
py.test --pastebin=all
|
||||
|
||||
and send the resulting URL to a py.test contact channel,
|
||||
and send the resulting URL to a ``pytest`` contact channel,
|
||||
at best to the mailing list.
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
@@ -49,7 +49,7 @@ Start improving this plugin in 30 seconds
|
||||
|
||||
1. Download `pytest_nose.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_nose.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
3. a subsequent ``pytest`` run will use your local version
|
||||
|
||||
Checkout customize_, other plugins_ or `get in contact`_.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pytest_oejskit plugin (EXTERNAL)
|
||||
==========================================
|
||||
|
||||
The `oejskit`_ offers a py.test plugin for running Javascript tests in life browsers. Running inside the browsers comes with some speed cost, on the other hand it means for example the code is tested against the real-word DOM implementations.
|
||||
The `oejskit`_ offers a ``pytest`` plugin for running Javascript tests in live browsers. Running inside the browsers comes with some speed cost, on the other hand it means for example the code is tested against the real-word DOM implementations.
|
||||
The approach enables to write integration tests such that the JavaScript code is tested against server-side Python code mocked as necessary. Any server-side framework that can already be exposed through WSGI (or for which a subset of WSGI can be written to accommodate the jskit own needs) can play along.
|
||||
|
||||
For more info and download please visit the `oejskit PyPI`_ page.
|
||||
|
||||
@@ -33,7 +33,7 @@ Start improving this plugin in 30 seconds
|
||||
|
||||
1. Download `pytest_terminal.py`_ plugin source code
|
||||
2. put it somewhere as ``pytest_terminal.py`` into your import path
|
||||
3. a subsequent ``py.test`` run will use your local version
|
||||
3. a subsequent ``pytest`` run will use your local version
|
||||
|
||||
Checkout customize_, other plugins_ or `get in contact`_.
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ loop on failing tests, distribute test runs to CPUs and hosts.
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
The `pytest-xdist`_ plugin extends py.test with some unique
|
||||
The `pytest-xdist`_ plugin extends ``pytest`` with some unique
|
||||
test execution modes:
|
||||
|
||||
* Looponfail: run your tests repeatedly in a subprocess. After each run py.test
|
||||
waits until a file in your project changes and then re-runs the previously
|
||||
failing tests. This is repeated until all tests pass after which again
|
||||
a full run is performed.
|
||||
* Looponfail: run your tests repeatedly in a subprocess. After each run
|
||||
``pytest`` waits until a file in your project changes and then re-runs the
|
||||
previously failing tests. This is repeated until all tests pass after which
|
||||
again a full run is performed.
|
||||
|
||||
* Load-balancing: if you have multiple CPUs or hosts you can use
|
||||
those for a combined test run. This allows to speed up
|
||||
@@ -21,7 +21,7 @@ test execution modes:
|
||||
* Multi-Platform coverage: you can specify different Python interpreters
|
||||
or different platforms and run tests in parallel on all of them.
|
||||
|
||||
Before running tests remotely, ``py.test`` efficiently synchronizes your
|
||||
Before running tests remotely, ``pytest`` efficiently synchronizes your
|
||||
program source code to the remote place. All test results
|
||||
are reported back and displayed to your local test session.
|
||||
You may specify different Python versions and interpreters.
|
||||
@@ -77,11 +77,11 @@ and send them to remote places for execution.
|
||||
You can specify multiple ``--rsyncdir`` directories
|
||||
to be sent to the remote side.
|
||||
|
||||
**NOTE:** For py.test to collect and send tests correctly
|
||||
**NOTE:** For ``pytest`` to collect and send tests correctly
|
||||
you not only need to make sure all code and tests
|
||||
directories are rsynced, but that any test (sub) directory
|
||||
also has an ``__init__.py`` file because internally
|
||||
py.test references tests as a fully qualified python
|
||||
``pytest`` references tests using their fully qualified python
|
||||
module path. **You will otherwise get strange errors**
|
||||
during setup of the remote side.
|
||||
|
||||
@@ -156,11 +156,11 @@ command line options
|
||||
box each test run in a separate process (unix)
|
||||
``--dist=distmode``
|
||||
set mode for distributing tests to exec environments.
|
||||
|
||||
|
||||
each: send each test to each available environment.
|
||||
|
||||
|
||||
load: send each test to available environment.
|
||||
|
||||
|
||||
(default) no: run tests inprocess, don't distribute.
|
||||
``--tx=xspec``
|
||||
add a test execution environment. some examples: --tx popen//python=python2.5 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
|
||||
|
||||
@@ -29,7 +29,7 @@ Running this would result in a passed test except for the last
|
||||
|
||||
$ py.test test_tmpdir.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 1 items
|
||||
|
||||
test_tmpdir.py F
|
||||
@@ -37,7 +37,7 @@ Running this would result in a passed test except for the last
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_create_file _____________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-278/test_create_file0')
|
||||
tmpdir = local('/tmp/pytest-1009/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.02 seconds =========================
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
.. _`base temporary directory`:
|
||||
|
||||
@@ -64,7 +64,7 @@ You can override the default temporary directory setting like this::
|
||||
|
||||
py.test --basetemp=mydir
|
||||
|
||||
When distributing tests on the local machine, ``py.test`` takes care to
|
||||
When distributing tests on the local machine, ``pytest`` takes care to
|
||||
configure a basetemp directory for the sub processes such that all temporary
|
||||
data lands below a single per-test run basetemp directory.
|
||||
|
||||
|
||||
@@ -6,13 +6,13 @@ Support for unittest.TestCase / Integration of fixtures
|
||||
|
||||
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
|
||||
|
||||
py.test has support for running Python `unittest.py style`_ tests.
|
||||
``pytest`` has support for running Python `unittest.py style`_ tests.
|
||||
It's meant for leveraging existing unittest-style projects
|
||||
to use pytest features. Concretely, pytest will automatically
|
||||
collect ``unittest.TestCase`` subclasses and their ``test`` methods in
|
||||
test files. It will invoke typical setup/teardown methods and
|
||||
generally try to make test suites written to run on unittest, to also
|
||||
run using ``py.test``. We assume here that you are familiar with writing
|
||||
run using ``pytest``. We assume here that you are familiar with writing
|
||||
``unittest.TestCase`` style tests and rather focus on
|
||||
integration aspects.
|
||||
|
||||
@@ -30,12 +30,12 @@ you can make use of most :ref:`pytest features <features>`, for example
|
||||
: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.
|
||||
the general ``pytest`` documentation for many more examples.
|
||||
|
||||
Mixing pytest fixtures into unittest.TestCase style tests
|
||||
-----------------------------------------------------------
|
||||
|
||||
Running your unittest with ``py.test`` allows you to use its
|
||||
Running your unittest with ``pytest`` allows you to use its
|
||||
:ref:`fixture mechanism <fixture>` with ``unittest.TestCase`` style
|
||||
tests. Assuming you have at least skimmed the pytest fixture features,
|
||||
let's jump-start into an example that integrates a pytest ``db_class``
|
||||
@@ -88,7 +88,7 @@ the ``self.db`` values in the traceback::
|
||||
|
||||
$ py.test test_unittest_db.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.5.0
|
||||
platform linux2 -- Python 2.7.3 -- py-1.4.20 -- pytest-2.5.2
|
||||
collected 2 items
|
||||
|
||||
test_unittest_db.py FF
|
||||
@@ -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 0x101b3b0>
|
||||
E AssertionError: <conftest.DummyDB instance at 0x12124d0>
|
||||
|
||||
test_unittest_db.py:9: AssertionError
|
||||
___________________________ MyTest.test_method2 ____________________________
|
||||
@@ -110,10 +110,10 @@ 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 0x101b3b0>
|
||||
E AssertionError: <conftest.DummyDB instance at 0x12124d0>
|
||||
|
||||
test_unittest_db.py:12: AssertionError
|
||||
========================= 2 failed in 0.02 seconds =========================
|
||||
========================= 2 failed in 0.01 seconds =========================
|
||||
|
||||
This default pytest traceback shows that the two test methods
|
||||
share the same ``self.db`` instance which was our intention
|
||||
@@ -160,7 +160,7 @@ Running this test module ...::
|
||||
|
||||
$ py.test -q test_unittest_cleandir.py
|
||||
.
|
||||
1 passed in 0.02 seconds
|
||||
1 passed in 0.01 seconds
|
||||
|
||||
... gives us one passed test because the ``initdir`` fixture function
|
||||
was executed ahead of the ``test_method``.
|
||||
|
||||
@@ -72,7 +72,7 @@ Dropping to PDB (Python Debugger) on failures
|
||||
|
||||
.. _PDB: http://docs.python.org/library/pdb.html
|
||||
|
||||
Python comes with a builtin Python debugger called PDB_. ``py.test``
|
||||
Python comes with a builtin Python debugger called PDB_. ``pytest``
|
||||
allows one to drop into the PDB prompt via a command line option::
|
||||
|
||||
py.test --pdb
|
||||
@@ -153,6 +153,17 @@ for example ``-x`` if you only want to send one particular failure.
|
||||
|
||||
Currently only pasting to the http://bpaste.net service is implemented.
|
||||
|
||||
Disabling plugins
|
||||
-----------------
|
||||
|
||||
To disable loading specific plugins at invocation time, use the ``-p`` option
|
||||
together with the prefix ``no:``.
|
||||
|
||||
Example: to disable loading the plugin ``doctest``, which is responsible for
|
||||
executing doctest tests from text files, invoke py.test like this::
|
||||
|
||||
py.test -p no:doctest
|
||||
|
||||
.. _`pytest.main-usage`:
|
||||
|
||||
Calling pytest from Python code
|
||||
@@ -160,7 +171,7 @@ Calling pytest from Python code
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
You can invoke ``py.test`` from Python code directly::
|
||||
You can invoke ``pytest`` from Python code directly::
|
||||
|
||||
pytest.main()
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
xdist: pytest distributed testing plugin
|
||||
===============================================================
|
||||
|
||||
The `pytest-xdist`_ plugin extends py.test with some unique
|
||||
The `pytest-xdist`_ plugin extends ``pytest`` with some unique
|
||||
test execution modes:
|
||||
|
||||
* Looponfail: run your tests repeatedly in a subprocess. After each
|
||||
run, py.test waits until a file in your project changes and then
|
||||
run, ``pytest`` waits until a file in your project changes and then
|
||||
re-runs the previously failing tests. This is repeated until all
|
||||
tests pass. At this point a full run is again performed.
|
||||
|
||||
@@ -19,7 +19,7 @@ test execution modes:
|
||||
* Multi-Platform coverage: you can specify different Python interpreters
|
||||
or different platforms and run tests in parallel on all of them.
|
||||
|
||||
Before running tests remotely, ``py.test`` efficiently "rsyncs" your
|
||||
Before running tests remotely, ``pytest`` efficiently "rsyncs" your
|
||||
program source code to the remote place. All test results
|
||||
are reported back and displayed to your local terminal.
|
||||
You may specify different Python versions and interpreters.
|
||||
@@ -86,7 +86,7 @@ you can use the looponfailing mode. Simply add the ``--f`` option::
|
||||
|
||||
py.test -f
|
||||
|
||||
and py.test will run your tests. Assuming you have failures it will then
|
||||
and ``pytest`` will run your tests. Assuming you have failures it will then
|
||||
wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
|
||||
can change it in your project by setting a configuration option::
|
||||
|
||||
@@ -115,11 +115,11 @@ to be sent to the remote side.
|
||||
|
||||
.. XXX CHECK
|
||||
|
||||
**NOTE:** For py.test to collect and send tests correctly
|
||||
**NOTE:** For ``pytest`` to collect and send tests correctly
|
||||
you not only need to make sure all code and tests
|
||||
directories are rsynced, but that any test (sub) directory
|
||||
also has an ``__init__.py`` file because internally
|
||||
py.test references tests as a fully qualified python
|
||||
``pytest`` references tests as a fully qualified python
|
||||
module path. **You will otherwise get strange errors**
|
||||
during setup of the remote side.
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ Let's run it with output capturing disabled::
|
||||
test called
|
||||
.teardown after yield
|
||||
|
||||
1 passed in 0.01 seconds
|
||||
1 passed in 0.00 seconds
|
||||
|
||||
We can also seemlessly use the new syntax with ``with`` statements.
|
||||
Let's simplify the above ``passwd`` fixture::
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user