Compare commits
230 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2a8866bce | ||
|
|
c69978fbb0 | ||
|
|
c1eaa72883 | ||
|
|
55f3ffd2ba | ||
|
|
55eb82c434 | ||
|
|
d94a29e866 | ||
|
|
a7d2a82caa | ||
|
|
ce95437dee | ||
|
|
3ba3112a85 | ||
|
|
c019e489d2 | ||
|
|
43e4fcf6dd | ||
|
|
65ca554230 | ||
|
|
52a2999a91 | ||
|
|
f3580bee2d | ||
|
|
deb163d237 | ||
|
|
6f81602ba2 | ||
|
|
ac17f20d98 | ||
|
|
a9b7de8bf0 | ||
|
|
0fc75c9622 | ||
|
|
9726fafa98 | ||
|
|
cf7bb70809 | ||
|
|
03c3930734 | ||
|
|
25a4d7d882 | ||
|
|
eead0365b5 | ||
|
|
eb3b989286 | ||
|
|
cdb46e9f16 | ||
|
|
ead25634fe | ||
|
|
3f3521c826 | ||
|
|
0c2dfb9683 | ||
|
|
5d6b0a59c0 | ||
|
|
c629f6b18b | ||
|
|
b48eda6d7d | ||
|
|
81243657be | ||
|
|
24fe051803 | ||
|
|
16bcfa749e | ||
|
|
d083153548 | ||
|
|
41e6b04f0b | ||
|
|
33c2a3a3e5 | ||
|
|
97d5da5c99 | ||
|
|
d1005ebb8f | ||
|
|
c4623939af | ||
|
|
060609317a | ||
|
|
bae0f7f46a | ||
|
|
09a50b6e6d | ||
|
|
200fe072f1 | ||
|
|
ff9ec13ddb | ||
|
|
9384ff38c9 | ||
|
|
1e6e373913 | ||
|
|
e510eb0d45 | ||
|
|
2e2d6a8bef | ||
|
|
44cd1c9862 | ||
|
|
f6f084fa01 | ||
|
|
b7d212c0c9 | ||
|
|
bda3e53df6 | ||
|
|
9d4354c0a4 | ||
|
|
f99ddbfdf2 | ||
|
|
019dc14fc4 | ||
|
|
dbb58b39d9 | ||
|
|
c3ca44b46f | ||
|
|
f6df3b0b97 | ||
|
|
e9d4853296 | ||
|
|
28c2327f73 | ||
|
|
8ed5b77aba | ||
|
|
660b84a052 | ||
|
|
d73e689991 | ||
|
|
c773ea664b | ||
|
|
aa757f7715 | ||
|
|
4222a806f1 | ||
|
|
415c76b255 | ||
|
|
f1c9554f42 | ||
|
|
3d0b756877 | ||
|
|
ea4e9fa4e2 | ||
|
|
777bde7c60 | ||
|
|
e19f3c260f | ||
|
|
5025478ac2 | ||
|
|
5b73de92c2 | ||
|
|
6a237bd49f | ||
|
|
89710b4901 | ||
|
|
459d6e610c | ||
|
|
d1adbf4a5c | ||
|
|
c11cc36997 | ||
|
|
2b7fae2368 | ||
|
|
f2ca0b8170 | ||
|
|
912c8f0540 | ||
|
|
8f12269db7 | ||
|
|
7325a5fe2e | ||
|
|
9f4d0be895 | ||
|
|
394367e1d2 | ||
|
|
7e15fb7f2d | ||
|
|
8859936301 | ||
|
|
d580f5bac8 | ||
|
|
5941b2e071 | ||
|
|
bca19a1156 | ||
|
|
3df5989326 | ||
|
|
98b9de4ff1 | ||
|
|
0e248c9aed | ||
|
|
883b3ca2c1 | ||
|
|
e4bb48995a | ||
|
|
1d15bb2880 | ||
|
|
959395b796 | ||
|
|
f6caf230f8 | ||
|
|
f2cdbe776e | ||
|
|
97c9c10f3c | ||
|
|
f74930db79 | ||
|
|
5a88a9b22a | ||
|
|
d0d4759c96 | ||
|
|
749316623b | ||
|
|
60cdb875ed | ||
|
|
e0251ecb41 | ||
|
|
0834b63560 | ||
|
|
0c8569dcb0 | ||
|
|
5f2444d2a2 | ||
|
|
537dca477b | ||
|
|
8480111012 | ||
|
|
c63dc62294 | ||
|
|
8d19ccb56f | ||
|
|
eac4514227 | ||
|
|
16f0d100cc | ||
|
|
0b620c304b | ||
|
|
7371d436d2 | ||
|
|
b928928942 | ||
|
|
4337e9c4ba | ||
|
|
8dfd6c17e3 | ||
|
|
de7c97aa1e | ||
|
|
ace668ae8f | ||
|
|
857db415bc | ||
|
|
f8623a6668 | ||
|
|
4cadc600d5 | ||
|
|
d62ec2985d | ||
|
|
b2341899c5 | ||
|
|
2c84e9ddac | ||
|
|
b7dd8eac8e | ||
|
|
61d0209093 | ||
|
|
8b9bb5ff54 | ||
|
|
cb2c89a070 | ||
|
|
cea9367739 | ||
|
|
e1a66d54b9 | ||
|
|
a37f9f19d4 | ||
|
|
91aa6ab0df | ||
|
|
c85c5d05c5 | ||
|
|
34df678bc3 | ||
|
|
8c91ffc701 | ||
|
|
eda39f361d | ||
|
|
c58770bfef | ||
|
|
d9858844c3 | ||
|
|
04b8111f8f | ||
|
|
0253f7b8d5 | ||
|
|
5999368002 | ||
|
|
bf2f2dc2a6 | ||
|
|
787b0212d1 | ||
|
|
1de5af66da | ||
|
|
61caa4f776 | ||
|
|
9ca7e46a0a | ||
|
|
f66e0825b2 | ||
|
|
f5f924d293 | ||
|
|
c3d1986101 | ||
|
|
89de87dce1 | ||
|
|
ab005a4261 | ||
|
|
3d6ad054c0 | ||
|
|
b6e619413f | ||
|
|
a43fb9cd93 | ||
|
|
68f3818562 | ||
|
|
1ed1ef3c71 | ||
|
|
b6475b058f | ||
|
|
e39556ada0 | ||
|
|
966c63d477 | ||
|
|
a298077461 | ||
|
|
e1aed27c15 | ||
|
|
a759da0208 | ||
|
|
6ab36592ea | ||
|
|
c45b7012f5 | ||
|
|
1d10db4bab | ||
|
|
767e44ef29 | ||
|
|
4a11edfb68 | ||
|
|
e53bb1af45 | ||
|
|
e5d0862fa5 | ||
|
|
2ed4c2135a | ||
|
|
8cfec56a82 | ||
|
|
818a412d29 | ||
|
|
39158957f4 | ||
|
|
2cb0145bce | ||
|
|
dfda9acd6d | ||
|
|
c6951d5184 | ||
|
|
f85648bbf8 | ||
|
|
dd1ee22293 | ||
|
|
9def8522f3 | ||
|
|
a999fcd36a | ||
|
|
24468a6f34 | ||
|
|
ba8ae427e2 | ||
|
|
d6d2e6c615 | ||
|
|
7f93063945 | ||
|
|
63f070317c | ||
|
|
3d84f35850 | ||
|
|
3d794b6b38 | ||
|
|
d8f4663f49 | ||
|
|
34b9f90f35 | ||
|
|
5ec1dd2609 | ||
|
|
b691cbd7e2 | ||
|
|
d7ada40130 | ||
|
|
2f141bbc54 | ||
|
|
a098226ee4 | ||
|
|
fd2572a39d | ||
|
|
05d4a3f9eb | ||
|
|
2161b54555 | ||
|
|
69ff29bf44 | ||
|
|
de83d35994 | ||
|
|
c7c4f62f77 | ||
|
|
e635f9f9b2 | ||
|
|
f250e912eb | ||
|
|
351931d5ca | ||
|
|
28c785a0d1 | ||
|
|
3de715ec13 | ||
|
|
ea5fb0c153 | ||
|
|
9e549a1acf | ||
|
|
c7a45d6eaf | ||
|
|
37631dbfa0 | ||
|
|
e9f240a9a3 | ||
|
|
531be22a87 | ||
|
|
be93fdf11d | ||
|
|
f05cb934a9 | ||
|
|
82d806deb6 | ||
|
|
72e6f55b45 | ||
|
|
9a0f2a9fb7 | ||
|
|
49b7237581 | ||
|
|
814d348e7d | ||
|
|
88c14cad94 | ||
|
|
d99243c1a7 | ||
|
|
8844d9d04f | ||
|
|
54e00429e4 | ||
|
|
4e35c00ab0 |
2
.hgtags
2
.hgtags
@@ -71,3 +71,5 @@ a064ad64d167508a8e9e73766b1a4e6bd10c85db 2.5.0
|
||||
88af949b9611494e2c65d528f9e565b00fb7e8ca 2.6.0
|
||||
a4f9639702baa3eb4f3b16e162f74f7b69f3f9e1 2.6.1
|
||||
a4f25c5e649892b5cc746d21be971e4773478af9 2.6.2
|
||||
2967aa416a4f3cdb65fc75073a2a148e1f372742 2.6.3
|
||||
f03b6de8325f5b6c35cea7c3de092f134ea8ef07 2.6.4
|
||||
|
||||
3
AUTHORS
3
AUTHORS
@@ -45,3 +45,6 @@ Andy Freeland
|
||||
Trevor Bekolay
|
||||
David Mohr
|
||||
Nicolas Delaby
|
||||
Tom Viner
|
||||
Dave Hunt
|
||||
Charles Cloud
|
||||
|
||||
127
CHANGELOG
127
CHANGELOG
@@ -1,3 +1,102 @@
|
||||
2.7.0 (compared to 2.6.4)
|
||||
-----------------------------
|
||||
|
||||
- fix issue435: make reload() work when assert rewriting is active.
|
||||
Thanks Daniel Hahler.
|
||||
|
||||
- fix issue616: conftest.py files and their contained fixutres are now
|
||||
properly considered for visibility, independently from the exact
|
||||
current working directory and test arguments that are used.
|
||||
Many thanks to Eric Siegerman and his PR235 which contains
|
||||
systematic tests for conftest visibility and now passes.
|
||||
This change also introduces the concept of a ``rootdir`` which
|
||||
is printed as a new pytest header and documented in the pytest
|
||||
customize web page.
|
||||
|
||||
- change reporting of "diverted" tests, i.e. tests that are collected
|
||||
in one file but actually come from another (e.g. when tests in a test class
|
||||
come from a base class in a different file). We now show the nodeid
|
||||
and indicate via a postfix the other file.
|
||||
|
||||
- add ability to set command line options by environment variable PYTEST_ADDOPTS.
|
||||
|
||||
- added documentation on the new pytest-dev teams on bitbucket and
|
||||
github. See https://pytest.org/latest/contributing.html .
|
||||
Thanks to Anatoly for pushing and initial work on this.
|
||||
|
||||
- fix issue650: new option ``--docttest-ignore-import-errors`` which
|
||||
will turn import errors in doctests into skips. Thanks Charles Cloud
|
||||
for the complete PR.
|
||||
|
||||
- fix issue655: work around different ways that cause python2/3
|
||||
to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
|
||||
|
||||
- fix issue615: assertion re-writing did not correctly escape % signs
|
||||
when formatting boolean operations, which tripped over mixing
|
||||
booleans with modulo operators. Thanks to Tom Viner for the report,
|
||||
triaging and fix.
|
||||
|
||||
- implement issue351: add ability to specify parametrize ids as a callable
|
||||
to generate custom test ids. Thanks Brianna Laugher for the idea and
|
||||
implementation.
|
||||
|
||||
- introduce and document new hookwrapper mechanism useful for plugins
|
||||
which want to wrap the execution of certain hooks for their purposes.
|
||||
This supersedes the undocumented ``__multicall__`` protocol which
|
||||
pytest itself and some external plugins use. Note that pytest-2.8
|
||||
is scheduled to drop supporting the old ``__multicall__``
|
||||
and only support the hookwrapper protocol.
|
||||
|
||||
- majorly speed up invocation of plugin hooks
|
||||
|
||||
- use hookwrapper mechanism in builtin pytest plugins.
|
||||
|
||||
- add a doctest ini option for doctest flags, thanks Holger Peters.
|
||||
|
||||
- add note to docs that if you want to mark a parameter and the
|
||||
parameter is a callable, you also need to pass in a reason to disambiguate
|
||||
it from the "decorator" case. Thanks Tom Viner.
|
||||
|
||||
- "python_classes" and "python_functions" options now support glob-patterns
|
||||
for test discovery, as discussed in issue600. Thanks Ldiary Translations.
|
||||
|
||||
- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
|
||||
|
||||
- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
|
||||
|
||||
- On failure, the ``sys.last_value``, ``sys.last_type`` and
|
||||
``sys.last_traceback`` are set, so that a user can inspect the error
|
||||
via postmortem debugging (almarklein).
|
||||
|
||||
2.6.4
|
||||
----------
|
||||
|
||||
- Improve assertion failure reporting on iterables, by using ndiff and
|
||||
pprint.
|
||||
|
||||
- removed outdated japanese docs from source tree.
|
||||
|
||||
- docs for "pytest_addhooks" hook. Thanks Bruno Oliveira.
|
||||
|
||||
- updated plugin index docs. Thanks Bruno Oliveira.
|
||||
|
||||
- fix issue557: with "-k" we only allow the old style "-" for negation
|
||||
at the beginning of strings and even that is deprecated. Use "not" instead.
|
||||
This should allow to pick parametrized tests where "-" appeared in the parameter.
|
||||
|
||||
- fix issue604: Escape % character in the assertion message.
|
||||
|
||||
- fix issue620: add explanation in the --genscript target about what
|
||||
the binary blob means. Thanks Dinu Gherman.
|
||||
|
||||
- fix issue614: fixed pastebin support.
|
||||
|
||||
|
||||
- fix issue620: add explanation in the --genscript target about what
|
||||
the binary blob means. Thanks Dinu Gherman.
|
||||
|
||||
- fix issue614: fixed pastebin support.
|
||||
|
||||
2.6.3
|
||||
-----------
|
||||
|
||||
@@ -51,7 +150,7 @@
|
||||
Thanks sontek.
|
||||
|
||||
- Implement issue549: user-provided assertion messages now no longer
|
||||
replace the py.test instrospection message but are shown in addition
|
||||
replace the py.test introspection message but are shown in addition
|
||||
to them.
|
||||
|
||||
2.6.1
|
||||
@@ -80,7 +179,7 @@
|
||||
- fix issue with detecting conftest files if the arguments contain
|
||||
"::" node id specifications (copy pasted from "-v" output)
|
||||
|
||||
- fix issue544 by only removing "@NUM" at the end of "::" separated parts
|
||||
- fix issue544 by only removing "@NUM" at the end of "::" separated parts
|
||||
and if the part has an ".py" extension
|
||||
|
||||
- don't use py.std import helper, rather import things directly.
|
||||
@@ -93,7 +192,7 @@
|
||||
|
||||
- fix issue537: Avoid importing old assertion reinterpretation code by default.
|
||||
|
||||
- fix issue364: shorten and enhance tracebacks representation by default.
|
||||
- fix issue364: shorten and enhance tracebacks representation by default.
|
||||
The new "--tb=auto" option (default) will only display long tracebacks
|
||||
for the first and last entry. You can get the old behaviour of printing
|
||||
all entries as long entries with "--tb=long". Also short entries by
|
||||
@@ -119,14 +218,14 @@
|
||||
- fix issue473: work around mock putting an unbound method into a class
|
||||
dict when double-patching.
|
||||
|
||||
- fix issue498: if a fixture finalizer fails, make sure that
|
||||
- fix issue498: if a fixture finalizer fails, make sure that
|
||||
the fixture is still invalidated.
|
||||
|
||||
- fix issue453: the result of the pytest_assertrepr_compare hook now gets
|
||||
it's newlines escaped so that format_exception does not blow up.
|
||||
|
||||
- internal new warning system: pytest will now produce warnings when
|
||||
it detects oddities in your test collection or execution.
|
||||
it detects oddities in your test collection or execution.
|
||||
Warnings are ultimately sent to a new pytest_logwarning hook which is
|
||||
currently only implemented by the terminal plugin which displays
|
||||
warnings in the summary line and shows more details when -rw (report on
|
||||
@@ -170,7 +269,7 @@
|
||||
|
||||
- fix issue492: avoid leak in test_writeorg. Thanks Marc Abramowitz.
|
||||
|
||||
- fix issue493: don't run tests in doc directory with ``python setup.py test``
|
||||
- fix issue493: don't run tests in doc directory with ``python setup.py test``
|
||||
(use tox -e doctesting for that)
|
||||
|
||||
- fix issue486: better reporting and handling of early conftest loading failures
|
||||
@@ -184,8 +283,8 @@
|
||||
Groenholm.
|
||||
|
||||
- support nose-style ``__test__`` attribute on modules, classes and
|
||||
functions, including unittest-style Classes. If set to False, the
|
||||
test will not be collected.
|
||||
functions, including unittest-style Classes. If set to False, the
|
||||
test will not be collected.
|
||||
|
||||
- fix issue512: show "<notset>" for arguments which might not be set
|
||||
in monkeypatch plugin. Improves output in documentation.
|
||||
@@ -195,11 +294,11 @@
|
||||
-----------------------------------
|
||||
|
||||
- fix issue409 -- better interoperate with cx_freeze by not
|
||||
trying to import from collections.abc which causes problems
|
||||
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.
|
||||
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)
|
||||
@@ -210,7 +309,7 @@
|
||||
|
||||
- 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
|
||||
@@ -230,7 +329,7 @@
|
||||
|
||||
- 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.
|
||||
Thanks Floris Bruynooghe.
|
||||
|
||||
- fix issue404 by always using the binary xml escape in the junitxml
|
||||
plugin. Thanks Ronny Pfannschmidt.
|
||||
@@ -397,7 +496,7 @@ v2.4.2
|
||||
|
||||
- introduce node.get_marker/node.add_marker API for plugins
|
||||
like pytest-pep8 and pytest-flakes to avoid the messy
|
||||
details of the node.keywords pseudo-dicts. Adapated
|
||||
details of the node.keywords pseudo-dicts. Adapted
|
||||
docs.
|
||||
|
||||
- remove attempt to "dup" stdout at startup as it's icky.
|
||||
@@ -464,7 +563,7 @@ new features:
|
||||
as strings will remain fully supported.
|
||||
|
||||
- reporting: color the last line red or green depending if
|
||||
failures/errors occured or everything passed. thanks Christian
|
||||
failures/errors occurred or everything passed. thanks Christian
|
||||
Theunert.
|
||||
|
||||
- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
|
||||
|
||||
151
CONTRIBUTING.rst
151
CONTRIBUTING.rst
@@ -1,18 +1,62 @@
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
============================
|
||||
Contribution getting started
|
||||
============================
|
||||
|
||||
Contributions are highly welcomed and appreciated. Every little help counts,
|
||||
so do not hesitate!
|
||||
|
||||
.. contents:: Contribution links
|
||||
:depth: 2
|
||||
|
||||
Types of contributions
|
||||
======================
|
||||
|
||||
.. _submitplugin:
|
||||
|
||||
Submit a plugin, co-develop pytest
|
||||
----------------------------------
|
||||
|
||||
Pytest development of the core, some plugins and support code happens
|
||||
in repositories living under:
|
||||
|
||||
- `the pytest-dev bitbucket team <https://bitbucket.org/pytest-dev>`_
|
||||
|
||||
- `the pytest-dev github organisation <https://github.com/pytest-dev>`_
|
||||
|
||||
All pytest-dev team members have write access to all contained
|
||||
repositories. pytest core and plugins are generally developed
|
||||
using `pull requests`_ to respective repositories.
|
||||
|
||||
You can submit your plugin by subscribing to the `pytest-dev mail list
|
||||
<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
|
||||
mail pointing to your existing pytest plugin repository which must have
|
||||
the following:
|
||||
|
||||
- PyPI presence with a ``setup.py`` that contains a license, ``pytest-``
|
||||
prefixed, version number, authors, short and long description.
|
||||
|
||||
- a ``tox.ini`` for running tests using `tox <http://tox.testrun.org>`_.
|
||||
|
||||
- a ``README.txt`` describing how to use the plugin and on which
|
||||
platforms it runs.
|
||||
|
||||
- a ``LICENSE.txt`` file or equivalent containing the licensing
|
||||
information, with matching info in ``setup.py``.
|
||||
|
||||
- an issue tracker unless you rather want to use the core ``pytest``
|
||||
issue tracker.
|
||||
|
||||
If no contributor strongly objects and two agree, the repo will be
|
||||
transferred to the ``pytest-dev`` organisation and you'll become a
|
||||
member of the ``pytest-dev`` team, with commit rights to all projects.
|
||||
We recommend that each plugin has at least three people who have the
|
||||
right to release to pypi.
|
||||
|
||||
|
||||
.. _reportbugs:
|
||||
|
||||
Report bugs
|
||||
-----------
|
||||
|
||||
Report bugs at https://bitbucket.org/hpk42/pytest/issues.
|
||||
Report bugs for pytest at https://bitbucket.org/pytest-dev/pytest/issues
|
||||
|
||||
If you are reporting a bug, please include:
|
||||
|
||||
@@ -22,13 +66,15 @@ If you are reporting a bug, please include:
|
||||
installed libraries and pytest version.
|
||||
* Detailed steps to reproduce the bug.
|
||||
|
||||
.. _submitfeedback:
|
||||
|
||||
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:
|
||||
`submit them as issues <https://bitbucket.org/pytest-dev/pytest/issues>`__ and:
|
||||
|
||||
* Set the "kind" to "enhancement" or "proposal" so that we can quickly find
|
||||
about them.
|
||||
@@ -37,21 +83,24 @@ We'd also like to hear about your propositions and suggestions. Feel free to
|
||||
* If you have required skills and/or knowledge, we are very happy for
|
||||
:ref:`pull requests <pull-requests>`.
|
||||
|
||||
.. _fixbugs:
|
||||
|
||||
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
|
||||
https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=bug
|
||||
|
||||
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
|
||||
|
||||
.. _writeplugins:
|
||||
|
||||
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
|
||||
https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&kind=enhancement
|
||||
|
||||
:ref:`Talk <contact>` to developers to find out how you can implement specific
|
||||
features.
|
||||
@@ -66,37 +115,34 @@ pytest could always use more documentation. What exactly is needed?
|
||||
* Docstrings. There's never too much of them.
|
||||
* Blog posts, articles and such -- they're all very appreciated.
|
||||
|
||||
.. _`pull requests`:
|
||||
.. _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>`__.
|
||||
`BitBucket servers <https://bitbucket.org/pytest-dev/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
|
||||
#. Fork the
|
||||
`pytest BitBucket repository <https://bitbucket.org/pytest-dev/pytest>`__. It's
|
||||
fine to use ``pytest`` as your fork repository name because it will live
|
||||
under your user.
|
||||
|
||||
.. _virtualenvactivate:
|
||||
#. Create a development environment
|
||||
(will implicitly use http://www.virtualenv.org/en/latest/)::
|
||||
|
||||
2. Create and activate a fork-specific virtualenv
|
||||
(http://www.virtualenv.org/en/latest/)::
|
||||
$ make develop
|
||||
$ source .env/bin/activate
|
||||
|
||||
$ virtualenv pytest-venv
|
||||
$ source pytest-venv/bin/activate
|
||||
|
||||
.. _checkout:
|
||||
|
||||
3. Clone your fork locally using `Mercurial <http://mercurial.selenic.com/>`_
|
||||
#. 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
|
||||
@@ -106,55 +152,56 @@ the issues there and submit your pull requests.
|
||||
If you need some help with Mercurial, follow this quick start
|
||||
guide: http://mercurial.selenic.com/wiki/QuickStart
|
||||
|
||||
.. _testing-pytest:
|
||||
#. Create a development environment
|
||||
(will implicitly use http://www.virtualenv.org/en/latest/)::
|
||||
|
||||
4. You can now edit your local working copy. To test you need to
|
||||
install the "tox" tool into your virtualenv::
|
||||
$ make develop
|
||||
$ source .env/bin/activate
|
||||
|
||||
$ pip install tox
|
||||
#. You can now edit your local working copy.
|
||||
|
||||
You need to have Python 2.7 and 3.3 available in your system. Now
|
||||
running tests is as simple as issuing this command::
|
||||
You need to have Python 2.7 and 3.4 available in your system. Now
|
||||
running tests is as simple as issuing this command::
|
||||
|
||||
$ python runtox.py -e py27,py33,flakes
|
||||
$ python runtox.py -e py27,py34,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.
|
||||
This command will run tests via the "tox" tool against Python 2.7 and 3.4
|
||||
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::
|
||||
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::
|
||||
or to only run tests in a particular test module on py34::
|
||||
|
||||
$ python runtox.py -e py33 -- testing/test_config.py
|
||||
$ python runtox.py -e py34 -- testing/test_config.py
|
||||
|
||||
5. Commit and push once your tests pass and you are happy with your change(s)::
|
||||
#. 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:
|
||||
#. Finally, submit a pull request through the BitBucket website:
|
||||
|
||||
.. image:: img/pullrequest.png
|
||||
:width: 700px
|
||||
:align: center
|
||||
.. image:: img/pullrequest.png
|
||||
:width: 700px
|
||||
:align: center
|
||||
|
||||
::
|
||||
::
|
||||
|
||||
source: YOUR_BITBUCKET_USERNAME/pytest
|
||||
branch: your-branch-name
|
||||
|
||||
target: hpk42/pytest
|
||||
target: pytest-dev/pytest
|
||||
branch: default
|
||||
|
||||
.. _contribution-using-git:
|
||||
|
||||
What about git (and so GitHub)?
|
||||
Using git with bitbucket/hg
|
||||
-------------------------------
|
||||
|
||||
There used to be the pytest GitHub mirror. It was removed in favor of the
|
||||
@@ -162,10 +209,8 @@ 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.
|
||||
In general we recommend to work with the same version control system of the
|
||||
original repository. If you insist on using git with bitbucket/hg you
|
||||
may try `gitifyhg <https://github.com/buchuki/gitifyhg>`_ but are on your
|
||||
own and need to submit pull requests through the respective platform,
|
||||
nevertheless.
|
||||
|
||||
10
ISSUES.txt
10
ISSUES.txt
@@ -49,7 +49,7 @@ probably makes sense in order to keep the declarative nature. This mirrors
|
||||
the marker-mechanism with respect to a test module but puts it to a directory
|
||||
scale.
|
||||
|
||||
When doing larger scoped parametrization it probably becomes neccessary
|
||||
When doing larger scoped parametrization it probably becomes necessary
|
||||
to allow parametrization to be ignored if the according parameter is not
|
||||
used (currently any parametrized argument that is not present in a function will cause a ValueError). Example:
|
||||
|
||||
@@ -77,7 +77,7 @@ this would run the test_hello() function three times with three
|
||||
different values for self.db. This could also work with unittest/nose
|
||||
style tests, i.e. it leverages existing test suites without needing
|
||||
to rewrite them. Together with the previously mentioned setup_test()
|
||||
maybe the setupfunc could be ommitted?
|
||||
maybe the setupfunc could be omitted?
|
||||
|
||||
optimizations
|
||||
---------------------------------------------------------------
|
||||
@@ -229,7 +229,7 @@ tags: feature
|
||||
|
||||
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.
|
||||
necessary. This is about trying to get rid of them, i.e.
|
||||
deprecating them and checking with PyPy's usages as well
|
||||
as others.
|
||||
|
||||
@@ -298,7 +298,7 @@ tags: feature
|
||||
|
||||
The idea is that you can e.g. import modules in a test and afterwards
|
||||
sys.modules, sys.meta_path etc would be reverted. It can go further
|
||||
then just importing however, e.g. current working direcroty, file
|
||||
then just importing however, e.g. current working directory, file
|
||||
descriptors, ...
|
||||
|
||||
This would probably be done by marking::
|
||||
@@ -357,7 +357,7 @@ a few use-cases come to mind:
|
||||
id, call = prepare_check(check)
|
||||
# bubble should only prevent exception propagation after a failure
|
||||
# the whole test should still fail
|
||||
# there might be need for a loer level api and taking custom markers into account
|
||||
# there might be need for a lower level api and taking custom markers into account
|
||||
with pytest.section(id, bubble=False):
|
||||
call()
|
||||
|
||||
|
||||
25
Makefile
Normal file
25
Makefile
Normal file
@@ -0,0 +1,25 @@
|
||||
# Set of targets useful for development/release process
|
||||
PYTHON = python2.7
|
||||
PATH := $(PWD)/.env/bin:$(PATH)
|
||||
|
||||
# prepare virtual python environment
|
||||
.env:
|
||||
virtualenv .env -p $(PYTHON)
|
||||
|
||||
# install all needed for development
|
||||
develop: .env
|
||||
pip install -e . tox -r requirements-docs.txt
|
||||
|
||||
# clean the development envrironment
|
||||
clean:
|
||||
-rm -rf .env
|
||||
|
||||
# generate documentation
|
||||
docs: develop
|
||||
find doc/en -name '*.txt' -not -path 'doc/en/_build/*' | xargs .env/bin/regendoc
|
||||
cd doc/en; make html
|
||||
|
||||
# upload documentation
|
||||
upload-docs: develop
|
||||
find doc/en -name '*.txt' -not -path 'doc/en/_build/*' | xargs .env/bin/regendoc --update
|
||||
cd doc/en; make install
|
||||
14
README.rst
14
README.rst
@@ -1,15 +1,15 @@
|
||||
.. image:: https://drone.io/bitbucket.org/hpk42/pytest/status.png
|
||||
:target: https://drone.io/bitbucket.org/hpk42/pytest/latest
|
||||
.. image:: https://drone.io/bitbucket.org/pytest-dev/pytest/status.png
|
||||
:target: https://drone.io/bitbucket.org/pytest-dev/pytest/latest
|
||||
.. image:: https://pypip.in/v/pytest/badge.png
|
||||
:target: https://crate.io/packages/pytest/
|
||||
:target: https://pypi.python.org/pypi/pytest
|
||||
|
||||
Documentation: http://pytest.org/latest/
|
||||
|
||||
Changelog: http://pytest.org/latest/changelog.html
|
||||
|
||||
Issues: https://bitbucket.org/hpk42/pytest/issues?status=open
|
||||
Issues: https://bitbucket.org/pytest-dev/pytest/issues?status=open
|
||||
|
||||
CI: https://drone.io/bitbucket.org/hpk42/pytest
|
||||
CI: https://drone.io/bitbucket.org/pytest-dev/pytest
|
||||
|
||||
The ``pytest`` testing tool makes it easy to write small tests, yet
|
||||
scales to support complex functional testing. It provides
|
||||
@@ -44,11 +44,11 @@ For much more info, including PDF docs, see
|
||||
|
||||
and report bugs at:
|
||||
|
||||
http://bitbucket.org/hpk42/pytest/issues/
|
||||
http://bitbucket.org/pytest-dev/pytest/issues/
|
||||
|
||||
and checkout or fork repo at:
|
||||
|
||||
http://bitbucket.org/hpk42/pytest/
|
||||
http://bitbucket.org/pytest-dev/pytest/
|
||||
|
||||
|
||||
Copyright Holger Krekel and others, 2004-2014
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
#
|
||||
__version__ = '2.6.3'
|
||||
__version__ = '2.7.0'
|
||||
|
||||
@@ -122,7 +122,7 @@ class AssertionRewritingHook(object):
|
||||
# One of the path components was not a directory, likely
|
||||
# because we're in a zip file.
|
||||
write = False
|
||||
elif e == errno.EACCES:
|
||||
elif e in [errno.EACCES, errno.EROFS]:
|
||||
state.trace("read only directory: %r" % fn_pypath.dirname)
|
||||
write = False
|
||||
else:
|
||||
@@ -146,6 +146,12 @@ class AssertionRewritingHook(object):
|
||||
return self
|
||||
|
||||
def load_module(self, name):
|
||||
# If there is an existing module object named 'fullname' in
|
||||
# sys.modules, the loader must use that existing module. (Otherwise,
|
||||
# the reload() builtin will not work correctly.)
|
||||
if name in sys.modules:
|
||||
return sys.modules[name]
|
||||
|
||||
co, pyc = self.modules.pop(name)
|
||||
# I wish I could just call imp.load_compiled here, but __file__ has to
|
||||
# be set properly. In Python 3.2+, this all would be handled correctly
|
||||
@@ -373,7 +379,7 @@ def _format_assertmsg(obj):
|
||||
t = py.builtin.text
|
||||
else:
|
||||
t = py.builtin.bytes
|
||||
s = s.replace(t("\n"), t("\n~"))
|
||||
s = s.replace(t("\n"), t("\n~")).replace(t("%"), t("%%"))
|
||||
if is_repr:
|
||||
s = s.replace(t("\\n"), t("\n~"))
|
||||
return s
|
||||
@@ -382,7 +388,12 @@ def _should_repr_global_name(obj):
|
||||
return not hasattr(obj, "__name__") and not py.builtin.callable(obj)
|
||||
|
||||
def _format_boolop(explanations, is_or):
|
||||
return "(" + (is_or and " or " or " and ").join(explanations) + ")"
|
||||
explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
|
||||
if py.builtin._istext(explanation):
|
||||
t = py.builtin.text
|
||||
else:
|
||||
t = py.builtin.bytes
|
||||
return explanation.replace(t('%'), t('%%'))
|
||||
|
||||
def _call_reprcompare(ops, results, expls, each_obj):
|
||||
for i, res, expl in zip(range(len(ops)), results, expls):
|
||||
@@ -455,7 +466,7 @@ class AssertionRewriter(ast.NodeVisitor):
|
||||
for an overview of how this works.
|
||||
|
||||
The entry point here is .run() which will iterate over all the
|
||||
statenemts in an ast.Module and for each ast.Assert statement it
|
||||
statements in an ast.Module and for each ast.Assert statement it
|
||||
finds call .visit() with it. Then .visit_Assert() takes over and
|
||||
is responsible for creating new ast statements to replace the
|
||||
original assert statement: it re-writes the test of an assertion
|
||||
|
||||
@@ -135,18 +135,32 @@ def assertrepr_compare(config, op, left, right):
|
||||
isdict = lambda x: isinstance(x, dict)
|
||||
isset = lambda x: isinstance(x, (set, frozenset))
|
||||
|
||||
def isiterable(obj):
|
||||
try:
|
||||
iter(obj)
|
||||
return not istext(obj)
|
||||
except TypeError:
|
||||
return False
|
||||
|
||||
verbose = config.getoption('verbose')
|
||||
explanation = None
|
||||
try:
|
||||
if op == '==':
|
||||
if istext(left) and istext(right):
|
||||
explanation = _diff_text(left, right, verbose)
|
||||
elif issequence(left) and issequence(right):
|
||||
explanation = _compare_eq_sequence(left, right, verbose)
|
||||
elif isset(left) and isset(right):
|
||||
explanation = _compare_eq_set(left, right, verbose)
|
||||
elif isdict(left) and isdict(right):
|
||||
explanation = _compare_eq_dict(left, right, verbose)
|
||||
else:
|
||||
if issequence(left) and issequence(right):
|
||||
explanation = _compare_eq_sequence(left, right, verbose)
|
||||
elif isset(left) and isset(right):
|
||||
explanation = _compare_eq_set(left, right, verbose)
|
||||
elif isdict(left) and isdict(right):
|
||||
explanation = _compare_eq_dict(left, right, verbose)
|
||||
if isiterable(left) and isiterable(right):
|
||||
expl = _compare_eq_iterable(left, right, verbose)
|
||||
if explanation is not None:
|
||||
explanation.extend(expl)
|
||||
else:
|
||||
explanation = expl
|
||||
elif op == 'not in':
|
||||
if istext(left) and istext(right):
|
||||
explanation = _notin_text(left, right, verbose)
|
||||
@@ -203,6 +217,19 @@ def _diff_text(left, right, verbose=False):
|
||||
return explanation
|
||||
|
||||
|
||||
def _compare_eq_iterable(left, right, verbose=False):
|
||||
if not verbose:
|
||||
return [u('Use -v to get the full diff')]
|
||||
# dynamic import to speedup pytest
|
||||
import difflib
|
||||
|
||||
left = pprint.pformat(left).splitlines()
|
||||
right = pprint.pformat(right).splitlines()
|
||||
explanation = [u('Full diff:')]
|
||||
explanation.extend(line.strip() for line in difflib.ndiff(left, right))
|
||||
return explanation
|
||||
|
||||
|
||||
def _compare_eq_sequence(left, right, verbose=False):
|
||||
explanation = []
|
||||
for i in range(min(len(left), len(right))):
|
||||
|
||||
@@ -29,8 +29,8 @@ def pytest_addoption(parser):
|
||||
help="shortcut for --capture=no.")
|
||||
|
||||
|
||||
@pytest.mark.tryfirst
|
||||
def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_load_initial_conftests(early_config, parser, args):
|
||||
ns = early_config.known_args_namespace
|
||||
pluginmanager = early_config.pluginmanager
|
||||
capman = CaptureManager(ns.capture)
|
||||
@@ -47,15 +47,11 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
|
||||
|
||||
# finally trigger conftest loading but while capturing (issue93)
|
||||
capman.init_capturings()
|
||||
try:
|
||||
try:
|
||||
return __multicall__.execute()
|
||||
finally:
|
||||
out, err = capman.suspendcapture()
|
||||
except:
|
||||
outcome = yield
|
||||
out, err = capman.suspendcapture()
|
||||
if outcome.excinfo is not None:
|
||||
sys.stdout.write(out)
|
||||
sys.stderr.write(err)
|
||||
raise
|
||||
|
||||
|
||||
class CaptureManager:
|
||||
@@ -105,20 +101,19 @@ class CaptureManager:
|
||||
if capfuncarg is not None:
|
||||
capfuncarg.close()
|
||||
|
||||
@pytest.mark.tryfirst
|
||||
def pytest_make_collect_report(self, __multicall__, collector):
|
||||
if not isinstance(collector, pytest.File):
|
||||
return
|
||||
self.resumecapture()
|
||||
try:
|
||||
rep = __multicall__.execute()
|
||||
finally:
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_make_collect_report(self, collector):
|
||||
if isinstance(collector, pytest.File):
|
||||
self.resumecapture()
|
||||
outcome = yield
|
||||
out, err = self.suspendcapture()
|
||||
if out:
|
||||
rep.sections.append(("Captured stdout", out))
|
||||
if err:
|
||||
rep.sections.append(("Captured stderr", err))
|
||||
return rep
|
||||
rep = outcome.get_result()
|
||||
if out:
|
||||
rep.sections.append(("Captured stdout", out))
|
||||
if err:
|
||||
rep.sections.append(("Captured stderr", err))
|
||||
else:
|
||||
yield
|
||||
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_runtest_setup(self, item):
|
||||
|
||||
@@ -98,7 +98,7 @@ class PytestPluginManager(PluginManager):
|
||||
err = py.io.dupfile(err, encoding=encoding)
|
||||
except Exception:
|
||||
pass
|
||||
self.trace.root.setwriter(err.write)
|
||||
self.set_tracing(err.write)
|
||||
|
||||
def pytest_configure(self, config):
|
||||
config.addinivalue_line("markers",
|
||||
@@ -657,6 +657,12 @@ class Config(object):
|
||||
sys.stderr.write("INTERNALERROR> %s\n" %line)
|
||||
sys.stderr.flush()
|
||||
|
||||
def cwd_relative_nodeid(self, nodeid):
|
||||
# nodeid's are relative to the rootpath, compute relative to cwd
|
||||
if self.invocation_dir != self.rootdir:
|
||||
fullpath = self.rootdir.join(nodeid)
|
||||
nodeid = self.invocation_dir.bestrelpath(fullpath)
|
||||
return nodeid
|
||||
|
||||
@classmethod
|
||||
def fromdictargs(cls, option_dict, args):
|
||||
@@ -682,11 +688,8 @@ class Config(object):
|
||||
setattr(self.option, opt.dest, opt.default)
|
||||
|
||||
def _getmatchingplugins(self, fspath):
|
||||
allconftests = self._conftest._conftestpath2mod.values()
|
||||
plugins = [x for x in self.pluginmanager.getplugins()
|
||||
if x not in allconftests]
|
||||
plugins += self._conftest.getconftestmodules(fspath)
|
||||
return plugins
|
||||
return self.pluginmanager._plugins + \
|
||||
self._conftest.getconftestmodules(fspath)
|
||||
|
||||
def pytest_load_initial_conftests(self, early_config):
|
||||
self._conftest.setinitial(early_config.known_args_namespace)
|
||||
@@ -694,20 +697,16 @@ class Config(object):
|
||||
|
||||
def _initini(self, args):
|
||||
parsed_args = self._parser.parse_known_args(args)
|
||||
if parsed_args.inifilename:
|
||||
iniconfig = py.iniconfig.IniConfig(parsed_args.inifilename)
|
||||
if 'pytest' in iniconfig.sections:
|
||||
self.inicfg = iniconfig['pytest']
|
||||
else:
|
||||
self.inicfg = {}
|
||||
else:
|
||||
self.inicfg = getcfg(args, ["pytest.ini", "tox.ini", "setup.cfg"])
|
||||
r = determine_setup(parsed_args.inifilename, parsed_args.file_or_dir)
|
||||
self.rootdir, self.inifile, self.inicfg = r
|
||||
self.invocation_dir = py.path.local()
|
||||
self._parser.addini('addopts', 'extra command line options', 'args')
|
||||
self._parser.addini('minversion', 'minimally required pytest version')
|
||||
|
||||
def _preparse(self, args, addopts=True):
|
||||
self._initini(args)
|
||||
if addopts:
|
||||
args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
|
||||
args[:] = self.getini("addopts") + args
|
||||
self._checkversion()
|
||||
self.pluginmanager.consider_preparse(args)
|
||||
@@ -861,8 +860,58 @@ def getcfg(args, inibasenames):
|
||||
if exists(p):
|
||||
iniconfig = py.iniconfig.IniConfig(p)
|
||||
if 'pytest' in iniconfig.sections:
|
||||
return iniconfig['pytest']
|
||||
return {}
|
||||
return base, p, iniconfig['pytest']
|
||||
elif inibasename == "pytest.ini":
|
||||
# allowed to be empty
|
||||
return base, p, {}
|
||||
return None, None, None
|
||||
|
||||
|
||||
def get_common_ancestor(args):
|
||||
# args are what we get after early command line parsing (usually
|
||||
# strings, but can be py.path.local objects as well)
|
||||
common_ancestor = None
|
||||
for arg in args:
|
||||
if str(arg)[0] == "-":
|
||||
continue
|
||||
p = py.path.local(arg)
|
||||
if common_ancestor is None:
|
||||
common_ancestor = p
|
||||
else:
|
||||
if p.relto(common_ancestor) or p == common_ancestor:
|
||||
continue
|
||||
elif common_ancestor.relto(p):
|
||||
common_ancestor = p
|
||||
else:
|
||||
shared = p.common(common_ancestor)
|
||||
if shared is not None:
|
||||
common_ancestor = shared
|
||||
if common_ancestor is None:
|
||||
common_ancestor = py.path.local()
|
||||
elif not common_ancestor.isdir():
|
||||
common_ancestor = common_ancestor.dirpath()
|
||||
return common_ancestor
|
||||
|
||||
|
||||
def determine_setup(inifile, args):
|
||||
if inifile:
|
||||
iniconfig = py.iniconfig.IniConfig(inifile)
|
||||
try:
|
||||
inicfg = iniconfig["pytest"]
|
||||
except KeyError:
|
||||
inicfg = None
|
||||
rootdir = get_common_ancestor(args)
|
||||
else:
|
||||
ancestor = get_common_ancestor(args)
|
||||
rootdir, inifile, inicfg = getcfg(
|
||||
[ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
|
||||
if rootdir is None:
|
||||
for rootdir in ancestor.parts(reverse=True):
|
||||
if rootdir.join("setup.py").exists():
|
||||
break
|
||||
else:
|
||||
rootdir = ancestor
|
||||
return rootdir, inifile, inicfg or {}
|
||||
|
||||
|
||||
def setns(obj, dic):
|
||||
|
||||
325
_pytest/core.py
325
_pytest/core.py
@@ -10,6 +10,8 @@ import py
|
||||
assert py.__version__.split(".")[:2] >= ['1', '4'], ("installation problem: "
|
||||
"%s is too old, remove or upgrade 'py'" % (py.__version__))
|
||||
|
||||
py3 = sys.version_info > (3,0)
|
||||
|
||||
class TagTracer:
|
||||
def __init__(self):
|
||||
self._tag2proc = {}
|
||||
@@ -67,16 +69,104 @@ class TagTracerSub:
|
||||
def get(self, name):
|
||||
return self.__class__(self.root, self.tags + (name,))
|
||||
|
||||
|
||||
def add_method_wrapper(cls, wrapper_func):
|
||||
""" Substitute the function named "wrapperfunc.__name__" at class
|
||||
"cls" with a function that wraps the call to the original function.
|
||||
Return an undo function which can be called to reset the class to use
|
||||
the old method again.
|
||||
|
||||
wrapper_func is called with the same arguments as the method
|
||||
it wraps and its result is used as a wrap_controller for
|
||||
calling the original function.
|
||||
"""
|
||||
name = wrapper_func.__name__
|
||||
oldcall = getattr(cls, name)
|
||||
def wrap_exec(*args, **kwargs):
|
||||
gen = wrapper_func(*args, **kwargs)
|
||||
return wrapped_call(gen, lambda: oldcall(*args, **kwargs))
|
||||
|
||||
setattr(cls, name, wrap_exec)
|
||||
return lambda: setattr(cls, name, oldcall)
|
||||
|
||||
def raise_wrapfail(wrap_controller, msg):
|
||||
co = wrap_controller.gi_code
|
||||
raise RuntimeError("wrap_controller at %r %s:%d %s" %
|
||||
(co.co_name, co.co_filename, co.co_firstlineno, msg))
|
||||
|
||||
def wrapped_call(wrap_controller, func):
|
||||
""" Wrap calling to a function with a generator which needs to yield
|
||||
exactly once. The yield point will trigger calling the wrapped function
|
||||
and return its CallOutcome to the yield point. The generator then needs
|
||||
to finish (raise StopIteration) in order for the wrapped call to complete.
|
||||
"""
|
||||
try:
|
||||
next(wrap_controller) # first yield
|
||||
except StopIteration:
|
||||
raise_wrapfail(wrap_controller, "did not yield")
|
||||
call_outcome = CallOutcome(func)
|
||||
try:
|
||||
wrap_controller.send(call_outcome)
|
||||
raise_wrapfail(wrap_controller, "has second yield")
|
||||
except StopIteration:
|
||||
pass
|
||||
return call_outcome.get_result()
|
||||
|
||||
|
||||
class CallOutcome:
|
||||
""" Outcome of a function call, either an exception or a proper result.
|
||||
Calling the ``get_result`` method will return the result or reraise
|
||||
the exception raised when the function was called. """
|
||||
excinfo = None
|
||||
def __init__(self, func):
|
||||
try:
|
||||
self.result = func()
|
||||
except Exception:
|
||||
self.excinfo = sys.exc_info()
|
||||
|
||||
def force_result(self, result):
|
||||
self.result = result
|
||||
self.excinfo = None
|
||||
|
||||
def get_result(self):
|
||||
if self.excinfo is None:
|
||||
return self.result
|
||||
else:
|
||||
ex = self.excinfo
|
||||
if py3:
|
||||
raise ex[1].with_traceback(ex[2])
|
||||
py.builtin._reraise(*ex)
|
||||
|
||||
|
||||
class PluginManager(object):
|
||||
def __init__(self, hookspecs=None):
|
||||
def __init__(self, hookspecs=None, prefix="pytest_"):
|
||||
self._name2plugin = {}
|
||||
self._listattrcache = {}
|
||||
self._plugins = []
|
||||
self._conftestplugins = []
|
||||
self._plugin2hookcallers = {}
|
||||
self._warnings = []
|
||||
self.trace = TagTracer().get("pluginmanage")
|
||||
self._plugin_distinfo = []
|
||||
self._shutdown = []
|
||||
self.hook = HookRelay(hookspecs or [], pm=self)
|
||||
self.hook = HookRelay(hookspecs or [], pm=self, prefix=prefix)
|
||||
|
||||
def set_tracing(self, writer):
|
||||
self.trace.root.setwriter(writer)
|
||||
# reconfigure HookCalling to perform tracing
|
||||
assert not hasattr(self, "_wrapping")
|
||||
self._wrapping = True
|
||||
|
||||
def _docall(self, methods, kwargs):
|
||||
trace = self.hookrelay.trace
|
||||
trace.root.indent += 1
|
||||
trace(self.name, kwargs)
|
||||
box = yield
|
||||
if box.excinfo is None:
|
||||
trace("finish", self.name, "-->", box.result)
|
||||
trace.root.indent -= 1
|
||||
|
||||
undo = add_method_wrapper(HookCaller, _docall)
|
||||
self.add_shutdown(undo)
|
||||
|
||||
def do_configure(self, config):
|
||||
# backward compatibility
|
||||
@@ -86,7 +176,7 @@ class PluginManager(object):
|
||||
assert not hasattr(self, "_registercallback")
|
||||
self._registercallback = callback
|
||||
|
||||
def register(self, plugin, name=None, prepend=False):
|
||||
def register(self, plugin, name=None, prepend=False, conftest=False):
|
||||
if self._name2plugin.get(name, None) == -1:
|
||||
return
|
||||
name = name or getattr(plugin, '__name__', str(id(plugin)))
|
||||
@@ -94,23 +184,35 @@ class PluginManager(object):
|
||||
raise ValueError("Plugin already registered: %s=%s\n%s" %(
|
||||
name, plugin, self._name2plugin))
|
||||
#self.trace("registering", name, plugin)
|
||||
self._name2plugin[name] = plugin
|
||||
reg = getattr(self, "_registercallback", None)
|
||||
if reg is not None:
|
||||
reg(plugin, name)
|
||||
if not prepend:
|
||||
self._plugins.append(plugin)
|
||||
reg(plugin, name) # may call addhooks
|
||||
hookcallers = list(self.hook._scan_plugin(plugin))
|
||||
self._plugin2hookcallers[plugin] = hookcallers
|
||||
self._name2plugin[name] = plugin
|
||||
if conftest:
|
||||
self._conftestplugins.append(plugin)
|
||||
else:
|
||||
self._plugins.insert(0, plugin)
|
||||
if not prepend:
|
||||
self._plugins.append(plugin)
|
||||
else:
|
||||
self._plugins.insert(0, plugin)
|
||||
# finally make sure that the methods of the new plugin take part
|
||||
for hookcaller in hookcallers:
|
||||
hookcaller.scan_methods()
|
||||
return True
|
||||
|
||||
def unregister(self, plugin=None, name=None):
|
||||
if plugin is None:
|
||||
plugin = self.getplugin(name=name)
|
||||
self._plugins.remove(plugin)
|
||||
def unregister(self, plugin):
|
||||
try:
|
||||
self._plugins.remove(plugin)
|
||||
except KeyError:
|
||||
self._conftestplugins.remove(plugin)
|
||||
for name, value in list(self._name2plugin.items()):
|
||||
if value == plugin:
|
||||
del self._name2plugin[name]
|
||||
hookcallers = self._plugin2hookcallers.pop(plugin)
|
||||
for hookcaller in hookcallers:
|
||||
hookcaller.scan_methods()
|
||||
|
||||
def add_shutdown(self, func):
|
||||
self._shutdown.append(func)
|
||||
@@ -119,22 +221,19 @@ class PluginManager(object):
|
||||
while self._shutdown:
|
||||
func = self._shutdown.pop()
|
||||
func()
|
||||
self._plugins = []
|
||||
self._plugins = self._conftestplugins = []
|
||||
self._name2plugin.clear()
|
||||
self._listattrcache.clear()
|
||||
|
||||
def isregistered(self, plugin, name=None):
|
||||
if self.getplugin(name) is not None:
|
||||
return True
|
||||
for val in self._name2plugin.values():
|
||||
if plugin == val:
|
||||
return True
|
||||
return plugin in self._plugins or plugin in self._conftestplugins
|
||||
|
||||
def addhooks(self, spec, prefix="pytest_"):
|
||||
self.hook._addhooks(spec, prefix=prefix)
|
||||
|
||||
def getplugins(self):
|
||||
return list(self._plugins)
|
||||
return self._plugins + self._conftestplugins
|
||||
|
||||
def skipifmissing(self, name):
|
||||
if not self.hasplugin(name):
|
||||
@@ -190,15 +289,17 @@ class PluginManager(object):
|
||||
def consider_pluginarg(self, arg):
|
||||
if arg.startswith("no:"):
|
||||
name = arg[3:]
|
||||
if self.getplugin(name) is not None:
|
||||
self.unregister(None, name=name)
|
||||
plugin = self.getplugin(name)
|
||||
if plugin is not None:
|
||||
self.unregister(plugin)
|
||||
self._name2plugin[name] = -1
|
||||
else:
|
||||
if self.getplugin(arg) is None:
|
||||
self.import_plugin(arg)
|
||||
|
||||
def consider_conftest(self, conftestmodule):
|
||||
if self.register(conftestmodule, name=conftestmodule.__file__):
|
||||
if self.register(conftestmodule, name=conftestmodule.__file__,
|
||||
conftest=True):
|
||||
self.consider_module(conftestmodule)
|
||||
|
||||
def consider_module(self, mod):
|
||||
@@ -233,12 +334,7 @@ class PluginManager(object):
|
||||
|
||||
def listattr(self, attrname, plugins=None):
|
||||
if plugins is None:
|
||||
plugins = self._plugins
|
||||
key = (attrname,) + tuple(plugins)
|
||||
try:
|
||||
return list(self._listattrcache[key])
|
||||
except KeyError:
|
||||
pass
|
||||
plugins = self._plugins + self._conftestplugins
|
||||
l = []
|
||||
last = []
|
||||
wrappers = []
|
||||
@@ -257,7 +353,6 @@ class PluginManager(object):
|
||||
l.append(meth)
|
||||
l.extend(last)
|
||||
l.extend(wrappers)
|
||||
self._listattrcache[key] = list(l)
|
||||
return l
|
||||
|
||||
def call_plugin(self, plugin, methname, kwargs):
|
||||
@@ -278,16 +373,10 @@ def importplugin(importspec):
|
||||
class MultiCall:
|
||||
""" execute a call into multiple python functions/methods. """
|
||||
|
||||
class WrongHookWrapper(Exception):
|
||||
""" a hook wrapper does not behave correctly. """
|
||||
def __init__(self, func, message):
|
||||
Exception.__init__(self, func, message)
|
||||
self.func = func
|
||||
self.message = message
|
||||
|
||||
def __init__(self, methods, kwargs, firstresult=False):
|
||||
self.methods = list(methods)
|
||||
self.kwargs = kwargs
|
||||
self.kwargs["__multicall__"] = self
|
||||
self.results = []
|
||||
self.firstresult = firstresult
|
||||
|
||||
@@ -296,51 +385,22 @@ class MultiCall:
|
||||
return "<MultiCall %s, kwargs=%r>" %(status, self.kwargs)
|
||||
|
||||
def execute(self):
|
||||
next_finalizers = []
|
||||
try:
|
||||
while self.methods:
|
||||
method = self.methods.pop()
|
||||
kwargs = self.getkwargs(method)
|
||||
if hasattr(method, "hookwrapper"):
|
||||
it = method(**kwargs)
|
||||
next = getattr(it, "next", None)
|
||||
if next is None:
|
||||
next = getattr(it, "__next__", None)
|
||||
if next is None:
|
||||
raise self.WrongHookWrapper(method,
|
||||
"wrapper does not contain a yield")
|
||||
res = next()
|
||||
next_finalizers.append((method, next))
|
||||
else:
|
||||
res = method(**kwargs)
|
||||
if res is not None:
|
||||
self.results.append(res)
|
||||
if self.firstresult:
|
||||
return res
|
||||
if not self.firstresult:
|
||||
return self.results
|
||||
finally:
|
||||
for method, fin in reversed(next_finalizers):
|
||||
try:
|
||||
fin()
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
raise self.WrongHookWrapper(method,
|
||||
"wrapper contain more than one yield")
|
||||
all_kwargs = self.kwargs
|
||||
while self.methods:
|
||||
method = self.methods.pop()
|
||||
args = [all_kwargs[argname] for argname in varnames(method)]
|
||||
if hasattr(method, "hookwrapper"):
|
||||
return wrapped_call(method(*args), self.execute)
|
||||
res = method(*args)
|
||||
if res is not None:
|
||||
self.results.append(res)
|
||||
if self.firstresult:
|
||||
return res
|
||||
if not self.firstresult:
|
||||
return self.results
|
||||
|
||||
|
||||
def getkwargs(self, method):
|
||||
kwargs = {}
|
||||
for argname in varnames(method):
|
||||
try:
|
||||
kwargs[argname] = self.kwargs[argname]
|
||||
except KeyError:
|
||||
if argname == "__multicall__":
|
||||
kwargs[argname] = self
|
||||
return kwargs
|
||||
|
||||
def varnames(func):
|
||||
def varnames(func, startindex=None):
|
||||
""" return argument name tuple for a function, method, class or callable.
|
||||
|
||||
In case of a class, its "__init__" method is considered.
|
||||
@@ -357,74 +417,127 @@ def varnames(func):
|
||||
func = func.__init__
|
||||
except AttributeError:
|
||||
return ()
|
||||
ismethod = True
|
||||
startindex = 1
|
||||
else:
|
||||
if not inspect.isfunction(func) and not inspect.ismethod(func):
|
||||
func = getattr(func, '__call__', func)
|
||||
ismethod = inspect.ismethod(func)
|
||||
if startindex is None:
|
||||
startindex = int(inspect.ismethod(func))
|
||||
|
||||
rawcode = py.code.getrawcode(func)
|
||||
try:
|
||||
x = rawcode.co_varnames[ismethod:rawcode.co_argcount]
|
||||
x = rawcode.co_varnames[startindex:rawcode.co_argcount]
|
||||
except AttributeError:
|
||||
x = ()
|
||||
else:
|
||||
defaults = func.__defaults__
|
||||
if defaults:
|
||||
x = x[:-len(defaults)]
|
||||
try:
|
||||
cache["_varnames"] = x
|
||||
except TypeError:
|
||||
pass
|
||||
return x
|
||||
|
||||
|
||||
class HookRelay:
|
||||
def __init__(self, hookspecs, pm, prefix="pytest_"):
|
||||
if not isinstance(hookspecs, list):
|
||||
hookspecs = [hookspecs]
|
||||
self._hookspecs = []
|
||||
self._pm = pm
|
||||
self.trace = pm.trace.root.get("hook")
|
||||
self.prefix = prefix
|
||||
for hookspec in hookspecs:
|
||||
self._addhooks(hookspec, prefix)
|
||||
|
||||
def _addhooks(self, hookspecs, prefix):
|
||||
self._hookspecs.append(hookspecs)
|
||||
def _addhooks(self, hookspec, prefix):
|
||||
added = False
|
||||
for name, method in vars(hookspecs).items():
|
||||
isclass = int(inspect.isclass(hookspec))
|
||||
for name, method in vars(hookspec).items():
|
||||
if name.startswith(prefix):
|
||||
firstresult = getattr(method, 'firstresult', False)
|
||||
hc = HookCaller(self, name, firstresult=firstresult)
|
||||
hc = HookCaller(self, name, firstresult=firstresult,
|
||||
argnames=varnames(method, startindex=isclass))
|
||||
setattr(self, name, hc)
|
||||
added = True
|
||||
#print ("setting new hook", name)
|
||||
if not added:
|
||||
raise ValueError("did not find new %r hooks in %r" %(
|
||||
prefix, hookspecs,))
|
||||
prefix, hookspec,))
|
||||
|
||||
def _getcaller(self, name, plugins):
|
||||
caller = getattr(self, name)
|
||||
methods = self._pm.listattr(name, plugins=plugins)
|
||||
if methods:
|
||||
return caller.new_cached_caller(methods)
|
||||
return caller
|
||||
|
||||
def _scan_plugin(self, plugin):
|
||||
def fail(msg, *args):
|
||||
name = getattr(plugin, '__name__', plugin)
|
||||
raise PluginValidationError("plugin %r\n%s" %(name, msg % args))
|
||||
|
||||
for name in dir(plugin):
|
||||
if not name.startswith(self.prefix):
|
||||
continue
|
||||
hook = getattr(self, name, None)
|
||||
method = getattr(plugin, name)
|
||||
if hook is None:
|
||||
is_optional = getattr(method, 'optionalhook', False)
|
||||
if not isgenerichook(name) and not is_optional:
|
||||
fail("found unknown hook: %r", name)
|
||||
continue
|
||||
for arg in varnames(method):
|
||||
if arg not in hook.argnames:
|
||||
fail("argument %r not available\n"
|
||||
"actual definition: %s\n"
|
||||
"available hookargs: %s",
|
||||
arg, formatdef(method),
|
||||
", ".join(hook.argnames))
|
||||
yield hook
|
||||
|
||||
|
||||
class HookCaller:
|
||||
def __init__(self, hookrelay, name, firstresult):
|
||||
def __init__(self, hookrelay, name, firstresult, argnames, methods=()):
|
||||
self.hookrelay = hookrelay
|
||||
self.name = name
|
||||
self.firstresult = firstresult
|
||||
self.trace = self.hookrelay.trace
|
||||
self.argnames = ["__multicall__"]
|
||||
self.argnames.extend(argnames)
|
||||
assert "self" not in argnames # sanity check
|
||||
self.methods = methods
|
||||
|
||||
def new_cached_caller(self, methods):
|
||||
return HookCaller(self.hookrelay, self.name, self.firstresult,
|
||||
argnames=self.argnames, methods=methods)
|
||||
|
||||
def __repr__(self):
|
||||
return "<HookCaller %r>" %(self.name,)
|
||||
|
||||
def __call__(self, **kwargs):
|
||||
methods = self.hookrelay._pm.listattr(self.name)
|
||||
return self._docall(methods, kwargs)
|
||||
def scan_methods(self):
|
||||
self.methods = self.hookrelay._pm.listattr(self.name)
|
||||
|
||||
def pcall(self, plugins, **kwargs):
|
||||
methods = self.hookrelay._pm.listattr(self.name, plugins=plugins)
|
||||
return self._docall(methods, kwargs)
|
||||
def __call__(self, **kwargs):
|
||||
return self._docall(self.methods, kwargs)
|
||||
|
||||
def callextra(self, methods, **kwargs):
|
||||
return self._docall(self.methods + methods, kwargs)
|
||||
|
||||
def _docall(self, methods, kwargs):
|
||||
self.trace(self.name, kwargs)
|
||||
self.trace.root.indent += 1
|
||||
mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
|
||||
try:
|
||||
res = mc.execute()
|
||||
if res:
|
||||
self.trace("finish", self.name, "-->", res)
|
||||
finally:
|
||||
self.trace.root.indent -= 1
|
||||
return res
|
||||
return MultiCall(methods, kwargs,
|
||||
firstresult=self.firstresult).execute()
|
||||
|
||||
|
||||
class PluginValidationError(Exception):
|
||||
""" plugin failed validation. """
|
||||
|
||||
def isgenerichook(name):
|
||||
return name == "pytest_plugins" or \
|
||||
name.startswith("pytest_funcarg__")
|
||||
|
||||
def formatdef(func):
|
||||
return "%s%s" % (
|
||||
func.__name__,
|
||||
inspect.formatargspec(*inspect.getargspec(func))
|
||||
)
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ from _pytest.python import FixtureRequest, FuncFixtureInfo
|
||||
from py._code.code import TerminalRepr, ReprFileLocation
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addini('doctest_optionflags', 'option flags for doctests',
|
||||
type="args", default=["ELLIPSIS"])
|
||||
group = parser.getgroup("collect")
|
||||
group.addoption("--doctest-modules",
|
||||
action="store_true", default=False,
|
||||
@@ -15,6 +17,10 @@ def pytest_addoption(parser):
|
||||
action="store", default="test*.txt", metavar="pat",
|
||||
help="doctests file matching pattern, default: test*.txt",
|
||||
dest="doctestglob")
|
||||
group.addoption("--doctest-ignore-import-errors",
|
||||
action="store_true", default=False,
|
||||
help="ignore doctest ImportErrors",
|
||||
dest="doctest_ignore_import_errors")
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
config = parent.config
|
||||
@@ -87,6 +93,23 @@ class DoctestItem(pytest.Item):
|
||||
def reportinfo(self):
|
||||
return self.fspath, None, "[doctest] %s" % self.name
|
||||
|
||||
def _get_flag_lookup():
|
||||
import doctest
|
||||
return dict(DONT_ACCEPT_TRUE_FOR_1=doctest.DONT_ACCEPT_TRUE_FOR_1,
|
||||
DONT_ACCEPT_BLANKLINE=doctest.DONT_ACCEPT_BLANKLINE,
|
||||
NORMALIZE_WHITESPACE=doctest.NORMALIZE_WHITESPACE,
|
||||
ELLIPSIS=doctest.ELLIPSIS,
|
||||
IGNORE_EXCEPTION_DETAIL=doctest.IGNORE_EXCEPTION_DETAIL,
|
||||
COMPARISON_FLAGS=doctest.COMPARISON_FLAGS)
|
||||
|
||||
def get_optionflags(parent):
|
||||
optionflags_str = parent.config.getini("doctest_optionflags")
|
||||
flag_lookup_table = _get_flag_lookup()
|
||||
flag_acc = 0
|
||||
for flag in optionflags_str:
|
||||
flag_acc |= flag_lookup_table[flag]
|
||||
return flag_acc
|
||||
|
||||
class DoctestTextfile(DoctestItem, pytest.File):
|
||||
def runtest(self):
|
||||
import doctest
|
||||
@@ -101,7 +124,7 @@ class DoctestTextfile(DoctestItem, pytest.File):
|
||||
fixture_request._fillfixtures()
|
||||
failed, tot = doctest.testfile(
|
||||
str(self.fspath), module_relative=False,
|
||||
optionflags=doctest.ELLIPSIS,
|
||||
optionflags=get_optionflags(self),
|
||||
extraglobs=dict(getfixture=fixture_request.getfuncargvalue),
|
||||
raise_on_error=True, verbose=0)
|
||||
|
||||
@@ -111,7 +134,13 @@ class DoctestModule(pytest.File):
|
||||
if self.fspath.basename == "conftest.py":
|
||||
module = self.config._conftest.importconftest(self.fspath)
|
||||
else:
|
||||
module = self.fspath.pyimport()
|
||||
try:
|
||||
module = self.fspath.pyimport()
|
||||
except ImportError:
|
||||
if self.config.getvalue('doctest_ignore_import_errors'):
|
||||
pytest.skip('unable to import module %r' % self.fspath)
|
||||
else:
|
||||
raise
|
||||
# satisfy `FixtureRequest` constructor...
|
||||
self.funcargs = {}
|
||||
self._fixtureinfo = FuncFixtureInfo((), [], {})
|
||||
@@ -119,8 +148,9 @@ class DoctestModule(pytest.File):
|
||||
doctest_globals = dict(getfixture=fixture_request.getfuncargvalue)
|
||||
# uses internal doctest module parsing mechanism
|
||||
finder = doctest.DocTestFinder()
|
||||
runner = doctest.DebugRunner(verbose=0, optionflags=doctest.ELLIPSIS)
|
||||
optionflags = get_optionflags(self)
|
||||
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags)
|
||||
for test in finder.find(module, module.__name__,
|
||||
extraglobs=doctest_globals):
|
||||
if test.examples: # skip empty doctests
|
||||
if test.examples: # skip empty doctests
|
||||
yield DoctestItem(test.name, self, runner, test)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
""" version info, help messages, tracing configuration. """
|
||||
import py
|
||||
import pytest
|
||||
import os, inspect, sys
|
||||
from _pytest.core import varnames
|
||||
import os, sys
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup('debugconfig')
|
||||
@@ -23,18 +22,21 @@ def pytest_addoption(parser):
|
||||
help="store internal tracing debug information in 'pytestdebug.log'.")
|
||||
|
||||
|
||||
def pytest_cmdline_parse(__multicall__):
|
||||
config = __multicall__.execute()
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_cmdline_parse():
|
||||
outcome = yield
|
||||
config = outcome.get_result()
|
||||
if config.option.debug:
|
||||
path = os.path.abspath("pytestdebug.log")
|
||||
f = open(path, 'w')
|
||||
config._debugfile = f
|
||||
f.write("versions pytest-%s, py-%s, python-%s\ncwd=%s\nargs=%s\n\n" %(
|
||||
pytest.__version__, py.__version__, ".".join(map(str, sys.version_info)),
|
||||
f.write("versions pytest-%s, py-%s, "
|
||||
"python-%s\ncwd=%s\nargs=%s\n\n" %(
|
||||
pytest.__version__, py.__version__,
|
||||
".".join(map(str, sys.version_info)),
|
||||
os.getcwd(), config._origargs))
|
||||
config.trace.root.setwriter(f.write)
|
||||
config.pluginmanager.set_tracing(f.write)
|
||||
sys.stderr.write("writing pytestdebug information to %s\n" % path)
|
||||
return config
|
||||
|
||||
@pytest.mark.trylast
|
||||
def pytest_unconfigure(config):
|
||||
@@ -127,70 +129,3 @@ def pytest_report_header(config):
|
||||
return lines
|
||||
|
||||
|
||||
# =====================================================
|
||||
# validate plugin syntax and hooks
|
||||
# =====================================================
|
||||
|
||||
def pytest_plugin_registered(manager, plugin):
|
||||
methods = collectattr(plugin)
|
||||
hooks = {}
|
||||
for hookspec in manager.hook._hookspecs:
|
||||
hooks.update(collectattr(hookspec))
|
||||
|
||||
stringio = py.io.TextIO()
|
||||
def Print(*args):
|
||||
if args:
|
||||
stringio.write(" ".join(map(str, args)))
|
||||
stringio.write("\n")
|
||||
|
||||
fail = False
|
||||
while methods:
|
||||
name, method = methods.popitem()
|
||||
#print "checking", name
|
||||
if isgenerichook(name):
|
||||
continue
|
||||
if name not in hooks:
|
||||
if not getattr(method, 'optionalhook', False):
|
||||
Print("found unknown hook:", name)
|
||||
fail = True
|
||||
else:
|
||||
#print "checking", method
|
||||
method_args = list(varnames(method))
|
||||
if '__multicall__' in method_args:
|
||||
method_args.remove('__multicall__')
|
||||
hook = hooks[name]
|
||||
hookargs = varnames(hook)
|
||||
for arg in method_args:
|
||||
if arg not in hookargs:
|
||||
Print("argument %r not available" %(arg, ))
|
||||
Print("actual definition: %s" %(formatdef(method)))
|
||||
Print("available hook arguments: %s" %
|
||||
", ".join(hookargs))
|
||||
fail = True
|
||||
break
|
||||
#if not fail:
|
||||
# print "matching hook:", formatdef(method)
|
||||
if fail:
|
||||
name = getattr(plugin, '__name__', plugin)
|
||||
raise PluginValidationError("%s:\n%s" % (name, stringio.getvalue()))
|
||||
|
||||
class PluginValidationError(Exception):
|
||||
""" plugin failed validation. """
|
||||
|
||||
def isgenerichook(name):
|
||||
return name == "pytest_plugins" or \
|
||||
name.startswith("pytest_funcarg__")
|
||||
|
||||
def collectattr(obj):
|
||||
methods = {}
|
||||
for apiname in dir(obj):
|
||||
if apiname.startswith("pytest_"):
|
||||
methods[apiname] = getattr(obj, apiname)
|
||||
return methods
|
||||
|
||||
def formatdef(func):
|
||||
return "%s%s" % (
|
||||
func.__name__,
|
||||
inspect.formatargspec(*inspect.getargspec(func))
|
||||
)
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ def pytest_generate_tests(metafunc):
|
||||
# -------------------------------------------------------------------------
|
||||
# generic runtest related hooks
|
||||
# -------------------------------------------------------------------------
|
||||
def pytest_itemstart(item, node=None):
|
||||
def pytest_itemstart(item, node):
|
||||
""" (deprecated, use pytest_runtest_logstart). """
|
||||
|
||||
def pytest_runtest_protocol(item, nextitem):
|
||||
|
||||
@@ -123,7 +123,12 @@ class LogXML(object):
|
||||
Junit.skipped(message="xfail-marked test passes unexpectedly"))
|
||||
self.skipped += 1
|
||||
else:
|
||||
fail = Junit.failure(message="test failure")
|
||||
if isinstance(report.longrepr, (unicode, str)):
|
||||
message = report.longrepr
|
||||
else:
|
||||
message = report.longrepr.reprcrash.message
|
||||
message = bin_xml_escape(message)
|
||||
fail = Junit.failure(message=message)
|
||||
fail.append(bin_xml_escape(report.longrepr))
|
||||
self.append(fail)
|
||||
self.failed += 1
|
||||
|
||||
@@ -24,7 +24,7 @@ name_re = re.compile("^[a-zA-Z_]\w*$")
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addini("norecursedirs", "directory patterns to avoid for recursion",
|
||||
type="args", default=('.*', 'CVS', '_darcs', '{arch}', '*.egg'))
|
||||
type="args", default=['.*', 'CVS', '_darcs', '{arch}', '*.egg'])
|
||||
#parser.addini("dirpatterns",
|
||||
# "patterns specifying possible locations of test files",
|
||||
# type="linelist", default=["**/test_*.txt",
|
||||
@@ -153,19 +153,17 @@ def pytest_ignore_collect(path, config):
|
||||
ignore_paths.extend([py.path.local(x) for x in excludeopt])
|
||||
return path in ignore_paths
|
||||
|
||||
class HookProxy(object):
|
||||
class FSHookProxy(object):
|
||||
def __init__(self, fspath, config):
|
||||
self.fspath = fspath
|
||||
self.config = config
|
||||
|
||||
def __getattr__(self, name):
|
||||
config = object.__getattribute__(self, "config")
|
||||
hookmethod = getattr(config.hook, name)
|
||||
plugins = self.config._getmatchingplugins(self.fspath)
|
||||
x = self.config.hook._getcaller(name, plugins)
|
||||
self.__dict__[name] = x
|
||||
return x
|
||||
|
||||
def call_matching_hooks(**kwargs):
|
||||
plugins = self.config._getmatchingplugins(self.fspath)
|
||||
return hookmethod.pcall(plugins, **kwargs)
|
||||
return call_matching_hooks
|
||||
|
||||
def compatproperty(name):
|
||||
def fget(self):
|
||||
@@ -459,9 +457,7 @@ class FSCollector(Collector):
|
||||
self.fspath = fspath
|
||||
|
||||
def _makeid(self):
|
||||
if self == self.session:
|
||||
return "."
|
||||
relpath = self.session.fspath.bestrelpath(self.fspath)
|
||||
relpath = self.fspath.relto(self.config.rootdir)
|
||||
if os.sep != "/":
|
||||
relpath = relpath.replace(os.sep, "/")
|
||||
return relpath
|
||||
@@ -512,7 +508,7 @@ class Session(FSCollector):
|
||||
__module__ = 'builtins' # for py3
|
||||
|
||||
def __init__(self, config):
|
||||
FSCollector.__init__(self, py.path.local(), parent=None,
|
||||
FSCollector.__init__(self, config.rootdir, parent=None,
|
||||
config=config, session=self)
|
||||
self.config.pluginmanager.register(self, name="session", prepend=True)
|
||||
self._testsfailed = 0
|
||||
@@ -520,6 +516,10 @@ class Session(FSCollector):
|
||||
self.trace = config.trace.root.get("collection")
|
||||
self._norecursepatterns = config.getini("norecursedirs")
|
||||
self.startdir = py.path.local()
|
||||
self._fs2hookproxy = {}
|
||||
|
||||
def _makeid(self):
|
||||
return ""
|
||||
|
||||
def pytest_collectstart(self):
|
||||
if self.shouldstop:
|
||||
@@ -538,7 +538,11 @@ class Session(FSCollector):
|
||||
return path in self._initialpaths
|
||||
|
||||
def gethookproxy(self, fspath):
|
||||
return HookProxy(fspath, self.config)
|
||||
try:
|
||||
return self._fs2hookproxy[fspath]
|
||||
except KeyError:
|
||||
self._fs2hookproxy[fspath] = x = FSHookProxy(fspath, self.config)
|
||||
return x
|
||||
|
||||
def perform_collect(self, args=None, genitems=True):
|
||||
hook = self.config.hook
|
||||
@@ -660,7 +664,7 @@ class Session(FSCollector):
|
||||
arg = self._tryconvertpyarg(arg)
|
||||
parts = str(arg).split("::")
|
||||
relpath = parts[0].replace("/", os.sep)
|
||||
path = self.fspath.join(relpath, abs=True)
|
||||
path = self.config.invocation_dir.join(relpath, abs=True)
|
||||
if not path.check():
|
||||
if self.config.option.pyargs:
|
||||
msg = "file or package not found: "
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import py
|
||||
|
||||
|
||||
class MarkerError(Exception):
|
||||
|
||||
"""Error in use of a pytest marker/attribute."""
|
||||
|
||||
|
||||
def pytest_namespace():
|
||||
return {'mark': MarkGenerator()}
|
||||
|
||||
@@ -56,6 +61,11 @@ def pytest_collection_modifyitems(items, config):
|
||||
matchexpr = config.option.markexpr
|
||||
if not keywordexpr and not matchexpr:
|
||||
return
|
||||
# pytest used to allow "-" for negating
|
||||
# but today we just allow "-" at the beginning, use "not" instead
|
||||
# we probably remove "-" alltogether soon
|
||||
if keywordexpr.startswith("-"):
|
||||
keywordexpr = "not " + keywordexpr[1:]
|
||||
selectuntil = False
|
||||
if keywordexpr[-1:] == ":":
|
||||
selectuntil = True
|
||||
@@ -122,7 +132,6 @@ def matchkeyword(colitem, keywordexpr):
|
||||
Additionally, matches on names in the 'extra_keyword_matches' set of
|
||||
any item, as well as names directly assigned to test functions.
|
||||
"""
|
||||
keywordexpr = keywordexpr.replace("-", "not ")
|
||||
mapped_names = set()
|
||||
|
||||
# Add the names of the current item and any parent items
|
||||
|
||||
@@ -66,14 +66,14 @@ class Notset:
|
||||
notset = Notset()
|
||||
|
||||
class monkeypatch:
|
||||
""" object keeping a record of setattr/item/env/syspath changes. """
|
||||
""" Object keeping a record of setattr/item/env/syspath changes. """
|
||||
def __init__(self):
|
||||
self._setattr = []
|
||||
self._setitem = []
|
||||
self._cwd = None
|
||||
|
||||
def setattr(self, target, name, value=notset, raising=True):
|
||||
""" set attribute value on target, memorizing the old value.
|
||||
""" Set attribute value on target, memorizing the old value.
|
||||
By default raise AttributeError if the attribute did not exist.
|
||||
|
||||
For convenience you can specify a string as ``target`` which
|
||||
@@ -108,15 +108,15 @@ class monkeypatch:
|
||||
setattr(target, name, value)
|
||||
|
||||
def delattr(self, target, name=notset, raising=True):
|
||||
""" delete attribute ``name`` from ``target``, by default raise
|
||||
""" Delete attribute ``name`` from ``target``, by default raise
|
||||
AttributeError it the attribute did not previously exist.
|
||||
|
||||
If no ``name`` is specified and ``target`` is a string
|
||||
it will be interpreted as a dotted import path with the
|
||||
last part being the attribute name.
|
||||
|
||||
If raising is set to false, the attribute is allowed to not
|
||||
pre-exist.
|
||||
If ``raising`` is set to False, no exception will be raised if the
|
||||
attribute is missing.
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
if name is notset:
|
||||
@@ -135,12 +135,16 @@ class monkeypatch:
|
||||
delattr(target, name)
|
||||
|
||||
def setitem(self, dic, name, value):
|
||||
""" set dictionary entry ``name`` to value. """
|
||||
""" Set dictionary entry ``name`` to value. """
|
||||
self._setitem.insert(0, (dic, name, dic.get(name, notset)))
|
||||
dic[name] = value
|
||||
|
||||
def delitem(self, dic, name, raising=True):
|
||||
""" delete ``name`` from dict, raise KeyError if it doesn't exist."""
|
||||
""" Delete ``name`` from dict. Raise KeyError if it doesn't exist.
|
||||
|
||||
If ``raising`` is set to False, no exception will be raised if the
|
||||
key is missing.
|
||||
"""
|
||||
if name not in dic:
|
||||
if raising:
|
||||
raise KeyError(name)
|
||||
@@ -149,7 +153,7 @@ class monkeypatch:
|
||||
del dic[name]
|
||||
|
||||
def setenv(self, name, value, prepend=None):
|
||||
""" set environment variable ``name`` to ``value``. if ``prepend``
|
||||
""" Set environment variable ``name`` to ``value``. If ``prepend``
|
||||
is a character, read the current environment variable value
|
||||
and prepend the ``value`` adjoined with the ``prepend`` character."""
|
||||
value = str(value)
|
||||
@@ -158,17 +162,22 @@ class monkeypatch:
|
||||
self.setitem(os.environ, name, value)
|
||||
|
||||
def delenv(self, name, raising=True):
|
||||
""" delete ``name`` from environment, raise KeyError it not exists."""
|
||||
""" Delete ``name`` from the environment. Raise KeyError it does not
|
||||
exist.
|
||||
|
||||
If ``raising`` is set to False, no exception will be raised if the
|
||||
environment variable is missing.
|
||||
"""
|
||||
self.delitem(os.environ, name, raising=raising)
|
||||
|
||||
def syspath_prepend(self, path):
|
||||
""" prepend ``path`` to ``sys.path`` list of import locations. """
|
||||
""" Prepend ``path`` to ``sys.path`` list of import locations. """
|
||||
if not hasattr(self, '_savesyspath'):
|
||||
self._savesyspath = sys.path[:]
|
||||
sys.path.insert(0, str(path))
|
||||
|
||||
def chdir(self, path):
|
||||
""" change the current working directory to the specified path
|
||||
""" Change the current working directory to the specified path
|
||||
path can be a string or a py.path.local object
|
||||
"""
|
||||
if self._cwd is None:
|
||||
@@ -179,9 +188,9 @@ class monkeypatch:
|
||||
os.chdir(path)
|
||||
|
||||
def undo(self):
|
||||
""" undo previous changes. This call consumes the
|
||||
undo stack. Calling it a second time has no effect unless
|
||||
you do more monkeypatching after the undo call."""
|
||||
""" Undo previous changes. This call consumes the
|
||||
undo stack. Calling it a second time has no effect unless
|
||||
you do more monkeypatching after the undo call."""
|
||||
for obj, name, value in self._setattr:
|
||||
if value is not notset:
|
||||
setattr(obj, name, value)
|
||||
|
||||
@@ -16,7 +16,7 @@ def get_skip_exceptions():
|
||||
return tuple(skip_classes)
|
||||
|
||||
|
||||
def pytest_runtest_makereport(__multicall__, item, call):
|
||||
def pytest_runtest_makereport(item, call):
|
||||
if call.excinfo and call.excinfo.errisinstance(get_skip_exceptions()):
|
||||
# let's substitute the excinfo with a pytest.skip one
|
||||
call2 = call.__class__(lambda:
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
""" submit failure or test session information to a pastebin service. """
|
||||
import pytest
|
||||
import py, sys
|
||||
import tempfile
|
||||
|
||||
class url:
|
||||
base = "http://bpaste.net"
|
||||
xmlrpc = base + "/xmlrpc/"
|
||||
show = base + "/show/"
|
||||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("terminal reporting")
|
||||
@@ -13,36 +11,62 @@ def pytest_addoption(parser):
|
||||
choices=['failed', 'all'],
|
||||
help="send failed|all info to bpaste.net pastebin service.")
|
||||
|
||||
def pytest_configure(__multicall__, config):
|
||||
import tempfile
|
||||
__multicall__.execute()
|
||||
@pytest.mark.trylast
|
||||
def pytest_configure(config):
|
||||
if config.option.pastebin == "all":
|
||||
config._pastebinfile = tempfile.TemporaryFile('w+')
|
||||
tr = config.pluginmanager.getplugin('terminalreporter')
|
||||
oldwrite = tr._tw.write
|
||||
def tee_write(s, **kwargs):
|
||||
oldwrite(s, **kwargs)
|
||||
config._pastebinfile.write(str(s))
|
||||
tr._tw.write = tee_write
|
||||
# if no terminal reporter plugin is present, nothing we can do here;
|
||||
# this can happen when this function executes in a slave node
|
||||
# when using pytest-xdist, for example
|
||||
if tr is not None:
|
||||
config._pastebinfile = tempfile.TemporaryFile('w+')
|
||||
oldwrite = tr._tw.write
|
||||
def tee_write(s, **kwargs):
|
||||
oldwrite(s, **kwargs)
|
||||
config._pastebinfile.write(str(s))
|
||||
tr._tw.write = tee_write
|
||||
|
||||
def pytest_unconfigure(config):
|
||||
if hasattr(config, '_pastebinfile'):
|
||||
# get terminal contents and delete file
|
||||
config._pastebinfile.seek(0)
|
||||
sessionlog = config._pastebinfile.read()
|
||||
config._pastebinfile.close()
|
||||
del config._pastebinfile
|
||||
proxyid = getproxy().newPaste("python", sessionlog)
|
||||
pastebinurl = "%s%s" % (url.show, proxyid)
|
||||
sys.stderr.write("pastebin session-log: %s\n" % pastebinurl)
|
||||
# undo our patching in the terminal reporter
|
||||
tr = config.pluginmanager.getplugin('terminalreporter')
|
||||
del tr._tw.__dict__['write']
|
||||
# write summary
|
||||
tr.write_sep("=", "Sending information to Paste Service")
|
||||
pastebinurl = create_new_paste(sessionlog)
|
||||
tr.write_line("pastebin session-log: %s\n" % pastebinurl)
|
||||
|
||||
def getproxy():
|
||||
def create_new_paste(contents):
|
||||
"""
|
||||
Creates a new paste using bpaste.net service.
|
||||
|
||||
:contents: paste contents
|
||||
:returns: url to the pasted contents
|
||||
"""
|
||||
import re
|
||||
if sys.version_info < (3, 0):
|
||||
from xmlrpclib import ServerProxy
|
||||
from urllib import urlopen, urlencode
|
||||
else:
|
||||
from xmlrpc.client import ServerProxy
|
||||
return ServerProxy(url.xmlrpc).pastes
|
||||
from urllib.request import urlopen
|
||||
from urllib.parse import urlencode
|
||||
|
||||
params = {
|
||||
'code': contents,
|
||||
'lexer': 'python3' if sys.version_info[0] == 3 else 'python',
|
||||
'expiry': '1week',
|
||||
}
|
||||
url = 'https://bpaste.net'
|
||||
response = urlopen(url, data=urlencode(params)).read()
|
||||
m = re.search(r'href="/raw/(\w+)"', response)
|
||||
if m:
|
||||
return '%s/show/%s' % (url, m.group(1))
|
||||
else:
|
||||
return 'bad response: ' + response
|
||||
|
||||
def pytest_terminal_summary(terminalreporter):
|
||||
if terminalreporter.config.option.pastebin != "failed":
|
||||
@@ -50,9 +74,6 @@ def pytest_terminal_summary(terminalreporter):
|
||||
tr = terminalreporter
|
||||
if 'failed' in tr.stats:
|
||||
terminalreporter.write_sep("=", "Sending information to Paste Service")
|
||||
if tr.config.option.debug:
|
||||
terminalreporter.write_line("xmlrpcurl: %s" %(url.xmlrpc,))
|
||||
serverproxy = getproxy()
|
||||
for rep in terminalreporter.stats.get('failed'):
|
||||
try:
|
||||
msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc
|
||||
@@ -62,6 +83,5 @@ def pytest_terminal_summary(terminalreporter):
|
||||
rep.toterminal(tw)
|
||||
s = tw.stringio.getvalue()
|
||||
assert len(s)
|
||||
proxyid = serverproxy.newPaste("python", s)
|
||||
pastebinurl = "%s%s" % (url.show, proxyid)
|
||||
pastebinurl = create_new_paste(s)
|
||||
tr.write_line("%s --> %s" %(msg, pastebinurl))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
""" (disabled by default) support for testing pytest and pytest plugins. """
|
||||
import inspect
|
||||
import sys
|
||||
import os
|
||||
import codecs
|
||||
@@ -12,7 +11,7 @@ import subprocess
|
||||
import py
|
||||
import pytest
|
||||
from py.builtin import print_
|
||||
from _pytest.core import HookRelay
|
||||
from _pytest.core import HookCaller, add_method_wrapper
|
||||
|
||||
from _pytest.main import Session, EXIT_OK
|
||||
|
||||
@@ -38,24 +37,10 @@ def pytest_configure(config):
|
||||
_pytest_fullpath = os.path.abspath(pytest.__file__.rstrip("oc"))
|
||||
_pytest_fullpath = _pytest_fullpath.replace("$py.class", ".py")
|
||||
|
||||
def pytest_funcarg___pytest(request):
|
||||
return PytestArg(request)
|
||||
|
||||
class PytestArg:
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
|
||||
def gethookrecorder(self, hook):
|
||||
hookrecorder = HookRecorder(hook._pm)
|
||||
hookrecorder.start_recording(hook._hookspecs)
|
||||
self.request.addfinalizer(hookrecorder.finish_recording)
|
||||
return hookrecorder
|
||||
|
||||
class ParsedCall:
|
||||
def __init__(self, name, locals):
|
||||
assert '_name' not in locals
|
||||
self.__dict__.update(locals)
|
||||
self.__dict__.pop('self')
|
||||
def __init__(self, name, kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
self._name = name
|
||||
|
||||
def __repr__(self):
|
||||
@@ -63,68 +48,27 @@ class ParsedCall:
|
||||
del d['_name']
|
||||
return "<ParsedCall %r(**%r)>" %(self._name, d)
|
||||
|
||||
|
||||
class HookRecorder:
|
||||
def __init__(self, pluginmanager):
|
||||
self._pluginmanager = pluginmanager
|
||||
self.calls = []
|
||||
self._recorders = {}
|
||||
|
||||
def start_recording(self, hookspecs):
|
||||
if not isinstance(hookspecs, (list, tuple)):
|
||||
hookspecs = [hookspecs]
|
||||
for hookspec in hookspecs:
|
||||
assert hookspec not in self._recorders
|
||||
class RecordCalls:
|
||||
_recorder = self
|
||||
for name, method in vars(hookspec).items():
|
||||
if name[0] != "_":
|
||||
setattr(RecordCalls, name, self._makecallparser(method))
|
||||
recorder = RecordCalls()
|
||||
self._recorders[hookspec] = recorder
|
||||
self._pluginmanager.register(recorder)
|
||||
self.hook = HookRelay(hookspecs, pm=self._pluginmanager,
|
||||
prefix="pytest_")
|
||||
def _docall(hookcaller, methods, kwargs):
|
||||
self.calls.append(ParsedCall(hookcaller.name, kwargs))
|
||||
yield
|
||||
self._undo_wrapping = add_method_wrapper(HookCaller, _docall)
|
||||
pluginmanager.add_shutdown(self._undo_wrapping)
|
||||
|
||||
def finish_recording(self):
|
||||
for recorder in self._recorders.values():
|
||||
if self._pluginmanager.isregistered(recorder):
|
||||
self._pluginmanager.unregister(recorder)
|
||||
self._recorders.clear()
|
||||
|
||||
def _makecallparser(self, method):
|
||||
name = method.__name__
|
||||
args, varargs, varkw, default = inspect.getargspec(method)
|
||||
if not args or args[0] != "self":
|
||||
args.insert(0, 'self')
|
||||
fspec = inspect.formatargspec(args, varargs, varkw, default)
|
||||
# we use exec because we want to have early type
|
||||
# errors on wrong input arguments, using
|
||||
# *args/**kwargs delays this and gives errors
|
||||
# elsewhere
|
||||
exec (py.code.compile("""
|
||||
def %(name)s%(fspec)s:
|
||||
self._recorder.calls.append(
|
||||
ParsedCall(%(name)r, locals()))
|
||||
""" % locals()))
|
||||
return locals()[name]
|
||||
self._undo_wrapping()
|
||||
|
||||
def getcalls(self, names):
|
||||
if isinstance(names, str):
|
||||
names = names.split()
|
||||
for name in names:
|
||||
for cls in self._recorders:
|
||||
if name in vars(cls):
|
||||
break
|
||||
else:
|
||||
raise ValueError("callname %r not found in %r" %(
|
||||
name, self._recorders.keys()))
|
||||
l = []
|
||||
for call in self.calls:
|
||||
if call._name in names:
|
||||
l.append(call)
|
||||
return l
|
||||
return [call for call in self.calls if call._name in names]
|
||||
|
||||
def contains(self, entries):
|
||||
def assert_contains(self, entries):
|
||||
__tracebackhide__ = True
|
||||
i = 0
|
||||
entries = list(entries)
|
||||
@@ -160,6 +104,69 @@ class HookRecorder:
|
||||
assert len(l) == 1, (name, l)
|
||||
return l[0]
|
||||
|
||||
# functionality for test reports
|
||||
|
||||
def getreports(self,
|
||||
names="pytest_runtest_logreport pytest_collectreport"):
|
||||
return [x.report for x in self.getcalls(names)]
|
||||
|
||||
def matchreport(self, inamepart="",
|
||||
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
||||
""" return a testreport whose dotted import path matches """
|
||||
l = []
|
||||
for rep in self.getreports(names=names):
|
||||
try:
|
||||
if not when and rep.when != "call" and rep.passed:
|
||||
# setup/teardown passing reports - let's ignore those
|
||||
continue
|
||||
except AttributeError:
|
||||
pass
|
||||
if when and getattr(rep, 'when', None) != when:
|
||||
continue
|
||||
if not inamepart or inamepart in rep.nodeid.split("::"):
|
||||
l.append(rep)
|
||||
if not l:
|
||||
raise ValueError("could not find test report matching %r: "
|
||||
"no test reports at all!" % (inamepart,))
|
||||
if len(l) > 1:
|
||||
raise ValueError(
|
||||
"found 2 or more testreports matching %r: %s" %(inamepart, l))
|
||||
return l[0]
|
||||
|
||||
def getfailures(self,
|
||||
names='pytest_runtest_logreport pytest_collectreport'):
|
||||
return [rep for rep in self.getreports(names) if rep.failed]
|
||||
|
||||
def getfailedcollections(self):
|
||||
return self.getfailures('pytest_collectreport')
|
||||
|
||||
def listoutcomes(self):
|
||||
passed = []
|
||||
skipped = []
|
||||
failed = []
|
||||
for rep in self.getreports(
|
||||
"pytest_collectreport pytest_runtest_logreport"):
|
||||
if rep.passed:
|
||||
if getattr(rep, "when", None) == "call":
|
||||
passed.append(rep)
|
||||
elif rep.skipped:
|
||||
skipped.append(rep)
|
||||
elif rep.failed:
|
||||
failed.append(rep)
|
||||
return passed, skipped, failed
|
||||
|
||||
def countoutcomes(self):
|
||||
return [len(x) for x in self.listoutcomes()]
|
||||
|
||||
def assertoutcome(self, passed=0, skipped=0, failed=0):
|
||||
realpassed, realskipped, realfailed = self.listoutcomes()
|
||||
assert passed == len(realpassed)
|
||||
assert skipped == len(realskipped)
|
||||
assert failed == len(realfailed)
|
||||
|
||||
def clear(self):
|
||||
self.calls[:] = []
|
||||
|
||||
|
||||
def pytest_funcarg__linecomp(request):
|
||||
return LineComp()
|
||||
@@ -195,7 +202,6 @@ class TmpTestdir:
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
self.Config = request.config.__class__
|
||||
self._pytest = request.getfuncargvalue("_pytest")
|
||||
# XXX remove duplication with tmpdir plugin
|
||||
basetmp = request.config._tmpdirhandler.ensuretemp("testdir")
|
||||
name = request.function.__name__
|
||||
@@ -226,15 +232,10 @@ class TmpTestdir:
|
||||
if fn and fn.startswith(str(self.tmpdir)):
|
||||
del sys.modules[name]
|
||||
|
||||
def getreportrecorder(self, obj):
|
||||
if hasattr(obj, 'config'):
|
||||
obj = obj.config
|
||||
if hasattr(obj, 'hook'):
|
||||
obj = obj.hook
|
||||
assert hasattr(obj, '_hookspecs'), obj
|
||||
reprec = ReportRecorder(obj)
|
||||
reprec.hookrecorder = self._pytest.gethookrecorder(obj)
|
||||
reprec.hook = reprec.hookrecorder.hook
|
||||
def make_hook_recorder(self, pluginmanager):
|
||||
assert not hasattr(pluginmanager, "reprec")
|
||||
pluginmanager.reprec = reprec = HookRecorder(pluginmanager)
|
||||
self.request.addfinalizer(reprec.finish_recording)
|
||||
return reprec
|
||||
|
||||
def chdir(self):
|
||||
@@ -305,9 +306,8 @@ class TmpTestdir:
|
||||
session = Session(config)
|
||||
assert '::' not in str(arg)
|
||||
p = py.path.local(arg)
|
||||
x = session.fspath.bestrelpath(p)
|
||||
config.hook.pytest_sessionstart(session=session)
|
||||
res = session.perform_collect([x], genitems=False)[0]
|
||||
res = session.perform_collect([str(p)], genitems=False)[0]
|
||||
config.hook.pytest_sessionfinish(session=session, exitstatus=EXIT_OK)
|
||||
return res
|
||||
|
||||
@@ -353,26 +353,23 @@ class TmpTestdir:
|
||||
def inline_genitems(self, *args):
|
||||
return self.inprocess_run(list(args) + ['--collectonly'])
|
||||
|
||||
def inline_run(self, *args):
|
||||
items, rec = self.inprocess_run(args)
|
||||
return rec
|
||||
def inprocess_run(self, args, plugins=()):
|
||||
rec = self.inline_run(*args, plugins=plugins)
|
||||
items = [x.item for x in rec.getcalls("pytest_itemcollected")]
|
||||
return items, rec
|
||||
|
||||
def inprocess_run(self, args, plugins=None):
|
||||
def inline_run(self, *args, **kwargs):
|
||||
rec = []
|
||||
items = []
|
||||
class Collect:
|
||||
def pytest_configure(x, config):
|
||||
rec.append(self.getreportrecorder(config))
|
||||
def pytest_itemcollected(self, item):
|
||||
items.append(item)
|
||||
if not plugins:
|
||||
plugins = []
|
||||
rec.append(self.make_hook_recorder(config.pluginmanager))
|
||||
plugins = kwargs.get("plugins") or []
|
||||
plugins.append(Collect())
|
||||
ret = pytest.main(list(args), plugins=plugins)
|
||||
assert len(rec) == 1
|
||||
reprec = rec[0]
|
||||
reprec.ret = ret
|
||||
assert len(rec) == 1
|
||||
return items, reprec
|
||||
return reprec
|
||||
|
||||
def parseconfig(self, *args):
|
||||
args = [str(x) for x in args]
|
||||
@@ -397,8 +394,7 @@ class TmpTestdir:
|
||||
def parseconfigure(self, *args):
|
||||
config = self.parseconfig(*args)
|
||||
config.do_configure()
|
||||
self.request.addfinalizer(lambda:
|
||||
config.do_unconfigure())
|
||||
self.request.addfinalizer(config.do_unconfigure)
|
||||
return config
|
||||
|
||||
def getitem(self, source, funcname="test_func"):
|
||||
@@ -547,86 +543,6 @@ def getdecoded(out):
|
||||
return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
|
||||
py.io.saferepr(out),)
|
||||
|
||||
class ReportRecorder(object):
|
||||
def __init__(self, hook):
|
||||
self.hook = hook
|
||||
self.pluginmanager = hook._pm
|
||||
self.pluginmanager.register(self)
|
||||
|
||||
def getcall(self, name):
|
||||
return self.hookrecorder.getcall(name)
|
||||
|
||||
def popcall(self, name):
|
||||
return self.hookrecorder.popcall(name)
|
||||
|
||||
def getcalls(self, names):
|
||||
""" return list of ParsedCall instances matching the given eventname. """
|
||||
return self.hookrecorder.getcalls(names)
|
||||
|
||||
# functionality for test reports
|
||||
|
||||
def getreports(self, names="pytest_runtest_logreport pytest_collectreport"):
|
||||
return [x.report for x in self.getcalls(names)]
|
||||
|
||||
def matchreport(self, inamepart="",
|
||||
names="pytest_runtest_logreport pytest_collectreport", when=None):
|
||||
""" return a testreport whose dotted import path matches """
|
||||
l = []
|
||||
for rep in self.getreports(names=names):
|
||||
try:
|
||||
if not when and rep.when != "call" and rep.passed:
|
||||
# setup/teardown passing reports - let's ignore those
|
||||
continue
|
||||
except AttributeError:
|
||||
pass
|
||||
if when and getattr(rep, 'when', None) != when:
|
||||
continue
|
||||
if not inamepart or inamepart in rep.nodeid.split("::"):
|
||||
l.append(rep)
|
||||
if not l:
|
||||
raise ValueError("could not find test report matching %r: no test reports at all!" %
|
||||
(inamepart,))
|
||||
if len(l) > 1:
|
||||
raise ValueError("found more than one testreport matching %r: %s" %(
|
||||
inamepart, l))
|
||||
return l[0]
|
||||
|
||||
def getfailures(self, names='pytest_runtest_logreport pytest_collectreport'):
|
||||
return [rep for rep in self.getreports(names) if rep.failed]
|
||||
|
||||
def getfailedcollections(self):
|
||||
return self.getfailures('pytest_collectreport')
|
||||
|
||||
def listoutcomes(self):
|
||||
passed = []
|
||||
skipped = []
|
||||
failed = []
|
||||
for rep in self.getreports(
|
||||
"pytest_collectreport pytest_runtest_logreport"):
|
||||
if rep.passed:
|
||||
if getattr(rep, "when", None) == "call":
|
||||
passed.append(rep)
|
||||
elif rep.skipped:
|
||||
skipped.append(rep)
|
||||
elif rep.failed:
|
||||
failed.append(rep)
|
||||
return passed, skipped, failed
|
||||
|
||||
def countoutcomes(self):
|
||||
return [len(x) for x in self.listoutcomes()]
|
||||
|
||||
def assertoutcome(self, passed=0, skipped=0, failed=0):
|
||||
realpassed, realskipped, realfailed = self.listoutcomes()
|
||||
assert passed == len(realpassed)
|
||||
assert skipped == len(realskipped)
|
||||
assert failed == len(realfailed)
|
||||
|
||||
def clear(self):
|
||||
self.hookrecorder.calls[:] = []
|
||||
|
||||
def unregister(self):
|
||||
self.pluginmanager.unregister(self)
|
||||
self.hookrecorder.finish_recording()
|
||||
|
||||
class LineComp:
|
||||
def __init__(self):
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
""" Python test discovery, setup and run of test functions. """
|
||||
import fnmatch
|
||||
import py
|
||||
import inspect
|
||||
import sys
|
||||
import pytest
|
||||
from _pytest.mark import MarkDecorator
|
||||
from _pytest.mark import MarkDecorator, MarkerError
|
||||
from py._code.code import TerminalRepr
|
||||
|
||||
import _pytest
|
||||
@@ -14,6 +15,8 @@ NOTSET = object()
|
||||
isfunction = inspect.isfunction
|
||||
isclass = inspect.isclass
|
||||
callable = py.builtin.callable
|
||||
# used to work around a python2 exception info leak
|
||||
exc_clear = getattr(sys, 'exc_clear', lambda: None)
|
||||
|
||||
def getfslineno(obj):
|
||||
# xxx let decorators etc specify a sane ordering
|
||||
@@ -124,12 +127,13 @@ def pytest_addoption(parser):
|
||||
parser.addini("usefixtures", type="args", default=[],
|
||||
help="list of default fixtures to be used with this project")
|
||||
parser.addini("python_files", type="args",
|
||||
default=('test_*.py', '*_test.py'),
|
||||
default=['test_*.py', '*_test.py'],
|
||||
help="glob-style file patterns for Python test module discovery")
|
||||
parser.addini("python_classes", type="args", default=("Test",),
|
||||
help="prefixes for Python test class discovery")
|
||||
parser.addini("python_functions", type="args", default=("test",),
|
||||
help="prefixes for Python test function and method discovery")
|
||||
parser.addini("python_classes", type="args", default=["Test",],
|
||||
help="prefixes or glob names for Python test class discovery")
|
||||
parser.addini("python_functions", type="args", default=["test",],
|
||||
help="prefixes or glob names for Python test function and "
|
||||
"method discovery")
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
if config.option.showfixtures:
|
||||
@@ -138,6 +142,10 @@ def pytest_cmdline_main(config):
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
# this misspelling is common - raise a specific error to alert the user
|
||||
if hasattr(metafunc.function, 'parameterize'):
|
||||
msg = "{0} has 'parameterize', spelling should be 'parametrize'"
|
||||
raise MarkerError(msg.format(metafunc.function.__name__))
|
||||
try:
|
||||
markers = metafunc.function.parametrize
|
||||
except AttributeError:
|
||||
@@ -183,17 +191,18 @@ def pytestconfig(request):
|
||||
return request.config
|
||||
|
||||
|
||||
def pytest_pyfunc_call(__multicall__, pyfuncitem):
|
||||
if not __multicall__.execute():
|
||||
testfunction = pyfuncitem.obj
|
||||
if pyfuncitem._isyieldedfunction():
|
||||
testfunction(*pyfuncitem._args)
|
||||
else:
|
||||
funcargs = pyfuncitem.funcargs
|
||||
testargs = {}
|
||||
for arg in pyfuncitem._fixtureinfo.argnames:
|
||||
testargs[arg] = funcargs[arg]
|
||||
testfunction(**testargs)
|
||||
@pytest.mark.trylast
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
testfunction = pyfuncitem.obj
|
||||
if pyfuncitem._isyieldedfunction():
|
||||
testfunction(*pyfuncitem._args)
|
||||
else:
|
||||
funcargs = pyfuncitem.funcargs
|
||||
testargs = {}
|
||||
for arg in pyfuncitem._fixtureinfo.argnames:
|
||||
testargs[arg] = funcargs[arg]
|
||||
testfunction(**testargs)
|
||||
return True
|
||||
|
||||
def pytest_collect_file(path, parent):
|
||||
ext = path.ext
|
||||
@@ -210,30 +219,31 @@ def pytest_collect_file(path, parent):
|
||||
def pytest_pycollect_makemodule(path, parent):
|
||||
return Module(path, parent)
|
||||
|
||||
def pytest_pycollect_makeitem(__multicall__, collector, name, obj):
|
||||
res = __multicall__.execute()
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_pycollect_makeitem(collector, name, obj):
|
||||
outcome = yield
|
||||
res = outcome.get_result()
|
||||
if res is not None:
|
||||
return res
|
||||
raise StopIteration
|
||||
# nothing was collected elsewhere, let's do it here
|
||||
if isclass(obj):
|
||||
#if hasattr(collector.obj, 'unittest'):
|
||||
# return # we assume it's a mixin class for a TestCase derived one
|
||||
if collector.classnamefilter(name):
|
||||
Class = collector._getcustomclass("Class")
|
||||
return Class(name, parent=collector)
|
||||
elif collector.funcnamefilter(name) and hasattr(obj, "__call__") and \
|
||||
outcome.force_result(Class(name, parent=collector))
|
||||
elif collector.funcnamefilter(name) and hasattr(obj, "__call__") and\
|
||||
getfixturemarker(obj) is None:
|
||||
# mock seems to store unbound methods (issue473), let's normalize it
|
||||
# mock seems to store unbound methods (issue473), normalize it
|
||||
obj = getattr(obj, "__func__", obj)
|
||||
if not isfunction(obj):
|
||||
collector.warn(code="C2", message=
|
||||
"cannot collect %r because it is not a function."
|
||||
% name, )
|
||||
return
|
||||
if getattr(obj, "__test__", True):
|
||||
if is_generator(obj):
|
||||
return Generator(name, parent=collector)
|
||||
res = Generator(name, parent=collector)
|
||||
else:
|
||||
return list(collector._genfunctions(name, obj))
|
||||
res = list(collector._genfunctions(name, obj))
|
||||
outcome.force_result(res)
|
||||
|
||||
def is_generator(func):
|
||||
try:
|
||||
@@ -305,14 +315,26 @@ class PyobjMixin(PyobjContext):
|
||||
class PyCollector(PyobjMixin, pytest.Collector):
|
||||
|
||||
def funcnamefilter(self, name):
|
||||
for prefix in self.config.getini("python_functions"):
|
||||
if name.startswith(prefix):
|
||||
return True
|
||||
return self._matches_prefix_or_glob_option('python_functions', name)
|
||||
|
||||
def classnamefilter(self, name):
|
||||
for prefix in self.config.getini("python_classes"):
|
||||
if name.startswith(prefix):
|
||||
return self._matches_prefix_or_glob_option('python_classes', name)
|
||||
|
||||
def _matches_prefix_or_glob_option(self, option_name, name):
|
||||
"""
|
||||
checks if the given name matches the prefix or glob-pattern defined
|
||||
in ini configuration.
|
||||
"""
|
||||
for option in self.config.getini(option_name):
|
||||
if name.startswith(option):
|
||||
return True
|
||||
# check that name looks like a glob-string before calling fnmatch
|
||||
# because this is called for every name in each collected module,
|
||||
# and fnmatch is somewhat expensive to call
|
||||
elif ('*' in option or '?' in option or '[' in option) and \
|
||||
fnmatch.fnmatch(name, option):
|
||||
return True
|
||||
return False
|
||||
|
||||
def collect(self):
|
||||
if not getattr(self.obj, "__test__", True):
|
||||
@@ -353,15 +375,17 @@ class PyCollector(PyobjMixin, pytest.Collector):
|
||||
fixtureinfo = fm.getfixtureinfo(self, funcobj, cls)
|
||||
metafunc = Metafunc(funcobj, fixtureinfo, self.config,
|
||||
cls=cls, module=module)
|
||||
gentesthook = self.config.hook.pytest_generate_tests
|
||||
extra = [module]
|
||||
if cls is not None:
|
||||
extra.append(cls())
|
||||
plugins = self.getplugins() + extra
|
||||
gentesthook.pcall(plugins, metafunc=metafunc)
|
||||
try:
|
||||
methods = [module.pytest_generate_tests]
|
||||
except AttributeError:
|
||||
methods = []
|
||||
if hasattr(cls, "pytest_generate_tests"):
|
||||
methods.append(cls().pytest_generate_tests)
|
||||
self.ihook.pytest_generate_tests.callextra(methods, metafunc=metafunc)
|
||||
|
||||
Function = self._getcustomclass("Function")
|
||||
if not metafunc._calls:
|
||||
yield Function(name, parent=self)
|
||||
yield Function(name, parent=self, fixtureinfo=fixtureinfo)
|
||||
else:
|
||||
# add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs
|
||||
add_funcarg_pseudo_fixture_def(self, metafunc, fm)
|
||||
@@ -370,6 +394,7 @@ class PyCollector(PyobjMixin, pytest.Collector):
|
||||
subname = "%s[%s]" %(name, callspec.id)
|
||||
yield Function(name=subname, parent=self,
|
||||
callspec=callspec, callobj=funcobj,
|
||||
fixtureinfo=fixtureinfo,
|
||||
keywords={callspec.id:True})
|
||||
|
||||
def add_funcarg_pseudo_fixture_def(collector, metafunc, fixturemanager):
|
||||
@@ -753,7 +778,6 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||
self.fixturenames = fixtureinfo.names_closure
|
||||
self._arg2fixturedefs = fixtureinfo.name2fixturedefs
|
||||
self.cls = cls
|
||||
self.module = module
|
||||
self._calls = []
|
||||
self._ids = py.builtin.set()
|
||||
|
||||
@@ -779,9 +803,14 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||
function so that it can perform more expensive setups during the
|
||||
setup phase of a test rather than at collection time.
|
||||
|
||||
:arg ids: list of string ids each corresponding to the argvalues so
|
||||
that they are part of the test id. If no ids are provided they will
|
||||
be generated automatically from the argvalues.
|
||||
:arg ids: list of string ids, or a callable.
|
||||
If strings, each is corresponding to the argvalues so that they are
|
||||
part of the test id.
|
||||
If callable, it should take one argument (a single argvalue) and return
|
||||
a string or return None. If None, the automatically generated id for that
|
||||
argument will be used.
|
||||
If no ids are provided they will be generated automatically from
|
||||
the argvalues.
|
||||
|
||||
:arg scope: if specified it denotes the scope of the parameters.
|
||||
The scope is used for grouping tests by parameter instances.
|
||||
@@ -821,11 +850,15 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||
raise ValueError("%r uses no fixture %r" %(
|
||||
self.function, arg))
|
||||
valtype = indirect and "params" or "funcargs"
|
||||
idfn = None
|
||||
if callable(ids):
|
||||
idfn = ids
|
||||
ids = None
|
||||
if ids and len(ids) != len(argvalues):
|
||||
raise ValueError('%d tests specified with %d ids' %(
|
||||
len(argvalues), len(ids)))
|
||||
if not ids:
|
||||
ids = idmaker(argnames, argvalues)
|
||||
ids = idmaker(argnames, argvalues, idfn)
|
||||
newcalls = []
|
||||
for callspec in self._calls or [CallSpec2(self)]:
|
||||
for param_index, valset in enumerate(argvalues):
|
||||
@@ -873,17 +906,31 @@ class Metafunc(FuncargnamesCompatAttr):
|
||||
cs.setall(funcargs, id, param)
|
||||
self._calls.append(cs)
|
||||
|
||||
def idmaker(argnames, argvalues):
|
||||
idlist = []
|
||||
for valindex, valset in enumerate(argvalues):
|
||||
this_id = []
|
||||
for nameindex, val in enumerate(valset):
|
||||
if not isinstance(val, (float, int, str, bool, NoneType)):
|
||||
this_id.append(str(argnames[nameindex])+str(valindex))
|
||||
else:
|
||||
this_id.append(str(val))
|
||||
idlist.append("-".join(this_id))
|
||||
return idlist
|
||||
|
||||
def _idval(val, argname, idx, idfn):
|
||||
if idfn:
|
||||
try:
|
||||
s = idfn(val)
|
||||
if s:
|
||||
return s
|
||||
except Exception:
|
||||
pass
|
||||
if isinstance(val, (float, int, str, bool, NoneType)):
|
||||
return str(val)
|
||||
return str(argname)+str(idx)
|
||||
|
||||
def _idvalset(idx, valset, argnames, idfn):
|
||||
this_id = [_idval(val, argname, idx, idfn)
|
||||
for val, argname in zip(valset, argnames)]
|
||||
return "-".join(this_id)
|
||||
|
||||
def idmaker(argnames, argvalues, idfn=None):
|
||||
ids = [_idvalset(valindex, valset, argnames, idfn)
|
||||
for valindex, valset in enumerate(argvalues)]
|
||||
if len(set(ids)) < len(ids):
|
||||
# user may have provided a bad idfn which means the ids are not unique
|
||||
ids = [str(i) + testid for i, testid in enumerate(ids)]
|
||||
return ids
|
||||
|
||||
def showfixtures(config):
|
||||
from _pytest.main import wrap_session
|
||||
@@ -935,7 +982,7 @@ def _showfixtures_main(config, session):
|
||||
loc = getlocation(fixturedef.func, curdir)
|
||||
doc = fixturedef.func.__doc__ or ""
|
||||
if doc:
|
||||
for line in doc.split("\n"):
|
||||
for line in doc.strip().split("\n"):
|
||||
tw.line(" " + line.strip())
|
||||
else:
|
||||
tw.line(" %s: no docstring available" %(loc,),
|
||||
@@ -1003,7 +1050,7 @@ def raises(ExpectedException, *args, **kwargs):
|
||||
if ExpectedException is AssertionError:
|
||||
# we want to catch a AssertionError
|
||||
# replace our subclass with the builtin one
|
||||
# see https://bitbucket.org/hpk42/pytest/issue/176/pytestraises
|
||||
# see https://bitbucket.org/pytest-dev/pytest/issue/176/pytestraises
|
||||
from _pytest.assertion.util import BuiltinAssertionError \
|
||||
as ExpectedException
|
||||
msg = ("exceptions must be old-style classes or"
|
||||
@@ -1065,28 +1112,27 @@ class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
|
||||
"""
|
||||
_genid = None
|
||||
def __init__(self, name, parent, args=None, config=None,
|
||||
callspec=None, callobj=NOTSET, keywords=None, session=None):
|
||||
callspec=None, callobj=NOTSET, keywords=None, session=None,
|
||||
fixtureinfo=None):
|
||||
super(Function, self).__init__(name, parent, config=config,
|
||||
session=session)
|
||||
self._args = args
|
||||
if callobj is not NOTSET:
|
||||
self.obj = callobj
|
||||
|
||||
for name, val in (py.builtin._getfuncdict(self.obj) or {}).items():
|
||||
self.keywords[name] = val
|
||||
self.keywords.update(self.obj.__dict__)
|
||||
if callspec:
|
||||
for name, val in callspec.keywords.items():
|
||||
self.keywords[name] = val
|
||||
if keywords:
|
||||
for name, val in keywords.items():
|
||||
self.keywords[name] = val
|
||||
|
||||
isyield = self._isyieldedfunction()
|
||||
self._fixtureinfo = fi = self.session._fixturemanager.getfixtureinfo(
|
||||
self.parent, self.obj, self.cls, funcargs=not isyield)
|
||||
self.fixturenames = fi.names_closure
|
||||
if callspec is not None:
|
||||
self.callspec = callspec
|
||||
self.keywords.update(callspec.keywords)
|
||||
if keywords:
|
||||
self.keywords.update(keywords)
|
||||
|
||||
if fixtureinfo is None:
|
||||
fixtureinfo = self.session._fixturemanager.getfixtureinfo(
|
||||
self.parent, self.obj, self.cls,
|
||||
funcargs=not self._isyieldedfunction())
|
||||
self._fixtureinfo = fixtureinfo
|
||||
self.fixturenames = fixtureinfo.names_closure
|
||||
self._initrequest()
|
||||
|
||||
def _initrequest(self):
|
||||
@@ -1348,10 +1394,12 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||
cached_result = (self, [0], None)
|
||||
return PseudoFixtureDef
|
||||
raise
|
||||
result = self._getfuncargvalue(fixturedef)
|
||||
self._funcargs[argname] = result
|
||||
self._fixturedefs[argname] = fixturedef
|
||||
return fixturedef
|
||||
# remove indent to prevent the python3 exception
|
||||
# from leaking into the call
|
||||
result = self._getfuncargvalue(fixturedef)
|
||||
self._funcargs[argname] = result
|
||||
self._fixturedefs[argname] = fixturedef
|
||||
return fixturedef
|
||||
|
||||
def _get_fixturestack(self):
|
||||
current = self
|
||||
@@ -1398,6 +1446,9 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||
(scope, argname, self.scope, "\n".join(lines))))
|
||||
__tracebackhide__ = False
|
||||
|
||||
# clear sys.exc_info before invoking the fixture (python bug?)
|
||||
# if its not explicitly cleared it will leak into the call
|
||||
exc_clear()
|
||||
try:
|
||||
# call the fixture function
|
||||
val = fixturedef.execute(request=subrequest)
|
||||
@@ -1571,15 +1622,8 @@ class FixtureManager:
|
||||
self._nodeid_and_autousenames = [("", self.config.getini("usefixtures"))]
|
||||
session.config.pluginmanager.register(self, "funcmanage")
|
||||
|
||||
self._nodename2fixtureinfo = {}
|
||||
|
||||
def getfixtureinfo(self, node, func, cls, funcargs=True):
|
||||
# node is the "collection node" for "func"
|
||||
key = (node, func)
|
||||
try:
|
||||
return self._nodename2fixtureinfo[key]
|
||||
except KeyError:
|
||||
pass
|
||||
if funcargs and not hasattr(node, "nofuncargs"):
|
||||
if cls is not None:
|
||||
startindex = 1
|
||||
@@ -1595,10 +1639,7 @@ class FixtureManager:
|
||||
fm = node.session._fixturemanager
|
||||
names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames,
|
||||
node)
|
||||
fixtureinfo = FuncFixtureInfo(argnames, names_closure,
|
||||
arg2fixturedefs)
|
||||
self._nodename2fixtureinfo[key] = fixtureinfo
|
||||
return fixtureinfo
|
||||
return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
|
||||
|
||||
### XXX this hook should be called for historic events like pytest_configure
|
||||
### so that we don't have to do the below pytest_configure hook
|
||||
@@ -1615,11 +1656,9 @@ class FixtureManager:
|
||||
# what fixtures are visible for particular tests (as denoted
|
||||
# by their test id)
|
||||
if p.basename.startswith("conftest.py"):
|
||||
nodeid = self.session.fspath.bestrelpath(p.dirpath())
|
||||
nodeid = p.dirpath().relto(self.config.rootdir)
|
||||
if p.sep != "/":
|
||||
nodeid = nodeid.replace(p.sep, "/")
|
||||
if nodeid == ".":
|
||||
nodeid = ""
|
||||
self.parsefactories(plugin, nodeid)
|
||||
self._seenplugins.add(plugin)
|
||||
|
||||
@@ -1676,13 +1715,17 @@ class FixtureManager:
|
||||
def pytest_generate_tests(self, metafunc):
|
||||
for argname in metafunc.fixturenames:
|
||||
faclist = metafunc._arg2fixturedefs.get(argname)
|
||||
if faclist is None:
|
||||
continue # will raise FixtureLookupError at setup time
|
||||
for fixturedef in faclist:
|
||||
if faclist:
|
||||
fixturedef = faclist[-1]
|
||||
if fixturedef.params is not None:
|
||||
metafunc.parametrize(argname, fixturedef.params,
|
||||
indirect=True, scope=fixturedef.scope,
|
||||
ids=fixturedef.ids)
|
||||
func_params = getattr(getattr(metafunc.function, 'parametrize', None), 'args', [[None]])
|
||||
# skip directly parametrized arguments
|
||||
if argname not in func_params and argname not in func_params[0]:
|
||||
metafunc.parametrize(argname, fixturedef.params,
|
||||
indirect=True, scope=fixturedef.scope,
|
||||
ids=fixturedef.ids)
|
||||
else:
|
||||
continue # will raise FixtureLookupError at setup time
|
||||
|
||||
def pytest_collection_modifyitems(self, items):
|
||||
# separate parametrized setups
|
||||
|
||||
@@ -86,7 +86,17 @@ def pytest_runtest_setup(item):
|
||||
item.session._setupstate.prepare(item)
|
||||
|
||||
def pytest_runtest_call(item):
|
||||
item.runtest()
|
||||
try:
|
||||
item.runtest()
|
||||
except Exception:
|
||||
# Store trace info to allow postmortem debugging
|
||||
type, value, tb = sys.exc_info()
|
||||
tb = tb.tb_next # Skip *this* frame
|
||||
sys.last_type = type
|
||||
sys.last_value = value
|
||||
sys.last_traceback = tb
|
||||
del tb # Get rid of it in this namespace
|
||||
raise
|
||||
|
||||
def pytest_runtest_teardown(item, nextitem):
|
||||
item.session._setupstate.teardown_exact(item, nextitem)
|
||||
|
||||
@@ -57,7 +57,7 @@ class MarkEvaluator:
|
||||
|
||||
@property
|
||||
def holder(self):
|
||||
return self.item.keywords.get(self.name, None)
|
||||
return self.item.keywords.get(self.name)
|
||||
|
||||
def __bool__(self):
|
||||
return bool(self.holder)
|
||||
@@ -75,9 +75,7 @@ class MarkEvaluator:
|
||||
def istrue(self):
|
||||
try:
|
||||
return self._istrue()
|
||||
except KeyboardInterrupt:
|
||||
raise
|
||||
except:
|
||||
except Exception:
|
||||
self.exc = sys.exc_info()
|
||||
if isinstance(self.exc[1], SyntaxError):
|
||||
msg = [" " * (self.exc[1].offset + 4) + "^",]
|
||||
@@ -153,44 +151,32 @@ def check_xfail_no_run(item):
|
||||
if not evalxfail.get('run', True):
|
||||
pytest.xfail("[NOTRUN] " + evalxfail.getexplanation())
|
||||
|
||||
def pytest_runtest_makereport(__multicall__, item, call):
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_runtest_makereport(item, call):
|
||||
outcome = yield
|
||||
rep = outcome.get_result()
|
||||
evalxfail = getattr(item, '_evalxfail', None)
|
||||
# unitttest special case, see setting of _unexpectedsuccess
|
||||
if hasattr(item, '_unexpectedsuccess'):
|
||||
rep = __multicall__.execute()
|
||||
if rep.when == "call":
|
||||
# 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(pytest.xfail.Exception)):
|
||||
evalxfail = getattr(item, '_evalxfail', None)
|
||||
if not evalxfail:
|
||||
return
|
||||
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
|
||||
rep.outcome = "skipped"
|
||||
return rep
|
||||
rep = __multicall__.execute()
|
||||
evalxfail = item._evalxfail
|
||||
if not rep.skipped:
|
||||
if not item.config.option.runxfail:
|
||||
if evalxfail.wasvalid() and evalxfail.istrue():
|
||||
if call.excinfo:
|
||||
if evalxfail.invalidraise(call.excinfo.value):
|
||||
rep.outcome = "failed"
|
||||
return rep
|
||||
else:
|
||||
rep.outcome = "skipped"
|
||||
elif call.when == "call":
|
||||
rep.outcome = "failed"
|
||||
else:
|
||||
return rep
|
||||
if hasattr(item, '_unexpectedsuccess') and rep.when == "call":
|
||||
# we need to translate into how pytest encodes xpass
|
||||
rep.wasxfail = "reason: " + repr(item._unexpectedsuccess)
|
||||
rep.outcome = "failed"
|
||||
elif item.config.option.runxfail:
|
||||
pass # don't interefere
|
||||
elif call.excinfo and call.excinfo.errisinstance(pytest.xfail.Exception):
|
||||
rep.wasxfail = "reason: " + call.excinfo.value.msg
|
||||
rep.outcome = "skipped"
|
||||
elif evalxfail and not rep.skipped and evalxfail.wasvalid() and \
|
||||
evalxfail.istrue():
|
||||
if call.excinfo:
|
||||
if evalxfail.invalidraise(call.excinfo.value):
|
||||
rep.outcome = "failed"
|
||||
else:
|
||||
rep.outcome = "skipped"
|
||||
rep.wasxfail = evalxfail.getexplanation()
|
||||
return rep
|
||||
return rep
|
||||
elif call.when == "call":
|
||||
rep.outcome = "failed" # xpass outcome
|
||||
rep.wasxfail = evalxfail.getexplanation()
|
||||
|
||||
# called by terminalreporter progress reporting
|
||||
def pytest_report_teststatus(report):
|
||||
@@ -232,14 +218,14 @@ def show_simple(terminalreporter, lines, stat, format):
|
||||
failed = terminalreporter.stats.get(stat)
|
||||
if failed:
|
||||
for rep in failed:
|
||||
pos = rep.nodeid
|
||||
lines.append(format %(pos, ))
|
||||
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
|
||||
lines.append(format %(pos,))
|
||||
|
||||
def show_xfailed(terminalreporter, lines):
|
||||
xfailed = terminalreporter.stats.get("xfailed")
|
||||
if xfailed:
|
||||
for rep in xfailed:
|
||||
pos = rep.nodeid
|
||||
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
|
||||
reason = rep.wasxfail
|
||||
lines.append("XFAIL %s" % (pos,))
|
||||
if reason:
|
||||
@@ -249,7 +235,7 @@ def show_xpassed(terminalreporter, lines):
|
||||
xpassed = terminalreporter.stats.get("xpassed")
|
||||
if xpassed:
|
||||
for rep in xpassed:
|
||||
pos = rep.nodeid
|
||||
pos = terminalreporter.config.cwd_relative_nodeid(rep.nodeid)
|
||||
reason = rep.wasxfail
|
||||
lines.append("XPASS %s %s" %(pos, reason))
|
||||
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Hi There!
|
||||
# You may be wondering what this giant blob of binary data here is, you might
|
||||
# even be worried that we're up to something nefarious (good for you for being
|
||||
# paranoid!). This is a base64 encoding of a zip file, this zip file contains
|
||||
# a fully functional basic pytest script.
|
||||
#
|
||||
# Pytest is a thing that tests packages, pytest itself is a package that some-
|
||||
# one might want to install, especially if they're looking to run tests inside
|
||||
# some package they want to install. Pytest has a lot of code to collect and
|
||||
# execute tests, and other such sort of "tribal knowledge" that has been en-
|
||||
# coded in its code base. Because of this we basically include a basic copy
|
||||
# of pytest inside this blob. We do this because it let's you as a maintainer
|
||||
# or application developer who wants people who don't deal with python much to
|
||||
# easily run tests without installing the complete pytest package.
|
||||
#
|
||||
# If you're wondering how this is created: you can create it yourself if you
|
||||
# have a complete pytest installation by using this command on the command-
|
||||
# line: ``py.test --genscript=runtests.py``.
|
||||
|
||||
sources = """
|
||||
@SOURCES@"""
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ def pytest_addoption(parser):
|
||||
group._addoption('--tb', metavar="style",
|
||||
action="store", dest="tbstyle", default='auto',
|
||||
choices=['auto', 'long', 'short', 'no', 'line', 'native'],
|
||||
help="traceback print mode (long/short/line/native/no).")
|
||||
help="traceback print mode (auto/long/short/line/native/no).")
|
||||
group._addoption('--fulltrace', '--full-trace',
|
||||
action="store_true", default=False,
|
||||
help="don't cut any tracebacks (default is to cut).")
|
||||
@@ -95,7 +95,7 @@ class TerminalReporter:
|
||||
self._numcollected = 0
|
||||
|
||||
self.stats = {}
|
||||
self.startdir = self.curdir = py.path.local()
|
||||
self.startdir = py.path.local()
|
||||
if file is None:
|
||||
file = sys.stdout
|
||||
self._tw = self.writer = py.io.TerminalWriter(file)
|
||||
@@ -111,12 +111,12 @@ class TerminalReporter:
|
||||
char = {'xfailed': 'x', 'skipped': 's'}.get(char, char)
|
||||
return char in self.reportchars
|
||||
|
||||
def write_fspath_result(self, fspath, res):
|
||||
def write_fspath_result(self, nodeid, res):
|
||||
fspath = self.config.rootdir.join(nodeid.split("::")[0])
|
||||
if fspath != self.currentfspath:
|
||||
self.currentfspath = fspath
|
||||
#fspath = self.startdir.bestrelpath(fspath)
|
||||
fspath = self.startdir.bestrelpath(fspath)
|
||||
self._tw.line()
|
||||
#relpath = self.startdir.bestrelpath(fspath)
|
||||
self._tw.write(fspath + " ")
|
||||
self._tw.write(res)
|
||||
|
||||
@@ -182,12 +182,12 @@ class TerminalReporter:
|
||||
def pytest_runtest_logstart(self, nodeid, location):
|
||||
# ensure that the path is printed before the
|
||||
# 1st test of a module starts running
|
||||
fspath = nodeid.split("::")[0]
|
||||
if self.showlongtestinfo:
|
||||
line = self._locationline(fspath, *location)
|
||||
line = self._locationline(nodeid, *location)
|
||||
self.write_ensure_prefix(line, "")
|
||||
elif self.showfspath:
|
||||
self.write_fspath_result(fspath, "")
|
||||
fsid = nodeid.split("::")[0]
|
||||
self.write_fspath_result(fsid, "")
|
||||
|
||||
def pytest_runtest_logreport(self, report):
|
||||
rep = report
|
||||
@@ -200,7 +200,7 @@ class TerminalReporter:
|
||||
return
|
||||
if self.verbosity <= 0:
|
||||
if not hasattr(rep, 'node') and self.showfspath:
|
||||
self.write_fspath_result(rep.fspath, letter)
|
||||
self.write_fspath_result(rep.nodeid, letter)
|
||||
else:
|
||||
self._tw.write(letter)
|
||||
else:
|
||||
@@ -213,7 +213,7 @@ class TerminalReporter:
|
||||
markup = {'red':True}
|
||||
elif rep.skipped:
|
||||
markup = {'yellow':True}
|
||||
line = self._locationline(str(rep.fspath), *rep.location)
|
||||
line = self._locationline(rep.nodeid, *rep.location)
|
||||
if not hasattr(rep, 'node'):
|
||||
self.write_ensure_prefix(line, word, **markup)
|
||||
#self._tw.write(word, **markup)
|
||||
@@ -237,7 +237,7 @@ class TerminalReporter:
|
||||
items = [x for x in report.result if isinstance(x, pytest.Item)]
|
||||
self._numcollected += len(items)
|
||||
if self.hasmarkup:
|
||||
#self.write_fspath_result(report.fspath, 'E')
|
||||
#self.write_fspath_result(report.nodeid, 'E')
|
||||
self.report_collect()
|
||||
|
||||
def report_collect(self, final=False):
|
||||
@@ -288,6 +288,10 @@ class TerminalReporter:
|
||||
self.write_line(line)
|
||||
|
||||
def pytest_report_header(self, config):
|
||||
inifile = ""
|
||||
if config.inifile:
|
||||
inifile = config.rootdir.bestrelpath(config.inifile)
|
||||
lines = ["rootdir: %s, inifile: %s" %(config.rootdir, inifile)]
|
||||
plugininfo = config.pluginmanager._plugin_distinfo
|
||||
if plugininfo:
|
||||
l = []
|
||||
@@ -296,7 +300,8 @@ class TerminalReporter:
|
||||
if name.startswith("pytest-"):
|
||||
name = name[7:]
|
||||
l.append(name)
|
||||
return "plugins: %s" % ", ".join(l)
|
||||
lines.append("plugins: %s" % ", ".join(l))
|
||||
return lines
|
||||
|
||||
def pytest_collection_finish(self, session):
|
||||
if self.config.option.collectonly:
|
||||
@@ -345,8 +350,10 @@ class TerminalReporter:
|
||||
indent = (len(stack) - 1) * " "
|
||||
self._tw.line("%s%s" % (indent, col))
|
||||
|
||||
def pytest_sessionfinish(self, exitstatus, __multicall__):
|
||||
__multicall__.execute()
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_sessionfinish(self, exitstatus):
|
||||
outcome = yield
|
||||
outcome.get_result()
|
||||
self._tw.line("")
|
||||
if exitstatus in (0, 1, 2, 4):
|
||||
self.summary_errors()
|
||||
@@ -376,19 +383,24 @@ class TerminalReporter:
|
||||
else:
|
||||
excrepr.reprcrash.toterminal(self._tw)
|
||||
|
||||
def _locationline(self, collect_fspath, fspath, lineno, domain):
|
||||
def _locationline(self, nodeid, fspath, lineno, domain):
|
||||
def mkrel(nodeid):
|
||||
line = self.config.cwd_relative_nodeid(nodeid)
|
||||
if domain and line.endswith(domain):
|
||||
line = line[:-len(domain)]
|
||||
l = domain.split("[")
|
||||
l[0] = l[0].replace('.', '::') # don't replace '.' in params
|
||||
line += "[".join(l)
|
||||
return line
|
||||
# collect_fspath comes from testid which has a "/"-normalized path
|
||||
if fspath and fspath.replace("\\", "/") != collect_fspath:
|
||||
fspath = "%s <- %s" % (collect_fspath, fspath)
|
||||
|
||||
if fspath:
|
||||
line = str(fspath)
|
||||
if domain:
|
||||
split = str(domain).split('[')
|
||||
split[0] = split[0].replace('.', '::') # don't replace '.' in params
|
||||
line += "::" + '['.join(split)
|
||||
res = mkrel(nodeid).replace("::()", "") # parens-normalization
|
||||
if nodeid.split("::")[0] != fspath.replace("\\", "/"):
|
||||
res += " <- " + self.startdir.bestrelpath(fspath)
|
||||
else:
|
||||
line = "[location]"
|
||||
return line + " "
|
||||
res = "[location]"
|
||||
return res + " "
|
||||
|
||||
def _getfailureheadline(self, rep):
|
||||
if hasattr(rep, 'location'):
|
||||
|
||||
@@ -151,30 +151,33 @@ def pytest_runtest_makereport(item, call):
|
||||
pass
|
||||
|
||||
# twisted trial support
|
||||
def pytest_runtest_protocol(item, __multicall__):
|
||||
if isinstance(item, TestCaseFunction):
|
||||
if 'twisted.trial.unittest' in sys.modules:
|
||||
ut = sys.modules['twisted.python.failure']
|
||||
Failure__init__ = ut.Failure.__init__
|
||||
check_testcase_implements_trial_reporter()
|
||||
def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
|
||||
captureVars=None):
|
||||
if exc_value is None:
|
||||
self._rawexcinfo = sys.exc_info()
|
||||
else:
|
||||
if exc_type is None:
|
||||
exc_type = type(exc_value)
|
||||
self._rawexcinfo = (exc_type, exc_value, exc_tb)
|
||||
try:
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb,
|
||||
captureVars=captureVars)
|
||||
except TypeError:
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb)
|
||||
ut.Failure.__init__ = excstore
|
||||
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_runtest_protocol(item):
|
||||
if isinstance(item, TestCaseFunction) and \
|
||||
'twisted.trial.unittest' in sys.modules:
|
||||
ut = sys.modules['twisted.python.failure']
|
||||
Failure__init__ = ut.Failure.__init__
|
||||
check_testcase_implements_trial_reporter()
|
||||
def excstore(self, exc_value=None, exc_type=None, exc_tb=None,
|
||||
captureVars=None):
|
||||
if exc_value is None:
|
||||
self._rawexcinfo = sys.exc_info()
|
||||
else:
|
||||
if exc_type is None:
|
||||
exc_type = type(exc_value)
|
||||
self._rawexcinfo = (exc_type, exc_value, exc_tb)
|
||||
try:
|
||||
return __multicall__.execute()
|
||||
finally:
|
||||
ut.Failure.__init__ = Failure__init__
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb,
|
||||
captureVars=captureVars)
|
||||
except TypeError:
|
||||
Failure__init__(self, exc_value, exc_type, exc_tb)
|
||||
ut.Failure.__init__ = excstore
|
||||
yield
|
||||
ut.Failure.__init__ = Failure__init__
|
||||
else:
|
||||
yield
|
||||
|
||||
|
||||
def check_testcase_implements_trial_reporter(done=[]):
|
||||
if done:
|
||||
|
||||
@@ -9,4 +9,4 @@ if __name__ == '__main__':
|
||||
p = pstats.Stats("prof")
|
||||
p.strip_dirs()
|
||||
p.sort_stats('cumulative')
|
||||
print(p.print_stats(250))
|
||||
print(p.print_stats(500))
|
||||
|
||||
@@ -12,7 +12,6 @@ PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
SITETARGET=latest
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
@@ -43,11 +42,15 @@ help:
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
SITETARGET=latest
|
||||
|
||||
install: html
|
||||
rsync -avz _build/html/ pytest.org:/www/pytest.org/$(SITETARGET)
|
||||
# for access talk to someone with login rights to
|
||||
# pytest-dev@pytest.org to add your ssh key
|
||||
rsync -avz _build/html/ pytest-dev@pytest.org:/www/pytest.org/$(SITETARGET)
|
||||
|
||||
installpdf: latexpdf
|
||||
@scp $(BUILDDIR)/latex/pytest.pdf pytest.org:/www/pytest.org/$(SITETARGET)
|
||||
@scp $(BUILDDIR)/latex/pytest.pdf pytest-dev@pytest.org:/www/pytest.org/$(SITETARGET)
|
||||
|
||||
installall: clean install installpdf
|
||||
@echo "done"
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<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="https://bitbucket.org/pytest-dev/pytest/">pytest @ Bitbucket</a></li>
|
||||
<li><a href="http://pytest.org/latest/plugins_index/index.html">3rd party plugins</a></li>
|
||||
<li><a href="https://bitbucket.org/hpk42/pytest/issues?status=new&status=open">Issue Tracker</a></li>
|
||||
<li><a href="https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open">Issue Tracker</a></li>
|
||||
<li><a href="http://pytest.org/latest/pytest.pdf">PDF Documentation</a>
|
||||
</ul>
|
||||
|
||||
|
||||
79
doc/en/adopt.txt
Normal file
79
doc/en/adopt.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
April 2015 is "adopt pytest month"
|
||||
=============================================
|
||||
|
||||
Are you an enthusiastic pytest user, the local testing guru in your workplace? Or are you considering using pytest for your open source project, but not sure how to get started? Then you may be interested in "adopt pytest month"!
|
||||
|
||||
We will pair experienced pytest users with open source projects, for a month's effort of getting new development teams started with pytest.
|
||||
|
||||
In 2015 we are trying this for the first time. In February and March 2015 we will gather volunteers on both sides, in April we will do the work, and in May we will evaluate how it went. This effort is being coordinated by Brianna Laugher. If you have any questions or comments, you can raise them on the `@pytestdotorg twitter account <https://twitter.com/pytestdotorg>`_ the `issue tracker`_ or the `pytest-dev mailing list`_.
|
||||
|
||||
|
||||
.. _`issue tracker`: https://bitbucket.org/pytest-dev/pytest/issue/676/adopt-pytest-month-2015
|
||||
.. _`pytest-dev mailing list`: https://mail.python.org/mailman/listinfo/pytest-dev
|
||||
.. _``:
|
||||
|
||||
|
||||
The ideal pytest helper
|
||||
-----------------------------------------
|
||||
|
||||
- will be able to commit 2-4 hours a week to working with their particular project (this might involve joining their mailing list, installing the software and exploring any existing tests, offering advice, writing some example tests)
|
||||
- feels confident in using pytest (e.g. has explored command line options, knows how to write parametrized tests, has an idea about conftest contents)
|
||||
- does not need to be an expert in every aspect!
|
||||
|
||||
`Pytest helpers, sign up here`_! (preferably in February, hard deadline 22 March)
|
||||
|
||||
|
||||
.. _`Pytest helpers, sign up here`: http://goo.gl/forms/nxqAhqWt1P
|
||||
|
||||
|
||||
The ideal partner project
|
||||
-----------------------------------------
|
||||
|
||||
- is open source, and predominantly written in Python
|
||||
- has an automated/documented install process for developers
|
||||
- has more than one core developer
|
||||
- has at least one official release (e.g. is available on pypi)
|
||||
- has the support of the core development team, in trying out pytest adoption
|
||||
- has no tests... or 100% test coverage... or somewhere in between!
|
||||
|
||||
`Partner projects, sign up here`_! (by 22 March)
|
||||
|
||||
|
||||
.. _`Partner projects, sign up here`: http://goo.gl/forms/ZGyqlHiwk3
|
||||
|
||||
|
||||
What does it mean to "adopt pytest"?
|
||||
-----------------------------------------
|
||||
|
||||
There can be many different definitions of "success". Pytest can run many `nose and unittest`_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right?
|
||||
|
||||
Progressive success might look like:
|
||||
|
||||
- tests can be run (by pytest) without errors (there may be failures)
|
||||
- tests can be run (by pytest) without failures
|
||||
- test runner is integrated into CI server
|
||||
- existing tests are rewritten to take advantage of pytest features - this can happen in several iterations, for example:
|
||||
- changing to native assert_ statements (pycmd_ has a script to help with that, ``pyconvert_unittest.py``)
|
||||
- changing `setUp/tearDown methods`_ to fixtures_
|
||||
- adding markers_
|
||||
- other changes to reduce boilerplate
|
||||
- assess needs for future tests to be written, e.g. new fixtures, distributed_ testing tweaks
|
||||
|
||||
"Success" should also include that the development team feels comfortable with their knowledge of how to use pytest. In fact this is probably more important than anything else. So spending a lot of time on communication, giving examples, etc will probably be important - both in running the tests, and in writing them.
|
||||
|
||||
It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies.
|
||||
|
||||
.. _`nose and unittest`: faq.html#how-does-pytest-relate-to-nose-and-unittest
|
||||
.. _assert: asserts.html
|
||||
.. _pycmd: https://bitbucket.org/hpk42/pycmd/overview
|
||||
.. _`setUp/tearDown methods`: xunit_setup.html
|
||||
.. _fixtures: fixture.html
|
||||
.. _markers: markers.html
|
||||
.. _distributed: xdist.html
|
||||
|
||||
|
||||
Other ways to help
|
||||
-----------------------------------------
|
||||
|
||||
Promote! Do your favourite open source Python projects use pytest? If not, why not tell them about this page?
|
||||
@@ -5,6 +5,7 @@ Release announcements
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
release-2.6.3
|
||||
release-2.6.2
|
||||
release-2.6.1
|
||||
release-2.6.0
|
||||
|
||||
@@ -34,7 +34,7 @@ a full list of details. A few feature highlights:
|
||||
influence the environment before conftest files import ``django``.
|
||||
|
||||
- reporting: color the last line red or green depending if
|
||||
failures/errors occured or everything passed.
|
||||
failures/errors occurred or everything passed.
|
||||
|
||||
The documentation has been updated to accomodate the changes,
|
||||
see `http://pytest.org <http://pytest.org>`_
|
||||
@@ -95,7 +95,7 @@ new features:
|
||||
as strings will remain fully supported.
|
||||
|
||||
- reporting: color the last line red or green depending if
|
||||
failures/errors occured or everything passed. thanks Christian
|
||||
failures/errors occurred or everything passed. thanks Christian
|
||||
Theunert.
|
||||
|
||||
- make "import pdb ; pdb.set_trace()" work natively wrt capturing (no
|
||||
|
||||
@@ -21,7 +21,7 @@ pytest-2.4.2 is another bug-fixing release:
|
||||
|
||||
- introduce node.get_marker/node.add_marker API for plugins
|
||||
like pytest-pep8 and pytest-flakes to avoid the messy
|
||||
details of the node.keywords pseudo-dicts. Adapated
|
||||
details of the node.keywords pseudo-dicts. Adapted
|
||||
docs.
|
||||
|
||||
- remove attempt to "dup" stdout at startup as it's icky.
|
||||
|
||||
@@ -21,7 +21,7 @@ fixes a number of bugs and brings some new features, mainly:
|
||||
Note also that 2.6.0 departs with the "zero reported bugs" policy
|
||||
because it has been too hard to keep up with it, unfortunately.
|
||||
Instead we are for now rather bound to work on "upvoted" issues in
|
||||
the https://bitbucket.org/hpk42/pytest/issues?status=new&status=open&sort=-votes
|
||||
the https://bitbucket.org/pytest-dev/pytest/issues?status=new&status=open&sort=-votes
|
||||
issue tracker.
|
||||
|
||||
See docs at:
|
||||
|
||||
101
doc/en/announce/release-2.7.0.txt
Normal file
101
doc/en/announce/release-2.7.0.txt
Normal file
@@ -0,0 +1,101 @@
|
||||
pytest-2.7.0: fixes, features, speed improvements
|
||||
===========================================================================
|
||||
|
||||
pytest is a mature Python testing tool with more than a 1100 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
This release is supposed to be drop-in compatible to 2.6.X.
|
||||
|
||||
See below for the changes and see docs at:
|
||||
|
||||
http://pytest.org
|
||||
|
||||
As usual, you can upgrade from pypi via::
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed, among them:
|
||||
|
||||
Anatoly Bubenkoff
|
||||
Floris Bruynooghe
|
||||
Brianna Laugher
|
||||
Eric Siegerman
|
||||
Daniel Hahler
|
||||
Charles Cloud
|
||||
Tom Viner
|
||||
Holger Peters
|
||||
Ldiary Translations
|
||||
almarklein
|
||||
|
||||
have fun,
|
||||
holger krekel
|
||||
|
||||
2.7.0 (compared to 2.6.4)
|
||||
-----------------------------
|
||||
|
||||
- fix issue435: make reload() work when assert rewriting is active.
|
||||
Thanks Daniel Hahler.
|
||||
|
||||
- fix issue616: conftest.py files and their contained fixutres are now
|
||||
properly considered for visibility, independently from the exact
|
||||
current working directory and test arguments that are used.
|
||||
Many thanks to Eric Siegerman and his PR235 which contains
|
||||
systematic tests for conftest visibility and now passes.
|
||||
This change also introduces the concept of a ``rootdir`` which
|
||||
is printed as a new pytest header and documented in the pytest
|
||||
customize web page.
|
||||
|
||||
- change reporting of "diverted" tests, i.e. tests that are collected
|
||||
in one file but actually come from another (e.g. when tests in a test class
|
||||
come from a base class in a different file). We now show the nodeid
|
||||
and indicate via a postfix the other file.
|
||||
|
||||
- add ability to set command line options by environment variable PYTEST_ADDOPTS.
|
||||
|
||||
- added documentation on the new pytest-dev teams on bitbucket and
|
||||
github. See https://pytest.org/latest/contributing.html .
|
||||
Thanks to Anatoly for pushing and initial work on this.
|
||||
|
||||
- fix issue650: new option ``--docttest-ignore-import-errors`` which
|
||||
will turn import errors in doctests into skips. Thanks Charles Cloud
|
||||
for the complete PR.
|
||||
|
||||
- fix issue655: work around different ways that cause python2/3
|
||||
to leak sys.exc_info into fixtures/tests causing failures in 3rd party code
|
||||
|
||||
- fix issue615: assertion re-writing did not correctly escape % signs
|
||||
when formatting boolean operations, which tripped over mixing
|
||||
booleans with modulo operators. Thanks to Tom Viner for the report,
|
||||
triaging and fix.
|
||||
|
||||
- implement issue351: add ability to specify parametrize ids as a callable
|
||||
to generate custom test ids. Thanks Brianna Laugher for the idea and
|
||||
implementation.
|
||||
|
||||
- introduce and document new hookwrapper mechanism useful for plugins
|
||||
which want to wrap the execution of certain hooks for their purposes.
|
||||
This supersedes the undocumented ``__multicall__`` protocol which
|
||||
pytest itself and some external plugins use. Note that pytest-2.8
|
||||
is scheduled to drop supporting the old ``__multicall__``
|
||||
and only support the hookwrapper protocol.
|
||||
|
||||
- majorly speed up invocation of plugin hooks
|
||||
|
||||
- use hookwrapper mechanism in builtin pytest plugins.
|
||||
|
||||
- add a doctest ini option for doctest flags, thanks Holger Peters.
|
||||
|
||||
- add note to docs that if you want to mark a parameter and the
|
||||
parameter is a callable, you also need to pass in a reason to disambiguate
|
||||
it from the "decorator" case. Thanks Tom Viner.
|
||||
|
||||
- "python_classes" and "python_functions" options now support glob-patterns
|
||||
for test discovery, as discussed in issue600. Thanks Ldiary Translations.
|
||||
|
||||
- allow to override parametrized fixtures with non-parametrized ones and vice versa (bubenkoff).
|
||||
|
||||
- fix issue463: raise specific error for 'parameterize' misspelling (pfctdayelise).
|
||||
|
||||
- On failure, the ``sys.last_value``, ``sys.last_type`` and
|
||||
``sys.last_traceback`` are set, so that a user can inspect the error
|
||||
via postmortem debugging (almarklein).
|
||||
|
||||
@@ -26,7 +26,8 @@ you will see the return value of the function call::
|
||||
|
||||
$ py.test test_assert1.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-98, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_assert1.py F
|
||||
@@ -135,7 +136,8 @@ if you run this module::
|
||||
|
||||
$ py.test test_assert2.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-98, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_assert2.py F
|
||||
@@ -152,6 +154,7 @@ if you run this module::
|
||||
E '1'
|
||||
E Extra items in the right set:
|
||||
E '5'
|
||||
E Use -v to get the full diff
|
||||
|
||||
test_assert2.py:5: AssertionError
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
@@ -201,16 +204,16 @@ the conftest file::
|
||||
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
|
||||
1 failed in 0.00 seconds
|
||||
|
||||
.. _assert-details:
|
||||
.. _`assert introspection`:
|
||||
|
||||
@@ -77,12 +77,10 @@ You can ask for available builtin or project-custom
|
||||
enables capturing of writes to sys.stdout/sys.stderr and makes
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple.
|
||||
|
||||
capfd
|
||||
enables capturing of writes to file descriptors 1 and 2 and makes
|
||||
captured output available via ``capfd.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple.
|
||||
|
||||
monkeypatch
|
||||
The returned ``monkeypatch`` funcarg provides these
|
||||
helper methods to modify objects, dictionaries or os.environ::
|
||||
@@ -100,7 +98,6 @@ You can ask for available builtin or project-custom
|
||||
test function has finished. The ``raising``
|
||||
parameter determines if a KeyError or AttributeError
|
||||
will be raised if the set/deletion operation has no target.
|
||||
|
||||
pytestconfig
|
||||
the pytest config object with access to command line opts.
|
||||
recwarn
|
||||
@@ -111,13 +108,11 @@ You can ask for available builtin or project-custom
|
||||
|
||||
See http://docs.python.org/library/warnings.html for information
|
||||
on warning categories.
|
||||
|
||||
tmpdir
|
||||
return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
created as a sub directory of the base temporary
|
||||
directory. The returned object is a `py.path.local`_
|
||||
path object.
|
||||
|
||||
|
||||
in 0.00 seconds
|
||||
|
||||
@@ -64,7 +64,8 @@ of the failing function and hide the other one::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-101, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_module.py .F
|
||||
@@ -78,7 +79,7 @@ of the failing function and hide the other one::
|
||||
|
||||
test_module.py:9: AssertionError
|
||||
-------------------------- Captured stdout setup ---------------------------
|
||||
setting up <function test_func2 at 0x2b3173d7fbf8>
|
||||
setting up <function test_func2 at 0x2b24d5259158>
|
||||
==================== 1 failed, 1 passed in 0.01 seconds ====================
|
||||
|
||||
Accessing captured output from a test function
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# The short X.Y version.
|
||||
version = "2.6"
|
||||
release = "2.6.3"
|
||||
version = "2.7"
|
||||
release = "2.7.0"
|
||||
|
||||
import sys, os
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ Contact channels
|
||||
- `merlinux.eu`_ offers pytest and tox-related professional teaching and
|
||||
consulting.
|
||||
|
||||
.. _`pytest issue tracker`: http://bitbucket.org/hpk42/pytest/issues/
|
||||
.. _`pytest issue tracker`: http://bitbucket.org/pytest-dev/pytest/issues/
|
||||
.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||
|
||||
.. _`merlinux.eu`: http://merlinux.eu
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
|
||||
.. note::
|
||||
|
||||
`improving your automated testing with pytest <https://ep2014.europython.eu/en/schedule/sessions/92/>`_, July 25th 2014, Berlin, Germany
|
||||
|
||||
`professional testing with pytest and tox <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_, 24-26th November 2014, Freiburg, Germany
|
||||
|
||||
.. _toc:
|
||||
|
||||
Full pytest documentation
|
||||
|
||||
@@ -12,37 +12,73 @@ configurations files by using the general help option::
|
||||
This will display command line and configuration file settings
|
||||
which were registered by installed plugins.
|
||||
|
||||
.. _rootdir:
|
||||
.. _inifiles:
|
||||
|
||||
How test configuration is read from configuration INI-files
|
||||
-------------------------------------------------------------
|
||||
initialization: determining rootdir and inifile
|
||||
-----------------------------------------------
|
||||
|
||||
``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::
|
||||
.. versionadded:: 2.7
|
||||
|
||||
pytest determines a "rootdir" for each test run which depends on
|
||||
the command line arguments (specified test files, paths) and on
|
||||
the existence of inifiles. The determined rootdir and ini-file are
|
||||
printed as part of the pytest header. The rootdir is used for constructing
|
||||
"nodeids" during collection and may also be used by plugins to store
|
||||
project/testrun-specific information.
|
||||
|
||||
Here is the algorithm which finds the rootdir from ``args``:
|
||||
|
||||
- determine the common ancestor directory for the specified ``args``.
|
||||
|
||||
- look for ``pytest.ini``, ``tox.ini`` and ``setup.cfg`` files in the
|
||||
ancestor directory and upwards. If one is matched, it becomes the
|
||||
ini-file and its directory becomes the rootdir. An existing
|
||||
``pytest.ini`` file will always be considered a match whereas
|
||||
``tox.ini`` and ``setup.cfg`` will only match if they contain
|
||||
a ``[pytest]`` section.
|
||||
|
||||
- if no ini-file was found, look for ``setup.py`` upwards from
|
||||
the common ancestor directory to determine the ``rootdir``.
|
||||
|
||||
- if no ini-file and no ``setup.py`` was found, use the already
|
||||
determined common ancestor as root directory. This allows to
|
||||
work with pytest in structures that are not part of a package
|
||||
and don't have any particular ini-file configuration.
|
||||
|
||||
Note that options from multiple ini-files candidates are never merged,
|
||||
the first one wins (``pytest.ini`` always wins even if it does not
|
||||
contain a ``[pytest]`` section).
|
||||
|
||||
The ``config`` object will subsequently carry these attributes:
|
||||
|
||||
- ``config.rootdir``: the determined root directory, guaranteed to exist.
|
||||
|
||||
- ``config.inifile``: the determined ini-file, may be ``None``.
|
||||
|
||||
The rootdir is used a reference directory for constructing test
|
||||
addresses ("nodeids") and can be used also by plugins for storing
|
||||
per-testrun information.
|
||||
|
||||
Example::
|
||||
|
||||
py.test path/to/testdir path/other/
|
||||
|
||||
will determine the common ancestor as ``path`` and then
|
||||
check for ini-files as follows::
|
||||
|
||||
# first look for pytest.ini files
|
||||
path/pytest.ini
|
||||
path/setup.cfg # must also contain [pytest] section to match
|
||||
path/tox.ini # must also contain [pytest] section to match
|
||||
pytest.ini
|
||||
tox.ini
|
||||
setup.cfg
|
||||
... # all the way down to the root
|
||||
|
||||
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::
|
||||
# now look for setup.py
|
||||
path/setup.py
|
||||
setup.py
|
||||
... # all the way down to the root
|
||||
|
||||
py.test path/to/testdir
|
||||
|
||||
will look in the following dirs for a config file::
|
||||
|
||||
path/to/testdir/pytest.ini
|
||||
path/to/testdir/tox.ini
|
||||
path/to/testdir/setup.cfg
|
||||
path/to/pytest.ini
|
||||
path/to/tox.ini
|
||||
path/to/setup.cfg
|
||||
... # up until root of filesystem
|
||||
|
||||
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`:
|
||||
.. _`adding default options`:
|
||||
@@ -60,8 +96,15 @@ progress output, you can write it into a configuration file::
|
||||
[pytest]
|
||||
addopts = -rsxX -q
|
||||
|
||||
Alternatively, you can set a PYTEST_ADDOPTS environment variable to add command
|
||||
line options while the environment is in use::
|
||||
|
||||
export PYTEST_ADDOPTS="-rsxX -q"
|
||||
|
||||
From now on, running ``pytest`` will add the specified options.
|
||||
|
||||
|
||||
|
||||
Builtin configuration file options
|
||||
----------------------------------------------
|
||||
|
||||
@@ -115,14 +158,35 @@ Builtin configuration file options
|
||||
|
||||
.. confval:: python_classes
|
||||
|
||||
One or more name prefixes determining which test classes
|
||||
are considered as test modules.
|
||||
One or more name prefixes or glob-style patterns determining which classes
|
||||
are considered for test collection. Here is an example of how to collect
|
||||
tests from classes that end in ``Suite``::
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
python_classes = *Suite
|
||||
|
||||
Note that ``unittest.TestCase`` derived classes are always collected
|
||||
regardless of this option, as ``unittest``'s own collection framework is used
|
||||
to collect those tests.
|
||||
|
||||
.. confval:: python_functions
|
||||
|
||||
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``
|
||||
derived class.
|
||||
One or more name prefixes or glob-patterns determining which test functions
|
||||
and methods are considered tests. Here is an example of how
|
||||
to collect test functions and methods that end in ``_test``::
|
||||
|
||||
See :ref:`change naming conventions` for examples.
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
python_functions = *_test
|
||||
|
||||
Note that this has no effect on methods that live on a ``unittest
|
||||
.TestCase`` derived class, as ``unittest``'s own collection framework is used
|
||||
to collect those tests.
|
||||
|
||||
See :ref:`change naming conventions` for more detailed examples.
|
||||
|
||||
.. confval:: doctest_optionflags
|
||||
|
||||
One or more doctest flag names from the standard ``doctest`` module.
|
||||
:doc:`See how py.test handles doctests <doctest>`.
|
||||
|
||||
@@ -44,7 +44,8 @@ then you can just invoke ``py.test`` without command line options::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-107, inifile: pytest.ini
|
||||
collected 1 items
|
||||
|
||||
mymodule.py .
|
||||
@@ -60,3 +61,12 @@ It is possible to use fixtures using the ``getfixture`` helper::
|
||||
|
||||
Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
|
||||
when executing text doctest files.
|
||||
|
||||
The standard ``doctest`` module provides some setting flags to configure the
|
||||
strictness of doctest tests. In py.test You can enable those flags those flags
|
||||
using the configuration file. To make pytest ignore trailing whitespaces and
|
||||
ignore lengthy exception stack traces you can just write::
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
|
||||
|
||||
@@ -31,7 +31,8 @@ You can then restrict a test run to only run tests marked with ``webtest``::
|
||||
|
||||
$ py.test -v -m webtest
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::test_send_http PASSED
|
||||
@@ -43,7 +44,8 @@ Or the inverse, running all tests except the webtest ones::
|
||||
|
||||
$ py.test -v -m "not webtest"
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::test_something_quick PASSED
|
||||
@@ -62,7 +64,8 @@ tests based on their module, class, method, or function name::
|
||||
|
||||
$ py.test -v test_server.py::TestClass::test_method
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 5 items
|
||||
|
||||
test_server.py::TestClass::test_method PASSED
|
||||
@@ -73,7 +76,8 @@ You can also select on the class::
|
||||
|
||||
$ py.test -v test_server.py::TestClass
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::TestClass::test_method PASSED
|
||||
@@ -84,7 +88,8 @@ Or select multiple nodes::
|
||||
|
||||
$ py.test -v test_server.py::TestClass test_server.py::test_send_http
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 8 items
|
||||
|
||||
test_server.py::TestClass::test_method PASSED
|
||||
@@ -120,7 +125,8 @@ select tests based on their names::
|
||||
|
||||
$ py.test -v -k http # running with the above defined example module
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::test_send_http PASSED
|
||||
@@ -132,7 +138,8 @@ 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 linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::test_something_quick PASSED
|
||||
@@ -140,13 +147,14 @@ And you can also run all tests except the ones that match the keyword::
|
||||
test_server.py::TestClass::test_method PASSED
|
||||
|
||||
================= 1 tests deselected by '-knot send_http' ==================
|
||||
================== 3 passed, 1 deselected in 0.02 seconds ==================
|
||||
================== 3 passed, 1 deselected in 0.01 seconds ==================
|
||||
|
||||
Or to select "http" and "quick" tests::
|
||||
|
||||
$ py.test -k "http or quick" -v
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_server.py::test_send_http PASSED
|
||||
@@ -280,6 +288,14 @@ In this example the mark "foo" will apply to each of the three
|
||||
tests, whereas the "bar" mark is only applied to the second test.
|
||||
Skip and xfail marks can also be applied in this way, see :ref:`skip/xfail with parametrize`.
|
||||
|
||||
.. note::
|
||||
|
||||
If the data you are parametrizing happen to be single callables, you need to be careful
|
||||
when marking these items. `pytest.mark.xfail(my_func)` won't work because it's also the
|
||||
signature of a function being decorated. To resolve this ambiguity, you need to pass a
|
||||
reason argument:
|
||||
`pytest.mark.xfail(func_bar, reason="Issue#7")`.
|
||||
|
||||
|
||||
.. _`adding a custom marker from a plugin`:
|
||||
|
||||
@@ -326,23 +342,25 @@ the test needs::
|
||||
|
||||
$ py.test -E stage2
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_someenv.py s
|
||||
|
||||
======================== 1 skipped in 0.01 seconds =========================
|
||||
======================== 1 skipped in 0.00 seconds =========================
|
||||
|
||||
and here is one that specifies exactly the environment needed::
|
||||
|
||||
$ py.test -E stage1
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_someenv.py .
|
||||
|
||||
========================= 1 passed in 0.01 seconds =========================
|
||||
========================= 1 passed in 0.00 seconds =========================
|
||||
|
||||
The ``--markers`` option always gives you a list of available markers::
|
||||
|
||||
@@ -455,12 +473,13 @@ 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 linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_plat.py sss.
|
||||
========================= short test summary info ==========================
|
||||
SKIP [3] /tmp/doc-exec-224/conftest.py:12: cannot run on platform linux
|
||||
SKIP [3] /tmp/doc-exec-167/conftest.py:12: cannot run on platform linux
|
||||
|
||||
=================== 1 passed, 3 skipped in 0.01 seconds ====================
|
||||
|
||||
@@ -468,7 +487,8 @@ Note that if you specify a platform via the marker-command line option like this
|
||||
|
||||
$ py.test -m linux2
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_plat.py s
|
||||
@@ -519,7 +539,8 @@ We can now use the ``-m option`` to select one set::
|
||||
|
||||
$ py.test -m interface --tb=short
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -540,7 +561,8 @@ or to select both "event" and "interface" tests::
|
||||
|
||||
$ py.test -m "interface or event" --tb=short
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-167, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_module.py FFF
|
||||
|
||||
@@ -5,7 +5,7 @@ serialization via the pickle module.
|
||||
import py
|
||||
import pytest
|
||||
|
||||
pythonlist = ['python2.6', 'python2.7', 'python3.4']
|
||||
pythonlist = ['python2.6', 'python2.7', 'python3.3']
|
||||
@pytest.fixture(params=pythonlist)
|
||||
def python1(request, tmpdir):
|
||||
picklefile = tmpdir.join("data.pickle")
|
||||
@@ -26,7 +26,7 @@ class Python:
|
||||
dumpfile.write(py.code.Source("""
|
||||
import pickle
|
||||
f = open(%r, 'wb')
|
||||
s = pickle.dump(%r, f)
|
||||
s = pickle.dump(%r, f, protocol=2)
|
||||
f.close()
|
||||
""" % (str(self.picklefile), obj)))
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
|
||||
|
||||
@@ -27,10 +27,11 @@ now execute the test specification::
|
||||
|
||||
nonpython $ py.test test_simple.yml
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collected 2 items
|
||||
|
||||
test_simple.yml .F
|
||||
test_simple.yml F.
|
||||
|
||||
================================= FAILURES =================================
|
||||
______________________________ usecase: hello ______________________________
|
||||
@@ -56,11 +57,12 @@ consulted when reporting in ``verbose`` mode::
|
||||
|
||||
nonpython $ py.test -v
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_simple.yml::usecase: ok PASSED
|
||||
test_simple.yml::usecase: hello FAILED
|
||||
test_simple.yml::hello FAILED
|
||||
test_simple.yml::ok PASSED
|
||||
|
||||
================================= FAILURES =================================
|
||||
______________________________ usecase: hello ______________________________
|
||||
@@ -74,10 +76,11 @@ interesting to just look at the collection tree::
|
||||
|
||||
nonpython $ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collected 2 items
|
||||
<YamlFile 'test_simple.yml'>
|
||||
<YamlItem 'ok'>
|
||||
<YamlFile 'example/nonpython/test_simple.yml'>
|
||||
<YamlItem 'hello'>
|
||||
<YamlItem 'ok'>
|
||||
|
||||
============================= in 0.03 seconds =============================
|
||||
|
||||
@@ -68,6 +68,71 @@ let's run the full monty::
|
||||
As expected when running the full range of ``param1`` values
|
||||
we'll get an error on the last one.
|
||||
|
||||
|
||||
Different options for test IDs
|
||||
------------------------------------
|
||||
|
||||
pytest will build a string that is the test ID for each set of values in a
|
||||
parametrized test. These IDs can be used with ``-k`` to select specific cases
|
||||
to run, and they will also identify the specific case when one is failing.
|
||||
Running pytest with ``--collect-only`` will show the generated IDs.
|
||||
|
||||
Numbers, strings, booleans and None will have their usual string representation
|
||||
used in the test ID. For other objects, pytest will make a string based on
|
||||
the argument name::
|
||||
|
||||
# contents of test_time.py
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
testdata = [(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
|
||||
(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b,expected", testdata)
|
||||
def test_timedistance_v0(a, b, expected):
|
||||
diff = a - b
|
||||
assert diff == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
|
||||
def test_timedistance_v1(a, b, expected):
|
||||
diff = a - b
|
||||
assert diff == expected
|
||||
|
||||
|
||||
def idfn(val):
|
||||
if isinstance(val, (datetime,)):
|
||||
# note this wouldn't show any hours/minutes/seconds
|
||||
return val.strftime('%Y%m%d')
|
||||
|
||||
|
||||
@pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
|
||||
def test_timedistance_v2(a, b, expected):
|
||||
diff = a - b
|
||||
assert diff == expected
|
||||
|
||||
|
||||
In ``test_timedistance_v0``, we let pytest generate the test IDs.
|
||||
|
||||
In ``test_timedistance_v1``, we specified ``ids`` as a list of strings which were
|
||||
used as the test IDs. These are succinct, but can be a pain to maintain.
|
||||
|
||||
In ``test_timedistance_v2``, we specified ``ids`` as a function that can generate a
|
||||
string representation to make part of the test ID. So our ``datetime`` values use the
|
||||
label generated by ``idfn``, but because we didn't generate a label for ``timedelta``
|
||||
objects, they are still using the default pytest representation::
|
||||
|
||||
|
||||
$ py.test test_time.py --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-169, inifile:
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
ERROR: file not found: test_time.py
|
||||
|
||||
A quick port of "testscenarios"
|
||||
------------------------------------
|
||||
|
||||
@@ -106,7 +171,8 @@ this is a fully self-contained example which you can run with::
|
||||
|
||||
$ py.test test_scenarios.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-169, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_scenarios.py ....
|
||||
@@ -118,7 +184,8 @@ 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 linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-169, inifile:
|
||||
collected 4 items
|
||||
<Module 'test_scenarios.py'>
|
||||
<Class 'TestSampleWithScenarios'>
|
||||
@@ -182,7 +249,8 @@ Let's first see how it looks like at collection time::
|
||||
|
||||
$ py.test test_backends.py --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-169, inifile:
|
||||
collected 2 items
|
||||
<Module 'test_backends.py'>
|
||||
<Function 'test_db_initialized[d1]'>
|
||||
@@ -197,7 +265,7 @@ And then when we run the test::
|
||||
================================= FAILURES =================================
|
||||
_________________________ test_db_initialized[d2] __________________________
|
||||
|
||||
db = <conftest.DB2 object at 0x2b24a8545390>
|
||||
db = <conftest.DB2 object at 0x2b160a531f98>
|
||||
|
||||
def test_db_initialized(db):
|
||||
# a dummy test
|
||||
@@ -206,7 +274,7 @@ And then when we run the test::
|
||||
E Failed: deliberately failing for demo purposes
|
||||
|
||||
test_backends.py:6: Failed
|
||||
1 failed, 1 passed in 0.02 seconds
|
||||
1 failed, 1 passed in 0.01 seconds
|
||||
|
||||
The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``db`` fixture function has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
|
||||
|
||||
@@ -253,14 +321,14 @@ argument sets to use for each test function. Let's run it::
|
||||
================================= FAILURES =================================
|
||||
________________________ TestClass.test_equals[1-2] ________________________
|
||||
|
||||
self = <test_parametrize.TestClass object at 0x2b0ed5d8cdd8>, a = 1, b = 2
|
||||
self = <test_parametrize.TestClass object at 0x2ab66352a978>, a = 1, b = 2
|
||||
|
||||
def test_equals(self, a, b):
|
||||
> assert a == b
|
||||
E assert 1 == 2
|
||||
|
||||
test_parametrize.py:18: AssertionError
|
||||
1 failed, 2 passed in 0.02 seconds
|
||||
1 failed, 2 passed in 0.01 seconds
|
||||
|
||||
Indirect parametrization with multiple fixtures
|
||||
--------------------------------------------------------------
|
||||
@@ -279,345 +347,8 @@ is to be run with different sets of arguments for its three arguments:
|
||||
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::
|
||||
|
||||
. $ py.test -rs -q multipython.py
|
||||
..................FFFFFF...
|
||||
================================= FAILURES =================================
|
||||
________________ test_basic_objects[python3.4-python2.6-42] ________________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1bc79b0>
|
||||
python2 = <multipython.Python object at 0x2b02a1bc7630>, obj = 42
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p0/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.6/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p0/load.py
|
||||
_______________ test_basic_objects[python3.4-python2.6-obj1] _______________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1b66f28>
|
||||
python2 = <multipython.Python object at 0x2b02a1b66198>, obj = {}
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p1/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.6/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p1/load.py
|
||||
_______________ test_basic_objects[python3.4-python2.6-obj2] _______________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1bcd320>
|
||||
python2 = <multipython.Python object at 0x2b02a1bcd358>, obj = {1: 3}
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.6 /tmp/pytest-21/test_basic_objects_python3_4_p2/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 1370, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.6/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.6/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p2/load.py
|
||||
________________ test_basic_objects[python3.4-python2.7-42] ________________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1bc78d0>
|
||||
python2 = <multipython.Python object at 0x2b02a1bc7128>, obj = 42
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p3/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.7/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p3/load.py
|
||||
_______________ test_basic_objects[python3.4-python2.7-obj1] _______________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1bd2550>
|
||||
python2 = <multipython.Python object at 0x2b02a1bd23c8>, obj = {}
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p4/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.7/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p4/load.py
|
||||
_______________ test_basic_objects[python3.4-python2.7-obj2] _______________
|
||||
|
||||
python1 = <multipython.Python object at 0x2b02a1bcdeb8>
|
||||
python2 = <multipython.Python object at 0x2b02a1bcdf98>, obj = {1: 3}
|
||||
|
||||
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||
def test_basic_objects(python1, python2, obj):
|
||||
python1.dumps(obj)
|
||||
> python2.load_and_is_true("obj == %s" % obj)
|
||||
|
||||
multipython.py:51:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
multipython.py:46: in load_and_is_true
|
||||
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
cmd = '/home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py'
|
||||
|
||||
def cmdexec(cmd):
|
||||
""" return unicode output of executing 'cmd' in a separate process.
|
||||
|
||||
raise cmdexec.Error exeception if the command failed.
|
||||
the exception will provide an 'err' attribute containing
|
||||
the error-output from the command.
|
||||
if the subprocess module does not provide a proper encoding/unicode strings
|
||||
sys.getdefaultencoding() will be used, if that does not exist, 'UTF-8'.
|
||||
"""
|
||||
process = subprocess.Popen(cmd, shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = process.communicate()
|
||||
if sys.version_info[0] < 3: # on py3 we get unicode strings, on py2 not
|
||||
try:
|
||||
default_encoding = sys.getdefaultencoding() # jython may not have it
|
||||
except AttributeError:
|
||||
default_encoding = sys.stdout.encoding or 'UTF-8'
|
||||
out = unicode(out, process.stdout.encoding or default_encoding)
|
||||
err = unicode(err, process.stderr.encoding or default_encoding)
|
||||
status = process.poll()
|
||||
if status:
|
||||
> raise ExecutionFailed(status, status, cmd, out, err)
|
||||
E py.process.cmdexec.Error: ExecutionFailed: 1 /home/hpk/bin/python2.7 /tmp/pytest-21/test_basic_objects_python3_4_p5/load.py
|
||||
E Traceback (most recent call last):
|
||||
E File "/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py", line 4, in <module>
|
||||
E obj = pickle.load(f)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 1378, in load
|
||||
E return Unpickler(file).load()
|
||||
E File "/usr/lib/python2.7/pickle.py", line 858, in load
|
||||
E dispatch[key](self)
|
||||
E File "/usr/lib/python2.7/pickle.py", line 886, in load_proto
|
||||
E raise ValueError, "unsupported pickle protocol: %d" % proto
|
||||
E ValueError: unsupported pickle protocol: 3
|
||||
|
||||
../../../.tox/regen/lib/python3.4/site-packages/py/_process/cmdexec.py:28: Error
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-21/test_basic_objects_python3_4_p5/load.py
|
||||
6 failed, 21 passed in 1.36 seconds
|
||||
...........................
|
||||
27 passed in 1.70 seconds
|
||||
|
||||
Indirect parametrization of optional implementations/imports
|
||||
--------------------------------------------------------------------
|
||||
@@ -664,12 +395,13 @@ If you run this with reporting for skips enabled::
|
||||
|
||||
$ py.test -rs test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-169, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s
|
||||
========================= short test summary info ==========================
|
||||
SKIP [1] /tmp/doc-exec-226/conftest.py:10: could not import 'opt2'
|
||||
SKIP [1] /tmp/doc-exec-169/conftest.py:10: could not import 'opt2'
|
||||
|
||||
=================== 1 passed, 1 skipped in 0.01 seconds ====================
|
||||
|
||||
|
||||
@@ -26,36 +26,37 @@ the :confval:`python_files`, :confval:`python_classes` and
|
||||
[pytest]
|
||||
python_files=check_*.py
|
||||
python_classes=Check
|
||||
python_functions=check
|
||||
python_functions=*_check
|
||||
|
||||
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::
|
||||
This would make ``pytest`` look for tests in files that match the ``check_*
|
||||
.py`` glob-pattern, ``Check`` prefixes in classes, and functions and methods
|
||||
that match ``*_check``. For example, if we have::
|
||||
|
||||
# content of check_myapp.py
|
||||
class CheckMyApp:
|
||||
def check_simple(self):
|
||||
def simple_check(self):
|
||||
pass
|
||||
def check_complex(self):
|
||||
def complex_check(self):
|
||||
pass
|
||||
|
||||
then the test collection looks like this::
|
||||
|
||||
$ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-170, inifile: setup.cfg
|
||||
collected 2 items
|
||||
<Module 'check_myapp.py'>
|
||||
<Class 'CheckMyApp'>
|
||||
<Instance '()'>
|
||||
<Function 'check_simple'>
|
||||
<Function 'check_complex'>
|
||||
<Function 'simple_check'>
|
||||
<Function 'complex_check'>
|
||||
|
||||
============================= in 0.01 seconds =============================
|
||||
|
||||
.. note::
|
||||
|
||||
the ``python_functions`` and ``python_classes`` has no effect
|
||||
the ``python_functions`` and ``python_classes`` options has no effect
|
||||
for ``unittest.TestCase`` test discovery because pytest delegates
|
||||
detection of test case methods to unittest code.
|
||||
|
||||
@@ -88,9 +89,10 @@ You can always peek at the collection tree without running tests like this::
|
||||
|
||||
. $ py.test --collect-only pythoncollection.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collected 3 items
|
||||
<Module 'pythoncollection.py'>
|
||||
<Module 'example/pythoncollection.py'>
|
||||
<Function 'test_function'>
|
||||
<Class 'TestClass'>
|
||||
<Instance '()'>
|
||||
@@ -141,10 +143,11 @@ interpreters and will leave out the setup.py file::
|
||||
|
||||
$ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-170, inifile: pytest.ini
|
||||
collected 0 items
|
||||
|
||||
============================= in 0.01 seconds =============================
|
||||
============================= in 0.00 seconds =============================
|
||||
|
||||
If you run with a Python3 interpreter the moduled added through the conftest.py file will not be considered for test collection.
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ get on the terminal - we are working on that):
|
||||
|
||||
assertion $ py.test failure_demo.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collected 42 items
|
||||
|
||||
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
@@ -30,7 +31,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:15: AssertionError
|
||||
_________________________ TestFailing.test_simple __________________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0x2adb9885cfd0>
|
||||
self = <failure_demo.TestFailing object at 0x2b186edcf6a0>
|
||||
|
||||
def test_simple(self):
|
||||
def f():
|
||||
@@ -40,13 +41,13 @@ get on the terminal - we are working on that):
|
||||
|
||||
> assert f() == g()
|
||||
E assert 42 == 43
|
||||
E + where 42 = <function TestFailing.test_simple.<locals>.f at 0x2adb9887e6a8>()
|
||||
E + and 43 = <function TestFailing.test_simple.<locals>.g at 0x2adb9887e598>()
|
||||
E + where 42 = <function TestFailing.test_simple.<locals>.f at 0x2b186edd09d8>()
|
||||
E + and 43 = <function TestFailing.test_simple.<locals>.g at 0x2b186edd9950>()
|
||||
|
||||
failure_demo.py:28: AssertionError
|
||||
____________________ TestFailing.test_simple_multiline _____________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0x2adb98841518>
|
||||
self = <failure_demo.TestFailing object at 0x2b186e2942e8>
|
||||
|
||||
def test_simple_multiline(self):
|
||||
otherfunc_multi(
|
||||
@@ -66,19 +67,19 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:11: AssertionError
|
||||
___________________________ TestFailing.test_not ___________________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0x2adb98813278>
|
||||
self = <failure_demo.TestFailing object at 0x2b186e270630>
|
||||
|
||||
def test_not(self):
|
||||
def f():
|
||||
return 42
|
||||
> assert not f()
|
||||
E assert not 42
|
||||
E + where 42 = <function TestFailing.test_not.<locals>.f at 0x2adb9887e840>()
|
||||
E + where 42 = <function TestFailing.test_not.<locals>.f at 0x2b186edd99d8>()
|
||||
|
||||
failure_demo.py:38: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_text _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987a9588>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186eea7048>
|
||||
|
||||
def test_eq_text(self):
|
||||
> assert 'spam' == 'eggs'
|
||||
@@ -89,7 +90,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 0x2adb9881fe80>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ed9aa58>
|
||||
|
||||
def test_eq_similar_text(self):
|
||||
> assert 'foo 1 bar' == 'foo 2 bar'
|
||||
@@ -102,7 +103,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 0x2adb98894b38>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee904a8>
|
||||
|
||||
def test_eq_multiline_text(self):
|
||||
> assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
||||
@@ -115,7 +116,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 0x2adb98812fd0>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee8d828>
|
||||
|
||||
def test_eq_long_text(self):
|
||||
a = '1'*100 + 'a' + '2'*100
|
||||
@@ -132,7 +133,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 0x2adb987ce240>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186e28cb00>
|
||||
|
||||
def test_eq_long_text_multiline(self):
|
||||
a = '1\n'*100 + 'a' + '2\n'*100
|
||||
@@ -156,17 +157,18 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:58: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_list _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98841a58>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee879b0>
|
||||
|
||||
def test_eq_list(self):
|
||||
> assert [0, 1, 2] == [0, 1, 3]
|
||||
E assert [0, 1, 2] == [0, 1, 3]
|
||||
E At index 2 diff: 2 != 3
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:61: AssertionError
|
||||
______________ TestSpecialisedExplanations.test_eq_list_long _______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987e4e48>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186e28eb70>
|
||||
|
||||
def test_eq_list_long(self):
|
||||
a = [0]*100 + [1] + [3]*100
|
||||
@@ -174,11 +176,12 @@ get on the terminal - we are working on that):
|
||||
> assert a == b
|
||||
E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
|
||||
E At index 100 diff: 1 != 2
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:66: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_dict _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98843d30>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee78860>
|
||||
|
||||
def test_eq_dict(self):
|
||||
> assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0}
|
||||
@@ -190,11 +193,12 @@ get on the terminal - we are working on that):
|
||||
E {'c': 0}
|
||||
E Right contains more items:
|
||||
E {'d': 0}
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:69: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_set __________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb98822b38>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186eea6588>
|
||||
|
||||
def test_eq_set(self):
|
||||
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
|
||||
@@ -206,21 +210,23 @@ get on the terminal - we are working on that):
|
||||
E Extra items in the right set:
|
||||
E 20
|
||||
E 21
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:72: AssertionError
|
||||
_____________ TestSpecialisedExplanations.test_eq_longer_list ______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987a96d8>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ecbdc50>
|
||||
|
||||
def test_eq_longer_list(self):
|
||||
> assert [1,2] == [1,2,3]
|
||||
E assert [1, 2] == [1, 2, 3]
|
||||
E Right contains more items, first extra item: 3
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:75: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_in_list _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2adb987b72e8>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186eeb0518>
|
||||
|
||||
def test_in_list(self):
|
||||
> assert 1 in [0, 2, 3, 4, 5]
|
||||
@@ -229,7 +235,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 0x2adb98894908>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186eeb1860>
|
||||
|
||||
def test_not_in_text_multiline(self):
|
||||
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
|
||||
@@ -247,7 +253,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 0x2adb9885c898>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee9e4a8>
|
||||
|
||||
def test_not_in_text_single(self):
|
||||
text = 'single foo line'
|
||||
@@ -260,7 +266,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 0x2adb987cc9e8>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186eea6908>
|
||||
|
||||
def test_not_in_text_single_long(self):
|
||||
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
|
||||
@@ -273,7 +279,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 0x2adb987d2748>
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0x2b186ee908d0>
|
||||
|
||||
def test_not_in_text_single_long_term(self):
|
||||
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
|
||||
@@ -292,7 +298,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.test_attribute.<locals>.Foo object at 0x2adb987b5470>.b
|
||||
E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0x2b186ee8d4e0>.b
|
||||
|
||||
failure_demo.py:101: AssertionError
|
||||
_________________________ test_attribute_instance __________________________
|
||||
@@ -302,8 +308,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.test_attribute_instance.<locals>.Foo object at 0x2adb987d0390>.b
|
||||
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2adb987d0390> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
|
||||
E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2b186eea6240>.b
|
||||
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0x2b186eea6240> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
|
||||
|
||||
failure_demo.py:107: AssertionError
|
||||
__________________________ test_attribute_failure __________________________
|
||||
@@ -319,7 +325,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:116:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0x2adb98822cf8>
|
||||
self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0x2b186ed9a4e0>
|
||||
|
||||
def _get_b(self):
|
||||
> raise Exception('Failed to get attrib')
|
||||
@@ -335,15 +341,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.test_attribute_multiple.<locals>.Foo object at 0x2adb98841dd8>.b
|
||||
E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2adb98841dd8> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
|
||||
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2adb98841a90>.b
|
||||
E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2adb98841a90> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
|
||||
E + where 1 = <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2b186ee78630>.b
|
||||
E + where <failure_demo.test_attribute_multiple.<locals>.Foo object at 0x2b186ee78630> = <class 'failure_demo.test_attribute_multiple.<locals>.Foo'>()
|
||||
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2b186ee78358>.b
|
||||
E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0x2b186ee78358> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
|
||||
|
||||
failure_demo.py:124: AssertionError
|
||||
__________________________ TestRaises.test_raises __________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0x2adb98854668>
|
||||
self = <failure_demo.TestRaises object at 0x2b186e270b38>
|
||||
|
||||
def test_raises(self):
|
||||
s = 'qwe'
|
||||
@@ -355,10 +361,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/lib/python3.4/site-packages/_pytest/python.py:1028>:1: ValueError
|
||||
<0-codegen /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1075>:1: ValueError
|
||||
______________________ TestRaises.test_raises_doesnt _______________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0x2adb988818d0>
|
||||
self = <failure_demo.TestRaises object at 0x2b186eeab2b0>
|
||||
|
||||
def test_raises_doesnt(self):
|
||||
> raises(IOError, "int('3')")
|
||||
@@ -367,7 +373,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:136: Failed
|
||||
__________________________ TestRaises.test_raise ___________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0x2adb9885cc50>
|
||||
self = <failure_demo.TestRaises object at 0x2b186ee75358>
|
||||
|
||||
def test_raise(self):
|
||||
> raise ValueError("demo error")
|
||||
@@ -376,7 +382,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:139: ValueError
|
||||
________________________ TestRaises.test_tupleerror ________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0x2adb988430b8>
|
||||
self = <failure_demo.TestRaises object at 0x2b186e285978>
|
||||
|
||||
def test_tupleerror(self):
|
||||
> a,b = [1]
|
||||
@@ -385,7 +391,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 object at 0x2adb9881fa20>
|
||||
self = <failure_demo.TestRaises object at 0x2b186edcfe48>
|
||||
|
||||
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
|
||||
l = [1,2,3]
|
||||
@@ -398,7 +404,7 @@ get on the terminal - we are working on that):
|
||||
l is [1, 2, 3]
|
||||
________________________ TestRaises.test_some_error ________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0x2adb98894a90>
|
||||
self = <failure_demo.TestRaises object at 0x2b186eeb1898>
|
||||
|
||||
def test_some_error(self):
|
||||
> if namenotexi:
|
||||
@@ -426,7 +432,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 object at 0x2adb98812da0>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186e270358>
|
||||
|
||||
def test_complex_error(self):
|
||||
def f():
|
||||
@@ -450,7 +456,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:5: AssertionError
|
||||
___________________ TestMoreErrors.test_z1_unpack_error ____________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb9884d4a8>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186ecbdba8>
|
||||
|
||||
def test_z1_unpack_error(self):
|
||||
l = []
|
||||
@@ -460,7 +466,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:179: ValueError
|
||||
____________________ TestMoreErrors.test_z2_type_error _____________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb987b52b0>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186ee78550>
|
||||
|
||||
def test_z2_type_error(self):
|
||||
l = 3
|
||||
@@ -470,19 +476,19 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:183: TypeError
|
||||
______________________ TestMoreErrors.test_startswith ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb988224e0>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186ee90978>
|
||||
|
||||
def test_startswith(self):
|
||||
s = "123"
|
||||
g = "456"
|
||||
> assert s.startswith(g)
|
||||
E assert <built-in method startswith of str object at 0x2adb987a9ca8>('456')
|
||||
E + where <built-in method startswith of str object at 0x2adb987a9ca8> = '123'.startswith
|
||||
E assert <built-in method startswith of str object at 0x2b186eea6500>('456')
|
||||
E + where <built-in method startswith of str object at 0x2b186eea6500> = '123'.startswith
|
||||
|
||||
failure_demo.py:188: AssertionError
|
||||
__________________ TestMoreErrors.test_startswith_nested ___________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb98836898>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186eeab358>
|
||||
|
||||
def test_startswith_nested(self):
|
||||
def f():
|
||||
@@ -490,15 +496,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 0x2adb987a9ca8>('456')
|
||||
E + where <built-in method startswith of str object at 0x2adb987a9ca8> = '123'.startswith
|
||||
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0x2adb9887e9d8>()
|
||||
E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0x2adb9887e7b8>()
|
||||
E assert <built-in method startswith of str object at 0x2b186eea6500>('456')
|
||||
E + where <built-in method startswith of str object at 0x2b186eea6500> = '123'.startswith
|
||||
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0x2b186eea1510>()
|
||||
E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0x2b186eea1268>()
|
||||
|
||||
failure_demo.py:195: AssertionError
|
||||
_____________________ TestMoreErrors.test_global_func ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb987b77f0>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186e28c7f0>
|
||||
|
||||
def test_global_func(self):
|
||||
> assert isinstance(globf(42), float)
|
||||
@@ -508,18 +514,18 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:198: AssertionError
|
||||
_______________________ TestMoreErrors.test_instance _______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb988729b0>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186ee759b0>
|
||||
|
||||
def test_instance(self):
|
||||
self.x = 6*7
|
||||
> assert self.x != 42
|
||||
E assert 42 != 42
|
||||
E + where 42 = <failure_demo.TestMoreErrors object at 0x2adb988729b0>.x
|
||||
E + where 42 = <failure_demo.TestMoreErrors object at 0x2b186ee759b0>.x
|
||||
|
||||
failure_demo.py:202: AssertionError
|
||||
_______________________ TestMoreErrors.test_compare ________________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb98812f98>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186ecbdf60>
|
||||
|
||||
def test_compare(self):
|
||||
> assert globf(10) < 5
|
||||
@@ -529,7 +535,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:205: AssertionError
|
||||
_____________________ TestMoreErrors.test_try_finally ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0x2adb987d0198>
|
||||
self = <failure_demo.TestMoreErrors object at 0x2b186eeb1e48>
|
||||
|
||||
def test_try_finally(self):
|
||||
x = 1
|
||||
@@ -540,7 +546,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:210: AssertionError
|
||||
___________________ TestCustomAssertMsg.test_single_line ___________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2adb98894cc0>
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2b186ed9a748>
|
||||
|
||||
def test_single_line(self):
|
||||
class A:
|
||||
@@ -554,7 +560,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:221: AssertionError
|
||||
____________________ TestCustomAssertMsg.test_multiline ____________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2adb988414e0>
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2b186ee8d630>
|
||||
|
||||
def test_multiline(self):
|
||||
class A:
|
||||
@@ -571,7 +577,7 @@ get on the terminal - we are working on that):
|
||||
failure_demo.py:227: AssertionError
|
||||
___________________ TestCustomAssertMsg.test_custom_repr ___________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2adb9885c668>
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0x2b186e270e48>
|
||||
|
||||
def test_custom_repr(self):
|
||||
class JSON:
|
||||
@@ -589,4 +595,4 @@ get on the terminal - we are working on that):
|
||||
E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a
|
||||
|
||||
failure_demo.py:237: AssertionError
|
||||
======================== 42 failed in 0.29 seconds =========================
|
||||
======================== 42 failed in 0.22 seconds =========================
|
||||
|
||||
@@ -55,7 +55,7 @@ Let's run this without supplying our new option::
|
||||
test_sample.py:6: AssertionError
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
first
|
||||
1 failed in 0.02 seconds
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
And now with supplying a command line option::
|
||||
|
||||
@@ -108,9 +108,10 @@ directory with the above conftest.py::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 0 items
|
||||
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
|
||||
.. _`excontrolskip`:
|
||||
@@ -152,12 +153,13 @@ 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 linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s
|
||||
========================= short test summary info ==========================
|
||||
SKIP [1] /tmp/doc-exec-229/conftest.py:9: need --runslow option to run
|
||||
SKIP [1] /tmp/doc-exec-172/conftest.py:9: need --runslow option to run
|
||||
|
||||
=================== 1 passed, 1 skipped in 0.01 seconds ====================
|
||||
|
||||
@@ -165,11 +167,12 @@ Or run it including the ``slow`` marked test::
|
||||
|
||||
$ py.test --runslow
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 2 items
|
||||
|
||||
|
||||
test_module.py ..
|
||||
|
||||
|
||||
========================= 2 passed in 0.01 seconds =========================
|
||||
|
||||
Writing well integrated assertion helpers
|
||||
@@ -256,10 +259,11 @@ which will add the string to the test header accordingly::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
project deps: mylib-1.1
|
||||
collected 0 items
|
||||
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
|
||||
.. regendoc:wipe
|
||||
@@ -279,20 +283,22 @@ which will add info only when run with "--v"::
|
||||
|
||||
$ py.test -v
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
info1: did you know that ...
|
||||
did you?
|
||||
collecting ... collected 0 items
|
||||
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
|
||||
and nothing when run plainly::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 0 items
|
||||
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
|
||||
profiling test duration
|
||||
@@ -322,7 +328,8 @@ Now we can profile which test functions execute the slowest::
|
||||
|
||||
$ py.test --durations=3
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 3 items
|
||||
|
||||
test_some_are_slow.py ...
|
||||
@@ -330,8 +337,8 @@ Now we can profile which test functions execute the slowest::
|
||||
========================= slowest 3 test durations =========================
|
||||
0.20s call test_some_are_slow.py::test_funcslow2
|
||||
0.10s call test_some_are_slow.py::test_funcslow1
|
||||
0.00s teardown test_some_are_slow.py::test_funcslow1
|
||||
========================= 3 passed in 0.32 seconds =========================
|
||||
0.00s setup test_some_are_slow.py::test_funcslow2
|
||||
========================= 3 passed in 0.31 seconds =========================
|
||||
|
||||
incremental testing - test steps
|
||||
---------------------------------------------------
|
||||
@@ -383,7 +390,8 @@ If we run this::
|
||||
|
||||
$ py.test -rx
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 4 items
|
||||
|
||||
test_step.py .Fx.
|
||||
@@ -391,7 +399,7 @@ If we run this::
|
||||
================================= FAILURES =================================
|
||||
____________________ TestUserHandling.test_modification ____________________
|
||||
|
||||
self = <test_step.TestUserHandling object at 0x2af9f0d94470>
|
||||
self = <test_step.TestUserHandling object at 0x2b9ab60ccfd0>
|
||||
|
||||
def test_modification(self):
|
||||
> assert 0
|
||||
@@ -453,7 +461,8 @@ We can run this::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 7 items
|
||||
|
||||
test_step.py .Fx.
|
||||
@@ -463,17 +472,17 @@ We can run this::
|
||||
|
||||
================================== ERRORS ==================================
|
||||
_______________________ ERROR at setup of test_root ________________________
|
||||
file /tmp/doc-exec-229/b/test_error.py, line 1
|
||||
file /tmp/doc-exec-172/b/test_error.py, line 1
|
||||
def test_root(db): # no db here, will error out
|
||||
fixture 'db' not found
|
||||
available fixtures: capsys, pytestconfig, monkeypatch, tmpdir, recwarn, capfd
|
||||
available fixtures: pytestconfig, tmpdir, monkeypatch, capfd, recwarn, capsys
|
||||
use 'py.test --fixtures [testpath]' for help on them.
|
||||
|
||||
/tmp/doc-exec-229/b/test_error.py:1
|
||||
/tmp/doc-exec-172/b/test_error.py:1
|
||||
================================= FAILURES =================================
|
||||
____________________ TestUserHandling.test_modification ____________________
|
||||
|
||||
self = <test_step.TestUserHandling object at 0x2b0f0e2ff0b8>
|
||||
self = <test_step.TestUserHandling object at 0x2aec569b87b8>
|
||||
|
||||
def test_modification(self):
|
||||
> assert 0
|
||||
@@ -482,25 +491,25 @@ We can run this::
|
||||
test_step.py:9: AssertionError
|
||||
_________________________________ test_a1 __________________________________
|
||||
|
||||
db = <conftest.DB object at 0x2b0f0e2ff630>
|
||||
db = <conftest.DB object at 0x2aec569d1588>
|
||||
|
||||
def test_a1(db):
|
||||
> assert 0, db # to show value
|
||||
E AssertionError: <conftest.DB object at 0x2b0f0e2ff630>
|
||||
E AssertionError: <conftest.DB object at 0x2aec569d1588>
|
||||
E assert 0
|
||||
|
||||
a/test_db.py:2: AssertionError
|
||||
_________________________________ test_a2 __________________________________
|
||||
|
||||
db = <conftest.DB object at 0x2b0f0e2ff630>
|
||||
db = <conftest.DB object at 0x2aec569d1588>
|
||||
|
||||
def test_a2(db):
|
||||
> assert 0, db # to show value
|
||||
E AssertionError: <conftest.DB object at 0x2b0f0e2ff630>
|
||||
E AssertionError: <conftest.DB object at 0x2aec569d1588>
|
||||
E assert 0
|
||||
|
||||
a/test_db2.py:2: AssertionError
|
||||
========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.04 seconds ==========
|
||||
========== 3 failed, 2 passed, 1 xfailed, 1 error in 0.03 seconds ==========
|
||||
|
||||
The two test modules in the ``a`` directory see the same ``db`` fixture instance
|
||||
while the one test in the sister-directory ``b`` doesn't see it. We could of course
|
||||
@@ -555,7 +564,8 @@ and run them::
|
||||
|
||||
$ py.test test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -563,7 +573,7 @@ and run them::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_fail1 ________________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-22/test_fail10')
|
||||
tmpdir = local('/tmp/pytest-219/test_fail10')
|
||||
|
||||
def test_fail1(tmpdir):
|
||||
> assert 0
|
||||
@@ -582,7 +592,7 @@ and run them::
|
||||
you will have a "failures" file which contains the failing test ids::
|
||||
|
||||
$ cat failures
|
||||
test_module.py::test_fail1 (/tmp/pytest-22/test_fail10)
|
||||
test_module.py::test_fail1 (/tmp/pytest-219/test_fail10)
|
||||
test_module.py::test_fail2
|
||||
|
||||
Making test result information available in fixtures
|
||||
@@ -645,7 +655,8 @@ and run it::
|
||||
|
||||
$ py.test -s test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-172, inifile:
|
||||
collected 3 items
|
||||
|
||||
test_module.py Esetting up a test failed! test_module.py::test_setup_fails
|
||||
|
||||
@@ -69,4 +69,4 @@ If you run this without output capturing::
|
||||
.test other
|
||||
.test_unit1 method called
|
||||
.
|
||||
4 passed in 0.05 seconds
|
||||
4 passed in 0.04 seconds
|
||||
|
||||
@@ -30,15 +30,15 @@ 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
|
||||
<http://pypi.python.org/pypi/pytest-twisted>`_ plugin which allows you to
|
||||
return deferreds from pytest-style tests, allowing the use of
|
||||
:ref:`fixtures` and other features.
|
||||
|
||||
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
|
||||
``manage.py test`` and allows to use all pytest features_ most of which
|
||||
``manage.py test`` and allows the use of all pytest features_ most of which
|
||||
are not available from Django directly.
|
||||
|
||||
.. _features: features.html
|
||||
@@ -49,7 +49,7 @@ What's this "magic" with pytest? (historic notes)
|
||||
|
||||
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
|
||||
contains a lot of unrelated python library code. Around 2010 there
|
||||
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 release also brought a complete pluginification
|
||||
@@ -63,7 +63,7 @@ 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.
|
||||
It also means, that you can use Python's ``-O`` optimization without loosing
|
||||
It also means, that you can use Python's ``-O`` optimization without losing
|
||||
assertions in test modules.
|
||||
|
||||
``pytest`` contains a second, mostly obsolete, assert debugging technique,
|
||||
@@ -152,13 +152,13 @@ pytest interaction with other packages
|
||||
Issues with pytest, multiprocess and setuptools?
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
On windows the multiprocess package will instantiate sub processes
|
||||
On Windows the multiprocess package will instantiate sub processes
|
||||
by pickling and thus implicitly re-import a lot of local modules.
|
||||
Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'``
|
||||
protect its generated command line script. This leads to infinite
|
||||
recursion when running a test that instantiates Processes.
|
||||
|
||||
As of middle 2013, there shouldn't be a problem anymore when you
|
||||
As of mid-2013, there shouldn't be a problem anymore when you
|
||||
use the standard setuptools (note that distribute has been merged
|
||||
back into setuptools which is now shipped directly with virtualenv).
|
||||
|
||||
|
||||
@@ -67,7 +67,6 @@ using it::
|
||||
def test_ehlo(smtp):
|
||||
response, msg = smtp.ehlo()
|
||||
assert response == 250
|
||||
assert "merlinux" in msg
|
||||
assert 0 # for demo purposes
|
||||
|
||||
Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
|
||||
@@ -76,7 +75,8 @@ marked ``smtp`` fixture function. Running the test looks like this::
|
||||
|
||||
$ py.test test_smtpsimple.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-109, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_smtpsimple.py F
|
||||
@@ -84,16 +84,16 @@ marked ``smtp`` fixture function. Running the test looks like this::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_ehlo _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2b040fa62128>
|
||||
smtp = <smtplib.SMTP object at 0x2b058f0f53c8>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response, msg = smtp.ehlo()
|
||||
assert response == 250
|
||||
> assert "merlinux" in msg
|
||||
E TypeError: Type str doesn't support the buffer API
|
||||
> assert 0 # for demo purposes
|
||||
E assert 0
|
||||
|
||||
test_smtpsimple.py:11: TypeError
|
||||
========================= 1 failed in 0.20 seconds =========================
|
||||
test_smtpsimple.py:11: AssertionError
|
||||
========================= 1 failed in 0.17 seconds =========================
|
||||
|
||||
In the failure traceback we see that the test function was called with a
|
||||
``smtp`` argument, the ``smtplib.SMTP()`` instance created by the fixture
|
||||
@@ -193,7 +193,8 @@ inspect what is going on and can now run the tests::
|
||||
|
||||
$ py.test test_module.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-109, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF
|
||||
@@ -201,7 +202,7 @@ inspect what is going on and can now run the tests::
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_ehlo _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2abe3c757208>
|
||||
smtp = <smtplib.SMTP object at 0x2aec79533a58>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -212,7 +213,7 @@ inspect what is going on and can now run the tests::
|
||||
test_module.py:5: TypeError
|
||||
________________________________ test_noop _________________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2abe3c757208>
|
||||
smtp = <smtplib.SMTP object at 0x2aec79533a58>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -221,7 +222,7 @@ inspect what is going on and can now run the tests::
|
||||
E assert 0
|
||||
|
||||
test_module.py:11: AssertionError
|
||||
========================= 2 failed in 0.17 seconds =========================
|
||||
========================= 2 failed in 0.20 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
|
||||
@@ -269,7 +270,7 @@ Let's execute it::
|
||||
$ py.test -s -q --tb=no
|
||||
FFteardown smtp
|
||||
|
||||
2 failed in 0.16 seconds
|
||||
2 failed in 0.25 seconds
|
||||
|
||||
We see that the ``smtp`` instance is finalized after the two
|
||||
tests finished execution. Note that if we decorated our fixture
|
||||
@@ -310,7 +311,7 @@ again, nothing much has changed::
|
||||
|
||||
$ py.test -s -q --tb=no
|
||||
FF
|
||||
2 failed in 0.16 seconds
|
||||
2 failed in 0.17 seconds
|
||||
|
||||
Let's quickly create another test module that actually sets the
|
||||
server URL in its module namespace::
|
||||
@@ -378,7 +379,7 @@ So let's just do another run::
|
||||
================================= FAILURES =================================
|
||||
__________________________ test_ehlo[merlinux.eu] __________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2afbf4496828>
|
||||
smtp = <smtplib.SMTP object at 0x2b4ce634f828>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -389,7 +390,7 @@ So let's just do another run::
|
||||
test_module.py:5: TypeError
|
||||
__________________________ test_noop[merlinux.eu] __________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2afbf4496828>
|
||||
smtp = <smtplib.SMTP object at 0x2b4ce634f828>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -400,7 +401,7 @@ So let's just do another run::
|
||||
test_module.py:11: AssertionError
|
||||
________________________ test_ehlo[mail.python.org] ________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2afbf4496d68>
|
||||
smtp = <smtplib.SMTP object at 0x2b4ce634f7f0>
|
||||
|
||||
def test_ehlo(smtp):
|
||||
response = smtp.ehlo()
|
||||
@@ -410,10 +411,10 @@ So let's just do another run::
|
||||
|
||||
test_module.py:5: TypeError
|
||||
-------------------------- Captured stdout setup ---------------------------
|
||||
finalizing <smtplib.SMTP object at 0x2afbf4496828>
|
||||
finalizing <smtplib.SMTP object at 0x2b4ce634f828>
|
||||
________________________ test_noop[mail.python.org] ________________________
|
||||
|
||||
smtp = <smtplib.SMTP object at 0x2afbf4496d68>
|
||||
smtp = <smtplib.SMTP object at 0x2b4ce634f7f0>
|
||||
|
||||
def test_noop(smtp):
|
||||
response = smtp.noop()
|
||||
@@ -422,13 +423,70 @@ So let's just do another run::
|
||||
E assert 0
|
||||
|
||||
test_module.py:11: AssertionError
|
||||
4 failed in 6.02 seconds
|
||||
4 failed in 6.70 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
|
||||
different server string is expected than what arrived.
|
||||
|
||||
pytest will build a string that is the test ID for each fixture value
|
||||
in a parametrized fixture, e.g. ``test_ehlo[merlinux.eu]`` and
|
||||
``test_ehlo[mail.python.org]`` in the above examples. These IDs can
|
||||
be used with ``-k`` to select specific cases to run, and they will
|
||||
also identify the specific case when one is failing. Running pytest
|
||||
with ``--collect-only`` will show the generated IDs.
|
||||
|
||||
Numbers, strings, booleans and None will have their usual string
|
||||
representation used in the test ID. For other objects, pytest will
|
||||
make a string based on the argument name. It is possible to customise
|
||||
the string used in a test ID for a certain fixture value by using the
|
||||
``ids`` keyword argument::
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(params=[0, 1], ids=["spam", "ham"])
|
||||
def a(request):
|
||||
return request.param
|
||||
|
||||
def test_a(a):
|
||||
pass
|
||||
|
||||
def idfn(fixture_value):
|
||||
if fixture_value == 0:
|
||||
return "eggs"
|
||||
else:
|
||||
return None
|
||||
|
||||
@pytest.fixture(params=[0, 1], ids=idfn)
|
||||
def b(request):
|
||||
return request.param
|
||||
|
||||
def test_b(b):
|
||||
pass
|
||||
|
||||
The above shows how ``ids`` can be either a list of strings to use or
|
||||
a function which will be called with the fixture value and then
|
||||
has to return a string to use. In the latter case if the function
|
||||
return ``None`` then pytest's auto-generated ID will be used.
|
||||
|
||||
Running the above tests results in the following test IDs being used::
|
||||
|
||||
$ py.test --collect-only
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-109, inifile:
|
||||
collected 6 items
|
||||
<Module 'test_anothersmtp.py'>
|
||||
<Function 'test_showhelo[merlinux.eu]'>
|
||||
<Function 'test_showhelo[mail.python.org]'>
|
||||
<Module 'test_module.py'>
|
||||
<Function 'test_ehlo[merlinux.eu]'>
|
||||
<Function 'test_noop[merlinux.eu]'>
|
||||
<Function 'test_ehlo[mail.python.org]'>
|
||||
<Function 'test_noop[mail.python.org]'>
|
||||
|
||||
============================= in 0.01 seconds =============================
|
||||
|
||||
.. _`interdependent fixtures`:
|
||||
|
||||
@@ -462,13 +520,14 @@ Here we declare an ``app`` fixture which receives the previously defined
|
||||
|
||||
$ py.test -v test_appsetup.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-109, inifile:
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_appsetup.py::test_smtp_exists[merlinux.eu] PASSED
|
||||
test_appsetup.py::test_smtp_exists[mail.python.org] PASSED
|
||||
|
||||
========================= 2 passed in 5.45 seconds =========================
|
||||
========================= 2 passed in 6.53 seconds =========================
|
||||
|
||||
Due to the parametrization of ``smtp`` the test will run twice with two
|
||||
different ``App`` instances and respective smtp servers. There is no
|
||||
@@ -526,7 +585,8 @@ 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 linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0 -- /home/hpk/p/pytest/.tox/regen/bin/python3.4
|
||||
rootdir: /tmp/doc-exec-109, inifile:
|
||||
collecting ... collected 8 items
|
||||
|
||||
test_module.py::test_0[1] test0 1
|
||||
@@ -725,4 +785,182 @@ to a :ref:`conftest.py <conftest.py>` file or even separately installable
|
||||
fixtures functions starts at test classes, then test modules, then
|
||||
``conftest.py`` files and finally builtin and third party plugins.
|
||||
|
||||
Overriding fixtures on various levels
|
||||
-------------------------------------
|
||||
|
||||
In relatively large test suite, you most likely need to ``override`` a ``global`` or ``root`` fixture with a ``locally``
|
||||
defined one, keeping the test code readable and maintainable.
|
||||
|
||||
Override a fixture on a folder (conftest) level
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Given the tests file structure is:
|
||||
|
||||
::
|
||||
|
||||
tests/
|
||||
__init__.py
|
||||
|
||||
conftest.py
|
||||
# content of tests/conftest.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username():
|
||||
return 'username'
|
||||
|
||||
test_something.py
|
||||
# content of tests/test_something.py
|
||||
def test_username(username):
|
||||
assert username == 'username'
|
||||
|
||||
subfolder/
|
||||
__init__.py
|
||||
|
||||
conftest.py
|
||||
# content of tests/subfolder/conftest.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username(username):
|
||||
return 'overridden-' + username
|
||||
|
||||
test_something.py
|
||||
# content of tests/subfolder/test_something.py
|
||||
def test_username(username):
|
||||
assert username == 'overridden-username'
|
||||
|
||||
As you can see, a fixture with the same name can be overridden for certain test folder level.
|
||||
Note that the ``base`` or ``super`` fixture can be accessed from the ``overriding``
|
||||
fixture easily - used in the example above.
|
||||
|
||||
Override a fixture on a test module level
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Given the tests file structure is:
|
||||
|
||||
::
|
||||
|
||||
tests/
|
||||
__init__.py
|
||||
|
||||
conftest.py
|
||||
# content of tests/conftest.py
|
||||
@pytest.fixture
|
||||
def username():
|
||||
return 'username'
|
||||
|
||||
test_something.py
|
||||
# content of tests/test_something.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username(username):
|
||||
return 'overridden-' + username
|
||||
|
||||
def test_username(username):
|
||||
assert username == 'overridden-username'
|
||||
|
||||
test_something_else.py
|
||||
# content of tests/test_something_else.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username(username):
|
||||
return 'overridden-else-' + username
|
||||
|
||||
def test_username(username):
|
||||
assert username == 'overridden-else-username'
|
||||
|
||||
In the example above, a fixture with the same name can be overridden for certain test module.
|
||||
|
||||
|
||||
Override a fixture with direct test parametrization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Given the tests file structure is:
|
||||
|
||||
::
|
||||
|
||||
tests/
|
||||
__init__.py
|
||||
|
||||
conftest.py
|
||||
# content of tests/conftest.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username():
|
||||
return 'username'
|
||||
|
||||
@pytest.fixture
|
||||
def other_username(username):
|
||||
return 'other-' + username
|
||||
|
||||
test_something.py
|
||||
# content of tests/test_something.py
|
||||
import pytest
|
||||
|
||||
@pytest.mark.parametrize('username', ['directly-overridden-username'])
|
||||
def test_username(username):
|
||||
assert username == 'directly-overridden-username'
|
||||
|
||||
@pytest.mark.parametrize('username', ['directly-overridden-username-other'])
|
||||
def test_username_other(other_username):
|
||||
assert username == 'other-directly-overridden-username-other'
|
||||
|
||||
In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture
|
||||
can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype).
|
||||
|
||||
|
||||
Override a parametrized fixture with non-parametrized one and vice versa
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Given the tests file structure is:
|
||||
|
||||
::
|
||||
|
||||
tests/
|
||||
__init__.py
|
||||
|
||||
conftest.py
|
||||
# content of tests/conftest.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(params=['one', 'two', 'three'])
|
||||
def parametrized_username(request):
|
||||
return request.param
|
||||
|
||||
@pytest.fixture
|
||||
def non_parametrized_username(request):
|
||||
return 'username'
|
||||
|
||||
test_something.py
|
||||
# content of tests/test_something.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def parametrized_username():
|
||||
return 'overridden-username'
|
||||
|
||||
@pytest.fixture(params=['one', 'two', 'three'])
|
||||
def non_parametrized_username(request):
|
||||
return request.param
|
||||
|
||||
def test_username(parametrized_username):
|
||||
assert parametrized_username == 'overridden-username'
|
||||
|
||||
def test_parametrized_username(non_parametrized_username):
|
||||
assert non_parametrized_username in ['one', 'two', 'three']
|
||||
|
||||
test_something_else.py
|
||||
# content of tests/test_something_else.py
|
||||
def test_username(parametrized_username):
|
||||
assert parametrized_username in ['one', 'two', 'three']
|
||||
|
||||
def test_username(non_parametrized_username):
|
||||
assert non_parametrized_username == 'username'
|
||||
|
||||
In the example above, a parametrized fixture is overridden with a non-parametrized version, and
|
||||
a non-parametrized fixture is overridden with a parametrized version for certain test module.
|
||||
The same applies for the test folder level obviously.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Installation and Getting Started
|
||||
===================================
|
||||
|
||||
**Pythons**: Python 2.6-3.4, Jython, PyPy-2.3
|
||||
**Pythons**: Python 2.6,2.7,3.3,3.4, Jython, PyPy-2.3
|
||||
|
||||
**Platforms**: Unix/Posix and Windows
|
||||
|
||||
@@ -27,7 +27,7 @@ Installation options::
|
||||
To check your installation has installed the correct version::
|
||||
|
||||
$ py.test --version
|
||||
This is pytest version 2.6.3, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py
|
||||
This is pytest version 2.7.0, imported from /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/pytest.py
|
||||
|
||||
If you get an error checkout :ref:`installation issues`.
|
||||
|
||||
@@ -49,7 +49,8 @@ That's it. You can execute the test function now::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-112, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_sample.py F
|
||||
@@ -127,7 +128,7 @@ run the module by passing its filename::
|
||||
================================= FAILURES =================================
|
||||
____________________________ TestClass.test_two ____________________________
|
||||
|
||||
self = <test_class.TestClass object at 0x2b39478f7438>
|
||||
self = <test_class.TestClass object at 0x2ad6b3a6f278>
|
||||
|
||||
def test_two(self):
|
||||
x = "hello"
|
||||
@@ -163,7 +164,7 @@ before performing the test function call. Let's just run it::
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_needsfiles ______________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-18/test_needsfiles0')
|
||||
tmpdir = local('/tmp/pytest-215/test_needsfiles0')
|
||||
|
||||
def test_needsfiles(tmpdir):
|
||||
print (tmpdir)
|
||||
@@ -172,7 +173,7 @@ before performing the test function call. Let's just run it::
|
||||
|
||||
test_tmpdir.py:3: AssertionError
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
/tmp/pytest-18/test_needsfiles0
|
||||
/tmp/pytest-215/test_needsfiles0
|
||||
1 failed in 0.01 seconds
|
||||
|
||||
Before the test runs, a unique-per-test-invocation temporary directory
|
||||
|
||||
@@ -194,7 +194,8 @@ this to your ``setup.py`` file::
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
import sys,subprocess
|
||||
import subprocess
|
||||
import sys
|
||||
errno = subprocess.call([sys.executable, 'runtests.py'])
|
||||
raise SystemExit(errno)
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
|
||||
.. _features:
|
||||
|
||||
.. note::
|
||||
|
||||
next training: `professional testing with pytest and tox <http://www.python-academy.com/courses/specialtopics/python_course_testing.html>`_, 24-26th November 2014, Freiburg, Germany
|
||||
Are you an experienced pytest user, or an open source project that needs some help getting started with pytest? **April 2015** is `adopt pytest month`_!
|
||||
|
||||
|
||||
.. _`adopt pytest month`: adopt.html
|
||||
pytest: helps you write better programs
|
||||
=============================================
|
||||
|
||||
@@ -31,7 +31,7 @@ pytest: helps you write better programs
|
||||
**scales from simple unit to complex functional testing**
|
||||
|
||||
- :ref:`modular parametrizeable fixtures <fixture>` (new in 2.3,
|
||||
continously improved)
|
||||
continuously improved)
|
||||
- :ref:`parametrized test functions <parametrized test functions>`
|
||||
- :ref:`mark`
|
||||
- :ref:`skipping` (improved in 2.4)
|
||||
|
||||
@@ -57,7 +57,7 @@ so that any attempts within tests to create http requests will fail.
|
||||
example: setting an attribute on some class
|
||||
------------------------------------------------------
|
||||
|
||||
If you need to patch out ``os.getcwd()`` to return an artifical
|
||||
If you need to patch out ``os.getcwd()`` to return an artificial
|
||||
value::
|
||||
|
||||
def test_some_interaction(monkeypatch):
|
||||
|
||||
@@ -39,13 +39,13 @@ Unsupported idioms / known issues
|
||||
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
|
||||
plain classes please post `to this issue
|
||||
<https://bitbucket.org/hpk42/pytest/issue/377/>`_.
|
||||
<https://bitbucket.org/pytest-dev/pytest/issue/377/>`_.
|
||||
|
||||
- nose imports test modules with the same import path (e.g.
|
||||
``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/pytest-dev/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,
|
||||
|
||||
@@ -53,7 +53,8 @@ them in turn::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-120, inifile:
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..F
|
||||
@@ -100,12 +101,13 @@ Let's run this::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-120, inifile:
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..x
|
||||
|
||||
=================== 2 passed, 1 xfailed in 0.02 seconds ====================
|
||||
=================== 2 passed, 1 xfailed in 0.01 seconds ====================
|
||||
|
||||
The one parameter set which caused a failure previously now
|
||||
shows up as an "xfailed (expected to fail)" test.
|
||||
@@ -170,8 +172,8 @@ Let's also run with a stringinput that will lead to a failing test::
|
||||
|
||||
def test_valid_string(stringinput):
|
||||
> assert stringinput.isalpha()
|
||||
E assert <built-in method isalpha of str object at 0x2b1c6de5bb20>()
|
||||
E + where <built-in method isalpha of str object at 0x2b1c6de5bb20> = '!'.isalpha
|
||||
E assert <built-in method isalpha of str object at 0x2ae1375d9810>()
|
||||
E + where <built-in method isalpha of str object at 0x2ae1375d9810> = '!'.isalpha
|
||||
|
||||
test_strings.py:3: AssertionError
|
||||
1 failed in 0.01 seconds
|
||||
@@ -185,8 +187,8 @@ listlist::
|
||||
$ py.test -q -rs test_strings.py
|
||||
s
|
||||
========================= short test summary info ==========================
|
||||
SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1139: got empty parameter set, function test_valid_string at /tmp/doc-exec-180/test_strings.py:1
|
||||
1 skipped in 0.01 seconds
|
||||
SKIP [1] /home/hpk/p/pytest/.tox/regen/lib/python3.4/site-packages/_pytest/python.py:1185: got empty parameter set, function test_valid_string at /tmp/doc-exec-120/test_strings.py:1
|
||||
1 skipped in 0.00 seconds
|
||||
|
||||
For further examples, you might want to look at :ref:`more
|
||||
parametrization examples <paramexamples>`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _plugins:
|
||||
|
||||
Working with plugins and conftest files
|
||||
=============================================
|
||||
=======================================
|
||||
|
||||
``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:
|
||||
|
||||
@@ -9,14 +9,14 @@ Working with plugins and conftest files
|
||||
* `external plugins`_: modules discovered through `setuptools entry points`_
|
||||
* `conftest.py plugins`_: modules auto-discovered in test directories
|
||||
|
||||
.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/
|
||||
.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/
|
||||
.. _`conftest.py plugins`:
|
||||
.. _`conftest.py`:
|
||||
.. _`localplugin`:
|
||||
.. _`conftest`:
|
||||
|
||||
conftest.py: local per-directory plugins
|
||||
--------------------------------------------------------------
|
||||
----------------------------------------
|
||||
|
||||
local ``conftest.py`` plugins contain directory-specific hook
|
||||
implementations. Session and test running activities will
|
||||
@@ -29,7 +29,7 @@ and content of files::
|
||||
# called for running each test in 'a' directory
|
||||
print ("setting up", item)
|
||||
|
||||
a/test_in_subdir.py:
|
||||
a/test_sub.py:
|
||||
def test_sub():
|
||||
pass
|
||||
|
||||
@@ -55,7 +55,7 @@ Here is how you might run it::
|
||||
.. _`extplugins`:
|
||||
|
||||
Installing External Plugins / Searching
|
||||
------------------------------------------------------
|
||||
---------------------------------------
|
||||
|
||||
Installing a plugin happens through any usual Python installation
|
||||
tool, for example::
|
||||
@@ -112,17 +112,17 @@ for some popular plugins:
|
||||
|
||||
To see a complete list of all plugins with their latest testing
|
||||
status against different py.test and Python versions, please visit
|
||||
`pytest-plugs <http://pytest-plugs.herokuapp.com/>`_.
|
||||
`plugincompat <http://plugincompat.herokuapp.com/>`_.
|
||||
|
||||
You may also discover more plugins through a `pytest- pypi.python.org search`_.
|
||||
|
||||
.. _`available installable plugins`:
|
||||
.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
|
||||
|
||||
Writing a plugin by looking at examples
|
||||
------------------------------------------------------
|
||||
|
||||
.. _`Distribute`: http://pypi.python.org/pypi/distribute
|
||||
Writing a plugin by looking at examples
|
||||
---------------------------------------
|
||||
|
||||
.. _`setuptools`: http://pypi.python.org/pypi/setuptools
|
||||
|
||||
If you want to write a plugin, there are many real-life examples
|
||||
@@ -135,18 +135,22 @@ you can copy from:
|
||||
All of these plugins implement the documented `well specified hooks`_
|
||||
to extend and add functionality.
|
||||
|
||||
You can also :ref:`contribute your plugin to pytest-dev<submitplugin>`
|
||||
once it has some happy users other than yourself.
|
||||
|
||||
|
||||
.. _`setuptools entry points`:
|
||||
|
||||
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 ``pytest`` finds your plugin module. Entry points are
|
||||
a feature that is provided by `setuptools`_ or `Distribute`_.
|
||||
pytest looks up the ``pytest11`` entrypoint to discover its
|
||||
a feature that is provided by `setuptools`_. 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:
|
||||
it in your setuptools-invocation:
|
||||
|
||||
.. sourcecode:: python
|
||||
|
||||
@@ -169,10 +173,11 @@ If a package is installed this way, ``pytest`` will load
|
||||
``myproject.pluginmodule`` as a plugin which can define
|
||||
`well specified hooks`_.
|
||||
|
||||
|
||||
.. _`pluginorder`:
|
||||
|
||||
Plugin discovery order at tool startup
|
||||
--------------------------------------------
|
||||
--------------------------------------
|
||||
|
||||
``pytest`` loads plugin modules at tool startup in the following way:
|
||||
|
||||
@@ -187,8 +192,8 @@ Plugin discovery order 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.
|
||||
- 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
|
||||
@@ -199,7 +204,7 @@ Plugin discovery order at tool startup
|
||||
|
||||
|
||||
Requiring/Loading plugins in a test module or conftest file
|
||||
-------------------------------------------------------------
|
||||
-----------------------------------------------------------
|
||||
|
||||
You can require plugins in a test module or a conftest file like this::
|
||||
|
||||
@@ -214,7 +219,7 @@ which will import the specified module as a ``pytest`` plugin.
|
||||
|
||||
|
||||
Accessing another plugin by name
|
||||
--------------------------------------------
|
||||
--------------------------------
|
||||
|
||||
If a plugin wants to collaborate with code from
|
||||
another plugin it can obtain a reference through
|
||||
@@ -230,7 +235,7 @@ the ``--traceconfig`` option.
|
||||
.. _`findpluginname`:
|
||||
|
||||
Finding out which plugins are active
|
||||
----------------------------------------------------------------------------
|
||||
------------------------------------
|
||||
|
||||
If you want to find out which plugins are active in your
|
||||
environment you can type::
|
||||
@@ -244,7 +249,7 @@ and their names. It will also print local plugins aka
|
||||
.. _`cmdunregister`:
|
||||
|
||||
Deactivating / unregistering a plugin by name
|
||||
----------------------------------------------------------------------------
|
||||
---------------------------------------------
|
||||
|
||||
You can prevent plugins from loading or unregister them::
|
||||
|
||||
@@ -257,11 +262,11 @@ how to obtain the name of a plugin.
|
||||
.. _`builtin plugins`:
|
||||
|
||||
pytest default plugin reference
|
||||
====================================
|
||||
===============================
|
||||
|
||||
|
||||
You can find the source code for the following plugins
|
||||
in the `pytest repository <http://bitbucket.org/hpk42/pytest/>`_.
|
||||
in the `pytest repository <http://bitbucket.org/pytest-dev/pytest/>`_.
|
||||
|
||||
.. autosummary::
|
||||
|
||||
@@ -291,10 +296,10 @@ in the `pytest repository <http://bitbucket.org/hpk42/pytest/>`_.
|
||||
.. _`well specified hooks`:
|
||||
|
||||
pytest hook reference
|
||||
====================================
|
||||
=====================
|
||||
|
||||
Hook specification and validation
|
||||
-----------------------------------------
|
||||
---------------------------------
|
||||
|
||||
``pytest`` calls hook functions to implement initialization, running,
|
||||
test execution and reporting. When ``pytest`` loads a plugin it validates
|
||||
@@ -305,7 +310,7 @@ by simply not specifying them. If you mistype argument names or the
|
||||
hook name itself you get an error showing the available arguments.
|
||||
|
||||
Initialization, command line and configuration hooks
|
||||
--------------------------------------------------------------------
|
||||
----------------------------------------------------
|
||||
|
||||
.. currentmodule:: _pytest.hookspec
|
||||
|
||||
@@ -319,7 +324,7 @@ Initialization, command line and configuration hooks
|
||||
.. autofunction:: pytest_unconfigure
|
||||
|
||||
Generic "runtest" hooks
|
||||
------------------------------
|
||||
-----------------------
|
||||
|
||||
All runtest related hooks receive a :py:class:`pytest.Item` object.
|
||||
|
||||
@@ -339,7 +344,7 @@ The :py:mod:`_pytest.terminal` reported specifically uses
|
||||
the reporting hook to print information about a test run.
|
||||
|
||||
Collection hooks
|
||||
------------------------------
|
||||
----------------
|
||||
|
||||
``pytest`` calls the following hooks for collecting files and directories:
|
||||
|
||||
@@ -359,7 +364,7 @@ items, delete or otherwise amend the test items:
|
||||
.. autofunction:: pytest_collection_modifyitems
|
||||
|
||||
Reporting hooks
|
||||
------------------------------
|
||||
---------------
|
||||
|
||||
Session related reporting hooks:
|
||||
|
||||
@@ -375,7 +380,7 @@ test execution:
|
||||
|
||||
|
||||
Debugging/Interaction hooks
|
||||
--------------------------------------
|
||||
---------------------------
|
||||
|
||||
There are few hooks which can be used for special
|
||||
reporting or interaction with exceptions:
|
||||
@@ -384,8 +389,91 @@ reporting or interaction with exceptions:
|
||||
.. autofunction:: pytest_keyboard_interrupt
|
||||
.. autofunction:: pytest_exception_interact
|
||||
|
||||
|
||||
Declaring new hooks
|
||||
------------------------
|
||||
|
||||
Plugins and ``conftest.py`` files may declare new hooks that can then be
|
||||
implemented by other plugins in order to alter behaviour or interact with
|
||||
the new plugin:
|
||||
|
||||
.. autofunction:: pytest_addhooks
|
||||
|
||||
Hooks are usually declared as do-nothing functions that contain only
|
||||
documentation describing when the hook will be called and what return values
|
||||
are expected.
|
||||
|
||||
For an example, see `newhooks.py`_ from :ref:`xdist`.
|
||||
|
||||
.. _`newhooks.py`: https://bitbucket.org/pytest-dev/pytest-xdist/src/52082f70e7dd04b00361091b8af906c60fd6700f/xdist/newhooks.py?at=default
|
||||
|
||||
|
||||
Using hooks from 3rd party plugins
|
||||
-------------------------------------
|
||||
|
||||
Using new hooks from plugins as explained above might be a little tricky
|
||||
because the standard `Hook specification and validation`_ mechanism:
|
||||
if you depend on a plugin that is not installed,
|
||||
validation will fail and the error message will not make much sense to your users.
|
||||
|
||||
One approach is to defer the hook implementation to a new plugin instead of
|
||||
declaring the hook functions directly in your plugin module, for example::
|
||||
|
||||
# contents of myplugin.py
|
||||
|
||||
class DeferPlugin(object):
|
||||
"""Simple plugin to defer pytest-xdist hook functions."""
|
||||
|
||||
def pytest_testnodedown(self, node, error):
|
||||
"""standard xdist hook function.
|
||||
"""
|
||||
|
||||
def pytest_configure(config):
|
||||
if config.pluginmanager.hasplugin('xdist'):
|
||||
config.pluginmanager.register(DeferPlugin())
|
||||
|
||||
|
||||
This has the added benefit of allowing you to conditionally install hooks
|
||||
depending on which plugins are installed.
|
||||
|
||||
hookwrapper: executing around other hooks
|
||||
-------------------------------------------------
|
||||
|
||||
.. currentmodule:: _pytest.core
|
||||
|
||||
.. versionadded:: 2.7 (experimental)
|
||||
|
||||
pytest plugins can implement hook wrappers which which wrap the execution
|
||||
of other hook implementations. A hook wrapper is a generator function
|
||||
which yields exactly once. When pytest invokes hooks it first executes
|
||||
hook wrappers and passes the same arguments as to the regular hooks.
|
||||
|
||||
At the yield point of the hook wrapper pytest will execute the next hook
|
||||
implementations and return their result to the yield point in the form of
|
||||
a :py:class:`CallOutcome` instance which encapsulates a result or
|
||||
exception info. The yield point itself will thus typically not raise
|
||||
exceptions (unless there are bugs).
|
||||
|
||||
Here is an example definition of a hook wrapper::
|
||||
|
||||
import pytest
|
||||
|
||||
@pytest.mark.hookwrapper
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
# do whatever you want before the next hook executes
|
||||
outcome = yield
|
||||
# outcome.excinfo may be None or a (cls, val, tb) tuple
|
||||
res = outcome.get_result() # will raise if outcome was exception
|
||||
# postprocess result
|
||||
|
||||
Note that hook wrappers don't return results themselves, they merely
|
||||
perform tracing or other side effects around the actual hook implementations.
|
||||
If the result of the underlying hook is a mutable object, they may modify
|
||||
that result, however.
|
||||
|
||||
|
||||
Reference of objects involved in hooks
|
||||
===========================================================
|
||||
======================================
|
||||
|
||||
.. autoclass:: _pytest.config.Config()
|
||||
:members:
|
||||
@@ -422,3 +510,6 @@ Reference of objects involved in hooks
|
||||
.. autoclass:: _pytest.runner.TestReport()
|
||||
:members:
|
||||
|
||||
.. autoclass:: _pytest.core.CallOutcome()
|
||||
:members:
|
||||
|
||||
|
||||
@@ -4,162 +4,224 @@ List of Third-Party Plugins
|
||||
===========================
|
||||
|
||||
The table below contains a listing of plugins found in PyPI and
|
||||
their status when tested using py.test **2.6.2.dev1** and python 2.7 and
|
||||
their status when tested using py.test **2.7.0** and python 2.7 and
|
||||
3.3.
|
||||
|
||||
A complete listing can also be found at
|
||||
`pytest-plugs <http://pytest-plugs.herokuapp.com/>`_, which contains tests
|
||||
`plugincompat <http://plugincompat.herokuapp.com/>`_, which contains tests
|
||||
status against other py.test releases.
|
||||
|
||||
|
||||
========================================================================================== ================================================================================================================= ================================================================================================================= ======================================================================================== =============================================================================================================================================
|
||||
Name Py27 Py34 Repo Summary
|
||||
========================================================================================== ================================================================================================================= ================================================================================================================= ======================================================================================== =============================================================================================================================================
|
||||
`pytest-allure-adaptor-1.4.0 <http://pypi.python.org/pypi/pytest-allure-adaptor>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Plugin for py.test to generate allure xml reports
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/allure-framework/allure-python
|
||||
`pytest-bdd-2.3.1 <http://pypi.python.org/pypi/pytest-bdd>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png BDD for pytest
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/olegpidsadnyi/pytest-bdd
|
||||
`pytest-beds-0.0.1 <http://pypi.python.org/pypi/pytest-beds>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/kaste/pytest-beds
|
||||
`pytest-bench-0.3.0 <http://pypi.python.org/pypi/pytest-bench>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Benchmark utility that plugs into pytest.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/concordusapps/pytest-bench
|
||||
`pytest-blockage-0.1 <http://pypi.python.org/pypi/pytest-blockage>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Disable network requests during a test run.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/rob-b/pytest-blockage
|
||||
`pytest-browsermob-proxy-0.1 <http://pypi.python.org/pypi/pytest-browsermob-proxy>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png BrowserMob proxy plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/davehunt/pytest-browsermob-proxy
|
||||
`pytest-bugzilla-0.2 <http://pypi.python.org/pypi/pytest-bugzilla>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test bugzilla integration plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/nibrahim/pytest_bugzilla
|
||||
`pytest-cache-1.0 <http://pypi.python.org/pypi/pytest-cache>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hpk42/pytest-cache/
|
||||
`pytest-capturelog-0.7 <http://pypi.python.org/pypi/pytest-capturelog>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test plugin to capture log messages
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/memedough/pytest-capturelog/overview
|
||||
`pytest-codecheckers-0.2 <http://pypi.python.org/pypi/pytest-codecheckers>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends)
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/
|
||||
`pytest-config-0.0.10 <http://pypi.python.org/pypi/pytest-config>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/buzzfeed/pytest_config
|
||||
`pytest-contextfixture-0.1.1 <http://pypi.python.org/pypi/pytest-contextfixture>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Define pytest fixtures as context managers.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/pelme/pytest-contextfixture/
|
||||
`pytest-couchdbkit-0.5.1 <http://pypi.python.org/pypi/pytest-couchdbkit>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit
|
||||
`pytest-cov-1.8.0 <http://pypi.python.org/pypi/pytest-cov>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png 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-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/schlamar/pytest-cov
|
||||
`pytest-cpp-0.3.0 <http://pypi.python.org/pypi/pytest-cpp>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Use pytest's runner to discover and execute C++ tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/nicoddemus/pytest-cpp
|
||||
`pytest-dbfixtures-0.5.1 <http://pypi.python.org/pypi/pytest-dbfixtures>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Databases fixtures plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures
|
||||
`pytest-dbus-notification-1.0.1 <http://pypi.python.org/pypi/pytest-dbus-notification>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png D-BUS notifications for pytest results.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/bmathieu33/pytest-dbus-notification
|
||||
`pytest-diffeo-0.1.8.dev1 <http://pypi.python.org/pypi/pytest-diffeo>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Common py.test support for Diffeo packages
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/diffeo/pytest-diffeo
|
||||
`pytest-django-2.6.2 <http://pypi.python.org/pypi/pytest-django>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.6.2.dev1 `http://pytest-django.readthedocs.org/ <http://pytest-django.readthedocs.org/>`_ A Django plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-django-haystack-0.1.1 <http://pypi.python.org/pypi/pytest-django-haystack>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Cleanup your Haystack indexes between tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/rouge8/pytest-django-haystack
|
||||
`pytest-django-lite-0.1.1 <http://pypi.python.org/pypi/pytest-django-lite>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png The bare minimum to integrate py.test with Django.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/dcramer/pytest-django-lite
|
||||
`pytest-echo-1.3 <http://pypi.python.org/pypi/pytest-echo>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.6.2.dev1 `http://pypi.python.org/pypi/pytest-echo/ <http://pypi.python.org/pypi/pytest-echo/>`_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-eradicate-0.0.2 <http://pypi.python.org/pypi/pytest-eradicate>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to check for commented out code
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/spil-johan/pytest-eradicate
|
||||
`pytest-figleaf-1.0 <http://pypi.python.org/pypi/pytest-figleaf>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test figleaf coverage plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hpk42/pytest-figleaf
|
||||
`pytest-fixture-tools-1.0.0 <http://pypi.python.org/pypi/pytest-fixture-tools>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.6.2.dev1 ? Plugin for pytest which provides tools for fixtures
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-flakes-0.2 <http://pypi.python.org/pypi/pytest-flakes>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to check source code with pyflakes
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/fschulze/pytest-flakes
|
||||
`pytest-greendots-0.3 <http://pypi.python.org/pypi/pytest-greendots>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.6.2.dev1 ? Green progress dots
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-growl-0.2 <http://pypi.python.org/pypi/pytest-growl>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.6.2.dev1 ? Growl notifications for pytest results.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-httpbin-0.0.2 <http://pypi.python.org/pypi/pytest-httpbin>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Easily test your HTTP library against a local copy of httpbin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/kevin1024/pytest-httpbin
|
||||
`pytest-httpretty-0.2.0 <http://pypi.python.org/pypi/pytest-httpretty>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png A thin wrapper of HTTPretty for pytest
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/papaeye/pytest-httpretty
|
||||
`pytest-incremental-0.3.0 <http://pypi.python.org/pypi/pytest-incremental>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png an incremental test runner (pytest plugin)
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.6.2.dev1 :target: https://bitbucket.org/schettino72/pytest-incremental
|
||||
`pytest-instafail-0.2.0 <http://pypi.python.org/pypi/pytest-instafail>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test plugin to show failures instantly
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/jpvanhal/pytest-instafail
|
||||
`pytest-ipdb-0.1-prerelease <http://pypi.python.org/pypi/pytest-ipdb>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/mverteuil/pytest-ipdb
|
||||
`pytest-jira-0.01 <http://pypi.python.org/pypi/pytest-jira>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test JIRA integration plugin, using markers
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/jlaska/pytest_jira
|
||||
`pytest-knows-0.1.5 <http://pypi.python.org/pypi/pytest-knows>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/mapix/ptknows
|
||||
`pytest-konira-0.2 <http://pypi.python.org/pypi/pytest-konira>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Run Konira DSL tests with py.test
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/alfredodeza/pytest-konira
|
||||
`pytest-localserver-0.3.2 <http://pypi.python.org/pypi/pytest-localserver>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test plugin to test server connections locally.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/basti/pytest-localserver/
|
||||
`pytest-marker-bugzilla-0.06 <http://pypi.python.org/pypi/pytest-marker-bugzilla>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test bugzilla integration plugin, using markers
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/eanxgeek/pytest_marker_bugzilla
|
||||
`pytest-markfiltration-0.8 <http://pypi.python.org/pypi/pytest-markfiltration>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/adamgoucher/pytest-markfiltration
|
||||
`pytest-marks-0.4 <http://pypi.python.org/pypi/pytest-marks>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/adamgoucher/pytest-marks
|
||||
`pytest-mock-0.3.0 <http://pypi.python.org/pypi/pytest-mock>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/nicoddemus/pytest-mock/
|
||||
`pytest-monkeyplus-1.1.0 <http://pypi.python.org/pypi/pytest-monkeyplus>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/
|
||||
`pytest-mozwebqa-1.1.1 <http://pypi.python.org/pypi/pytest-mozwebqa>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Mozilla WebQA plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/davehunt/pytest-mozwebqa
|
||||
`pytest-oerp-0.2.0 <http://pypi.python.org/pypi/pytest-oerp>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to test OpenERP modules
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/santagada/pytest-oerp/
|
||||
`pytest-ordering-0.3 <http://pypi.python.org/pypi/pytest-ordering>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to run your tests in a specific order
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/ftobia/pytest-ordering
|
||||
`pytest-osxnotify-0.1.4 <http://pypi.python.org/pypi/pytest-osxnotify>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png OS X notifications for py.test results.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/dbader/pytest-osxnotify
|
||||
`pytest-paste-config-0.1 <http://pypi.python.org/pypi/pytest-paste-config>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.6.2.dev1 ? Allow setting the path to a paste config file
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-pep8-1.0.6 <http://pypi.python.org/pypi/pytest-pep8>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest plugin to check PEP8 requirements
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hpk42/pytest-pep8/
|
||||
`pytest-pipeline-0.1.0 <http://pypi.python.org/pypi/pytest-pipeline>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/bow/pytest_pipeline
|
||||
`pytest-poo-0.2 <http://pypi.python.org/pypi/pytest-poo>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Visualize your crappy tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/pelme/pytest-poo
|
||||
`pytest-pycharm-0.1.0 <http://pypi.python.org/pypi/pytest-pycharm>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/jlubcke/pytest-pycharm
|
||||
`pytest-pydev-0.1 <http://pypi.python.org/pypi/pytest-pydev>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/basti/pytest-pydev/
|
||||
`pytest-pythonpath-0.3 <http://pypi.python.org/pypi/pytest-pythonpath>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/bigsassy/pytest-pythonpath
|
||||
`pytest-qt-1.2.0 <http://pypi.python.org/pypi/pytest-qt>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest support for PyQt and PySide applications
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/nicoddemus/pytest-qt
|
||||
`pytest-quickcheck-0.8 <http://pypi.python.org/pypi/pytest-quickcheck>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/t2y/pytest-quickcheck/
|
||||
`pytest-rage-0.1 <http://pypi.python.org/pypi/pytest-rage>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to implement PEP712
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/santagada/pytest-rage/
|
||||
`pytest-raisesregexp-1.0 <http://pypi.python.org/pypi/pytest-raisesregexp>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Simple pytest plugin to look for regex in Exceptions
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/Walkman/pytest_raisesregexp
|
||||
`pytest-random-0.02 <http://pypi.python.org/pypi/pytest-random>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test plugin to randomize tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/klrmn/pytest-random
|
||||
`pytest-rerunfailures-0.05 <http://pypi.python.org/pypi/pytest-rerunfailures>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/klrmn/pytest-rerunfailures
|
||||
`pytest-runfailed-0.3 <http://pypi.python.org/pypi/pytest-runfailed>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png implement a --failed option for pytest
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/dmerejkowsky/pytest-runfailed
|
||||
`pytest-runner-2.1 <http://pypi.python.org/pypi/pytest-runner>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png UNKNOWN
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.6.2.dev1 :target: https://bitbucket.org/jaraco/pytest-runner
|
||||
`pytest-sftpserver-1.0.2 <http://pypi.python.org/pypi/pytest-sftpserver>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test plugin to locally test sftp server connections.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.6.2.dev1 :target: http://github.com/ulope/pytest-sftpserver/
|
||||
`pytest-spec-0.2.22 <http://pypi.python.org/pypi/pytest-spec>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/pchomik/pytest-spec
|
||||
`pytest-splinter-1.0.3 <http://pypi.python.org/pypi/pytest-splinter>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Splinter subplugin for Pytest BDD plugin
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/paylogic/pytest-splinter
|
||||
`pytest-stepwise-0.2 <http://pypi.python.org/pypi/pytest-stepwise>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png Run a test suite one failing test at a time.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/nip3o/pytest-stepwise
|
||||
`pytest-sugar-0.3.4 <http://pypi.python.org/pypi/pytest-sugar>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly).
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/Frozenball/pytest-sugar
|
||||
`pytest-timeout-0.4 <http://pypi.python.org/pypi/pytest-timeout>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test plugin to abort hanging tests
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/flub/pytest-timeout/
|
||||
`pytest-twisted-1.5 <http://pypi.python.org/pypi/pytest-twisted>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png A twisted plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/schmir/pytest-twisted
|
||||
`pytest-xdist-1.10 <http://pypi.python.org/pypi/pytest-xdist>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hpk42/pytest-xdist
|
||||
`pytest-xprocess-0.8 <http://pypi.python.org/pypi/pytest-xprocess>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.6.2.dev1 .. image:: bitbucket.png pytest plugin to manage external processes across test runs
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.6.2.dev1 :target: http://bitbucket.org/hpk42/pytest-xprocess/
|
||||
`pytest-yamlwsgi-0.6 <http://pypi.python.org/pypi/pytest-yamlwsgi>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.6.2.dev1 ? Run tests against wsgi apps defined in yaml
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.6.2.dev1
|
||||
`pytest-zap-0.2 <http://pypi.python.org/pypi/pytest-zap>`_ .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.6.2.dev1 .. image:: http://pytest-plugs.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.6.2.dev1 .. image:: github.png OWASP ZAP plugin for py.test.
|
||||
:target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.6.2.dev1 :target: http://pytest-plugs.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.6.2.dev1 :target: https://github.com/davehunt/pytest-zap
|
||||
============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== =============================================================================================================================================
|
||||
Name Py27 Py34 Home Summary
|
||||
============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== =============================================================================================================================================
|
||||
`pytest-allure-adaptor <http://pypi.python.org/pypi/pytest-allure-adaptor>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to generate allure xml reports
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-allure-adaptor-latest?py=py34&pytest=2.7.0 :target: https://github.com/allure-framework/allure-python
|
||||
`pytest-ansible <http://pypi.python.org/pypi/pytest-ansible>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ansible-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ansible-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest-ansible
|
||||
`pytest-autochecklog <http://pypi.python.org/pypi/pytest-autochecklog>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-autochecklog-latest?py=py34&pytest=2.7.0 .. image:: github.png automatically check condition and log all the checks
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-autochecklog-latest?py=py34&pytest=2.7.0 :target: https://github.com/steven004/python-autochecklog
|
||||
`pytest-bdd <http://pypi.python.org/pypi/pytest-bdd>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bdd-latest?py=py34&pytest=2.7.0 .. image:: github.png BDD for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bdd-latest?py=py34&pytest=2.7.0 :target: https://github.com/olegpidsadnyi/pytest-bdd
|
||||
`pytest-beakerlib <http://pypi.python.org/pypi/pytest-beakerlib>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beakerlib-latest?py=py34&pytest=2.7.0 `link <https://fedorahosted.org/python-pytest-beakerlib/>`_ A pytest plugin that reports test results to the BeakerLib framework
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beakerlib-latest?py=py34&pytest=2.7.0
|
||||
`pytest-beds <http://pypi.python.org/pypi/pytest-beds>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-beds-latest?py=py34&pytest=2.7.0 .. image:: github.png Fixtures for testing Google Appengine (GAE) apps
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-beds-latest?py=py34&pytest=2.7.0 :target: https://github.com/kaste/pytest-beds
|
||||
`pytest-bench <http://pypi.python.org/pypi/pytest-bench>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bench-latest?py=py34&pytest=2.7.0 .. image:: github.png Benchmark utility that plugs into pytest.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bench-latest?py=py34&pytest=2.7.0 :target: http://github.com/concordusapps/pytest-bench
|
||||
`pytest-benchmark <http://pypi.python.org/pypi/pytest-benchmark>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-benchmark-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test fixture for benchmarking code
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-benchmark-latest?py=py34&pytest=2.7.0 :target: https://github.com/ionelmc/pytest-benchmark
|
||||
`pytest-blockage <http://pypi.python.org/pypi/pytest-blockage>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-blockage-latest?py=py34&pytest=2.7.0 .. image:: github.png Disable network requests during a test run.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-blockage-latest?py=py34&pytest=2.7.0 :target: https://github.com/rob-b/pytest-blockage
|
||||
`pytest-bpdb <http://pypi.python.org/pypi/pytest-bpdb>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bpdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to bpdb debugger on test failure.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bpdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/slafs/pytest-bpdb
|
||||
`pytest-browsermob-proxy <http://pypi.python.org/pypi/pytest-browsermob-proxy>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 .. image:: github.png BrowserMob proxy plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-browsermob-proxy-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-browsermob-proxy
|
||||
`pytest-bugzilla <http://pypi.python.org/pypi/pytest-bugzilla>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/nibrahim/pytest_bugzilla
|
||||
`pytest-cache <http://pypi.python.org/pypi/pytest-cache>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cache-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin with mechanisms for caching across test runs
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cache-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-cache/
|
||||
`pytest-cagoule <http://pypi.python.org/pypi/pytest-cagoule>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cagoule-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin to only run tests affected by changes
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cagoule-latest?py=py34&pytest=2.7.0 :target: https://github.com/davidszotten/pytest-cagoule
|
||||
`pytest-capturelog <http://pypi.python.org/pypi/pytest-capturelog>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-capturelog-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to capture log messages
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-capturelog-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/memedough/pytest-capturelog/overview
|
||||
`pytest-catchlog <http://pypi.python.org/pypi/pytest-catchlog>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-catchlog-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to catch log messages. This is a fork of pytest-capturelog.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-catchlog-latest?py=py34&pytest=2.7.0 :target: https://github.com/eisensheng/pytest-catchlog
|
||||
`pytest-circleci <http://pypi.python.org/pypi/pytest-circleci>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-circleci-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for CircleCI
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-circleci-latest?py=py34&pytest=2.7.0 :target: https://github.com/micktwomey/pytest-circleci
|
||||
`pytest-cloud <http://pypi.python.org/pypi/pytest-cloud>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cloud-latest?py=py34&pytest=2.7.0 .. image:: github.png Distributed tests planner plugin for pytest testing framework.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cloud-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-cloud
|
||||
`pytest-codecheckers <http://pypi.python.org/pypi/pytest-codecheckers>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-codecheckers-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to add source code sanity checks (pep8 and friends)
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-codecheckers-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-codecheckers/
|
||||
`pytest-colordots <http://pypi.python.org/pypi/pytest-colordots>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-colordots-latest?py=py34&pytest=2.7.0 .. image:: github.png Colorizes the progress indicators
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-colordots-latest?py=py34&pytest=2.7.0 :target: https://github.com/svenstaro/pytest-colordots
|
||||
`pytest-config <http://pypi.python.org/pypi/pytest-config>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-config-latest?py=py34&pytest=2.7.0 .. image:: github.png Base configurations and utilities for developing your Python project test suite with pytest.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-config-latest?py=py34&pytest=2.7.0 :target: https://github.com/buzzfeed/pytest_config
|
||||
`pytest-contextfixture <http://pypi.python.org/pypi/pytest-contextfixture>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-contextfixture-latest?py=py34&pytest=2.7.0 .. image:: github.png Define pytest fixtures as context managers.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-contextfixture-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-contextfixture/
|
||||
`pytest-couchdbkit <http://pypi.python.org/pypi/pytest-couchdbkit>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test extension for per-test couchdb databases using couchdbkit
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-couchdbkit-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/RonnyPfannschmidt/pytest-couchdbkit
|
||||
`pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cov-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cov-latest?py=py34&pytest=2.7.0 :target: https://github.com/schlamar/pytest-cov
|
||||
`pytest-cpp <http://pypi.python.org/pypi/pytest-cpp>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-cpp-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute C++ tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-cpp-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-cpp
|
||||
`pytest-dbfixtures <http://pypi.python.org/pypi/pytest-dbfixtures>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 .. image:: github.png Databases fixtures plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbfixtures-latest?py=py34&pytest=2.7.0 :target: https://github.com/ClearcodeHQ/pytest-dbfixtures
|
||||
`pytest-dbus-notification <http://pypi.python.org/pypi/pytest-dbus-notification>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 .. image:: github.png D-BUS notifications for pytest results.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-dbus-notification-latest?py=py34&pytest=2.7.0 :target: https://github.com/bmathieu33/pytest-dbus-notification
|
||||
`pytest-describe <http://pypi.python.org/pypi/pytest-describe>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-describe-latest?py=py34&pytest=2.7.0 .. image:: github.png Describe-style plugin for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-describe-latest?py=py34&pytest=2.7.0 :target: https://github.com/ropez/pytest-describe
|
||||
`pytest-diffeo <http://pypi.python.org/pypi/pytest-diffeo>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-diffeo-latest?py=py34&pytest=2.7.0 .. image:: github.png Common py.test support for Diffeo packages
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-diffeo-latest?py=py34&pytest=2.7.0 :target: https://github.com/diffeo/pytest-diffeo
|
||||
`pytest-django <http://pypi.python.org/pypi/pytest-django>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-latest?py=py34&pytest=2.7.0 `link <http://pytest-django.readthedocs.org/>`_ A Django plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-latest?py=py34&pytest=2.7.0
|
||||
`pytest-django-haystack <http://pypi.python.org/pypi/pytest-django-haystack>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-haystack-latest?py=py34&pytest=2.7.0 .. image:: github.png Cleanup your Haystack indexes between tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-haystack-latest?py=py34&pytest=2.7.0 :target: http://github.com/rouge8/pytest-django-haystack
|
||||
`pytest-django-lite <http://pypi.python.org/pypi/pytest-django-lite>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-lite-latest?py=py34&pytest=2.7.0 .. image:: github.png The bare minimum to integrate py.test with Django.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-lite-latest?py=py34&pytest=2.7.0 :target: https://github.com/dcramer/pytest-django-lite
|
||||
`pytest-django-sqlcount <http://pypi.python.org/pypi/pytest-django-sqlcount>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin for reporting the number of SQLs executed per django testcase.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-django-sqlcount-latest?py=py34&pytest=2.7.0 :target: https://github.com/stj/pytest-django-sqlcount
|
||||
`pytest-echo <http://pypi.python.org/pypi/pytest-echo>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-echo-latest?py=py34&pytest=2.7.0 `link <http://pypi.python.org/pypi/pytest-echo/>`_ pytest plugin with mechanisms for echoing environment variables, package version and generic attributes
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-echo-latest?py=py34&pytest=2.7.0
|
||||
`pytest-env <http://pypi.python.org/pypi/pytest-env>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-env-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin that allows you to add environment variables.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-env-latest?py=py34&pytest=2.7.0 :target: https://github.com/MobileDynasty/pytest-env
|
||||
`pytest-eradicate <http://pypi.python.org/pypi/pytest-eradicate>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-eradicate-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check for commented out code
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-eradicate-latest?py=py34&pytest=2.7.0 :target: https://github.com/spil-johan/pytest-eradicate
|
||||
`pytest-figleaf <http://pypi.python.org/pypi/pytest-figleaf>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-figleaf-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test figleaf coverage plugin
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-figleaf-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-figleaf
|
||||
`pytest-fixture-tools <http://pypi.python.org/pypi/pytest-fixture-tools>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-fixture-tools-latest?py=py34&pytest=2.7.0 ? Plugin for pytest which provides tools for fixtures
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-fixture-tools-latest?py=py34&pytest=2.7.0
|
||||
`pytest-flakes <http://pypi.python.org/pypi/pytest-flakes>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flakes-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to check source code with pyflakes
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flakes-latest?py=py34&pytest=2.7.0 :target: https://github.com/fschulze/pytest-flakes
|
||||
`pytest-flask <http://pypi.python.org/pypi/pytest-flask>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-flask-latest?py=py34&pytest=2.7.0 .. image:: github.png A set of py.test fixtures to test Flask applications.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-flask-latest?py=py34&pytest=2.7.0 :target: https://github.com/vitalk/pytest-flask
|
||||
`pytest-greendots <http://pypi.python.org/pypi/pytest-greendots>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-greendots-latest?py=py34&pytest=2.7.0 ? Green progress dots
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-greendots-latest?py=py34&pytest=2.7.0
|
||||
`pytest-growl <http://pypi.python.org/pypi/pytest-growl>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-growl-latest?py=py34&pytest=2.7.0 ? Growl notifications for pytest results.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-growl-latest?py=py34&pytest=2.7.0
|
||||
`pytest-httpbin <http://pypi.python.org/pypi/pytest-httpbin>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpbin-latest?py=py34&pytest=2.7.0 .. image:: github.png Easily test your HTTP library against a local copy of httpbin
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpbin-latest?py=py34&pytest=2.7.0 :target: https://github.com/kevin1024/pytest-httpbin
|
||||
`pytest-httpretty <http://pypi.python.org/pypi/pytest-httpretty>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-httpretty-latest?py=py34&pytest=2.7.0 .. image:: github.png A thin wrapper of HTTPretty for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-httpretty-latest?py=py34&pytest=2.7.0 :target: http://github.com/papaeye/pytest-httpretty
|
||||
`pytest-incremental <http://pypi.python.org/pypi/pytest-incremental>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-incremental-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png an incremental test runner (pytest plugin)
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-incremental-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/schettino72/pytest-incremental
|
||||
`pytest-instafail <http://pypi.python.org/pypi/pytest-instafail>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-instafail-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to show failures instantly
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-instafail-latest?py=py34&pytest=2.7.0 :target: https://github.com/jpvanhal/pytest-instafail
|
||||
`pytest-ipdb <http://pypi.python.org/pypi/pytest-ipdb>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipdb-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plug-in to enable drop to ipdb debugger on test failure.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipdb-latest?py=py34&pytest=2.7.0 :target: https://github.com/mverteuil/pytest-ipdb
|
||||
`pytest-ipynb <http://pypi.python.org/pypi/pytest-ipynb>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ipynb-latest?py=py34&pytest=2.7.0 .. image:: github.png Use pytest's runner to discover and execute tests as cells of IPython notebooks
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ipynb-latest?py=py34&pytest=2.7.0 :target: http://github.com/zonca/pytest-ipynb
|
||||
`pytest-jira <http://pypi.python.org/pypi/pytest-jira>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-jira-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test JIRA integration plugin, using markers
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-jira-latest?py=py34&pytest=2.7.0 :target: http://github.com/jlaska/pytest_jira
|
||||
`pytest-knows <http://pypi.python.org/pypi/pytest-knows>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-knows-latest?py=py34&pytest=2.7.0 .. image:: github.png A pytest plugin that can automaticly skip test case based on dependence info calculated by trace
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-knows-latest?py=py34&pytest=2.7.0 :target: https://github.com/mapix/ptknows
|
||||
`pytest-konira <http://pypi.python.org/pypi/pytest-konira>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-konira-latest?py=py34&pytest=2.7.0 .. image:: github.png Run Konira DSL tests with py.test
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-konira-latest?py=py34&pytest=2.7.0 :target: http://github.com/alfredodeza/pytest-konira
|
||||
`pytest-localserver <http://pypi.python.org/pypi/pytest-localserver>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-localserver-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to test server connections locally.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-localserver-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-localserver/
|
||||
`pytest-marker-bugzilla <http://pypi.python.org/pypi/pytest-marker-bugzilla>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test bugzilla integration plugin, using markers
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marker-bugzilla-latest?py=py34&pytest=2.7.0 :target: http://github.com/eanxgeek/pytest_marker_bugzilla
|
||||
`pytest-markfiltration <http://pypi.python.org/pypi/pytest-markfiltration>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-markfiltration-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-markfiltration-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-markfiltration
|
||||
`pytest-marks <http://pypi.python.org/pypi/pytest-marks>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-marks-latest?py=py34&pytest=2.7.0 .. image:: github.png UNKNOWN
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-marks-latest?py=py34&pytest=2.7.0 :target: https://github.com/adamgoucher/pytest-marks
|
||||
`pytest-mock <http://pypi.python.org/pypi/pytest-mock>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mock-latest?py=py34&pytest=2.7.0 .. image:: github.png Thin-wrapper around the mock package for easier use with py.test
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mock-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-mock/
|
||||
`pytest-monkeyplus <http://pypi.python.org/pypi/pytest-monkeyplus>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest's monkeypatch subclass with extra functionalities
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-monkeyplus-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hsoft/pytest-monkeyplus/
|
||||
`pytest-mozwebqa <http://pypi.python.org/pypi/pytest-mozwebqa>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 .. image:: github.png Mozilla WebQA plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-mozwebqa-latest?py=py34&pytest=2.7.0 :target: https://github.com/mozilla/pytest-mozwebqa
|
||||
`pytest-multihost <http://pypi.python.org/pypi/pytest-multihost>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-multihost-latest?py=py34&pytest=2.7.0 `link <https://fedorahosted.org/python-pytest-multihost/>`_ Utility for writing multi-host tests for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-multihost-latest?py=py34&pytest=2.7.0
|
||||
`pytest-oerp <http://pypi.python.org/pypi/pytest-oerp>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oerp-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to test OpenERP modules
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oerp-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-oerp/
|
||||
`pytest-oot <http://pypi.python.org/pypi/pytest-oot>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-oot-latest?py=py34&pytest=2.7.0 `link <https://pypi.python.org/pypi?name=pytest-oot&:action=display>`_ Run object-oriented tests in a simple format
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-oot-latest?py=py34&pytest=2.7.0
|
||||
`pytest-optional <http://pypi.python.org/pypi/pytest-optional>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-optional-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png include/exclude values of fixtures in pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-optional-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/maho/pytest-optional
|
||||
`pytest-ordering <http://pypi.python.org/pypi/pytest-ordering>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-ordering-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to run your tests in a specific order
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-ordering-latest?py=py34&pytest=2.7.0 :target: https://github.com/ftobia/pytest-ordering
|
||||
`pytest-osxnotify <http://pypi.python.org/pypi/pytest-osxnotify>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-osxnotify-latest?py=py34&pytest=2.7.0 .. image:: github.png OS X notifications for py.test results.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-osxnotify-latest?py=py34&pytest=2.7.0 :target: https://github.com/dbader/pytest-osxnotify
|
||||
`pytest-paste-config <http://pypi.python.org/pypi/pytest-paste-config>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-paste-config-latest?py=py34&pytest=2.7.0 ? Allow setting the path to a paste config file
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-paste-config-latest?py=py34&pytest=2.7.0
|
||||
`pytest-pep257 <http://pypi.python.org/pypi/pytest-pep257>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep257-latest?py=py34&pytest=2.7.0 ? py.test plugin for pep257
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep257-latest?py=py34&pytest=2.7.0
|
||||
`pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pep8-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to check PEP8 requirements
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pep8-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-pep8/
|
||||
`pytest-pipeline <http://pypi.python.org/pypi/pytest-pipeline>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pipeline-latest?py=py34&pytest=2.7.0 .. image:: github.png Pytest plugin for functional testing of data analysis pipelines
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pipeline-latest?py=py34&pytest=2.7.0 :target: https://github.com/bow/pytest_pipeline
|
||||
`pytest-poo <http://pypi.python.org/pypi/pytest-poo>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your crappy tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-latest?py=py34&pytest=2.7.0 :target: http://github.com/pelme/pytest-poo
|
||||
`pytest-poo-fail <http://pypi.python.org/pypi/pytest-poo-fail>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-poo-fail-latest?py=py34&pytest=2.7.0 .. image:: github.png Visualize your failed tests with poo
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-poo-fail-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-poo-fail
|
||||
`pytest-pycharm <http://pypi.python.org/pypi/pytest-pycharm>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pycharm-latest?py=py34&pytest=2.7.0 .. image:: github.png Plugin for py.test to enter PyCharm debugger on uncaught exceptions
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pycharm-latest?py=py34&pytest=2.7.0 :target: https://github.com/jlubcke/pytest-pycharm
|
||||
`pytest-pydev <http://pypi.python.org/pypi/pytest-pydev>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pydev-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to connect to a remote debug server with PyDev or PyCharm.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pydev-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/basti/pytest-pydev/
|
||||
`pytest-pyq <http://pypi.python.org/pypi/pytest-pyq>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pyq-latest?py=py34&pytest=2.7.0 `link <http://pyq.enlnt.com>`_ Pytest fixture "q" for pyq
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pyq-latest?py=py34&pytest=2.7.0
|
||||
`pytest-pythonpath <http://pypi.python.org/pypi/pytest-pythonpath>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-pythonpath-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin for adding to the PYTHONPATH from command line or configs.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-pythonpath-latest?py=py34&pytest=2.7.0 :target: https://github.com/bigsassy/pytest-pythonpath
|
||||
`pytest-qt <http://pypi.python.org/pypi/pytest-qt>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-qt-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest support for PyQt and PySide applications
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-qt-latest?py=py34&pytest=2.7.0 :target: http://github.com/pytest-dev/pytest-qt
|
||||
`pytest-quickcheck <http://pypi.python.org/pypi/pytest-quickcheck>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-quickcheck-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to generate random data inspired by QuickCheck
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-quickcheck-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/t2y/pytest-quickcheck/
|
||||
`pytest-rage <http://pypi.python.org/pypi/pytest-rage>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rage-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to implement PEP712
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rage-latest?py=py34&pytest=2.7.0 :target: http://github.com/santagada/pytest-rage/
|
||||
`pytest-raisesregexp <http://pypi.python.org/pypi/pytest-raisesregexp>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 .. image:: github.png Simple pytest plugin to look for regex in Exceptions
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-raisesregexp-latest?py=py34&pytest=2.7.0 :target: https://github.com/Walkman/pytest_raisesregexp
|
||||
`pytest-random <http://pypi.python.org/pypi/pytest-random>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-random-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to randomize tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-random-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-random
|
||||
`pytest-readme <http://pypi.python.org/pypi/pytest-readme>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-readme-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your README.md file
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-readme-latest?py=py34&pytest=2.7.0 :target: https://github.com/boxed/pytest-readme
|
||||
`pytest-regtest <http://pypi.python.org/pypi/pytest-regtest>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-regtest-latest?py=py34&pytest=2.7.0 `link <https://sissource.ethz.ch/uweschmitt/pytest-regtest/tree/master>`_ py.test plugin for regression tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-regtest-latest?py=py34&pytest=2.7.0
|
||||
`pytest-remove-stale-bytecode <http://pypi.python.org/pypi/pytest-remove-stale-bytecode>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to remove stale byte code files.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-remove-stale-bytecode-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/gocept/pytest-remove-stale-bytecode/
|
||||
`pytest-rerunfailures <http://pypi.python.org/pypi/pytest-rerunfailures>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to re-run tests to eliminate flakey failures
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-rerunfailures-latest?py=py34&pytest=2.7.0 :target: https://github.com/klrmn/pytest-rerunfailures
|
||||
`pytest-runfailed <http://pypi.python.org/pypi/pytest-runfailed>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runfailed-latest?py=py34&pytest=2.7.0 .. image:: github.png implement a --failed option for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runfailed-latest?py=py34&pytest=2.7.0 :target: http://github.com/dmerejkowsky/pytest-runfailed
|
||||
`pytest-runner <http://pypi.python.org/pypi/pytest-runner>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-runner-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png Invoke py.test as distutils command with dependency resolution.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-runner-latest?py=py34&pytest=2.7.0 :target: https://bitbucket.org/jaraco/pytest-runner
|
||||
`pytest-services <http://pypi.python.org/pypi/pytest-services>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-services-latest?py=py34&pytest=2.7.0 .. image:: github.png Services plugin for pytest testing framework
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-services-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-services
|
||||
`pytest-sftpserver <http://pypi.python.org/pypi/pytest-sftpserver>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sftpserver-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test plugin to locally test sftp server connections.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sftpserver-latest?py=py34&pytest=2.7.0 :target: http://github.com/ulope/pytest-sftpserver/
|
||||
`pytest-smartcov <http://pypi.python.org/pypi/pytest-smartcov>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-smartcov-latest?py=py34&pytest=2.7.0 .. image:: github.png Smart coverage plugin for pytest.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-smartcov-latest?py=py34&pytest=2.7.0 :target: https://github.com/carljm/pytest-smartcov/
|
||||
`pytest-sourceorder <http://pypi.python.org/pypi/pytest-sourceorder>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sourceorder-latest?py=py34&pytest=2.7.0 `link <https://fedorahosted.org/python-pytest-sourceorder/>`_ Test-ordering plugin for pytest
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sourceorder-latest?py=py34&pytest=2.7.0
|
||||
`pytest-spec <http://pypi.python.org/pypi/pytest-spec>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-spec-latest?py=py34&pytest=2.7.0 .. image:: github.png pytest plugin to display test execution output like a SPECIFICATION
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-spec-latest?py=py34&pytest=2.7.0 :target: https://github.com/pchomik/pytest-spec
|
||||
`pytest-splinter <http://pypi.python.org/pypi/pytest-splinter>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-splinter-latest?py=py34&pytest=2.7.0 .. image:: github.png Splinter plugin for pytest testing framework
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-splinter-latest?py=py34&pytest=2.7.0 :target: https://github.com/pytest-dev/pytest-splinter
|
||||
`pytest-stepwise <http://pypi.python.org/pypi/pytest-stepwise>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-stepwise-latest?py=py34&pytest=2.7.0 .. image:: github.png Run a test suite one failing test at a time.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-stepwise-latest?py=py34&pytest=2.7.0 :target: https://github.com/nip3o/pytest-stepwise
|
||||
`pytest-sugar <http://pypi.python.org/pypi/pytest-sugar>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-sugar-latest?py=py34&pytest=2.7.0 .. image:: github.png py.test is a plugin for py.test that changes the default look and feel of py.test (e.g. progressbar, show tests that fail instantly).
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-sugar-latest?py=py34&pytest=2.7.0 :target: https://github.com/Frozenball/pytest-sugar
|
||||
`pytest-timeout <http://pypi.python.org/pypi/pytest-timeout>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-timeout-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test plugin to abort hanging tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-timeout-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/flub/pytest-timeout/
|
||||
`pytest-tornado <http://pypi.python.org/pypi/pytest-tornado>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-tornado-latest?py=py34&pytest=2.7.0 .. image:: github.png A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-tornado-latest?py=py34&pytest=2.7.0 :target: https://github.com/eugeniy/pytest-tornado
|
||||
`pytest-translations <http://pypi.python.org/pypi/pytest-translations>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-translations-latest?py=py34&pytest=2.7.0 .. image:: github.png Test your translation files
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-translations-latest?py=py34&pytest=2.7.0 :target: https://github.com/thermondo/pytest-translations
|
||||
`pytest-twisted <http://pypi.python.org/pypi/pytest-twisted>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-twisted-latest?py=py34&pytest=2.7.0 .. image:: github.png A twisted plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-twisted-latest?py=py34&pytest=2.7.0 :target: https://github.com/schmir/pytest-twisted
|
||||
`pytest-unmarked <http://pypi.python.org/pypi/pytest-unmarked>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-unmarked-latest?py=py34&pytest=2.7.0 .. image:: github.png Run only unmarked tests
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-unmarked-latest?py=py34&pytest=2.7.0 :target: http://github.com/alyssa.barela/pytest-unmarked
|
||||
`pytest-watch <http://pypi.python.org/pypi/pytest-watch>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-watch-latest?py=py34&pytest=2.7.0 .. image:: github.png Local continuous test runner with pytest and watchdog.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-watch-latest?py=py34&pytest=2.7.0 :target: http://github.com/joeyespo/pytest-watch
|
||||
`pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xdist-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png py.test xdist plugin for distributed testing and loop-on-failing modes
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xdist-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xdist
|
||||
`pytest-xprocess <http://pypi.python.org/pypi/pytest-xprocess>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-xprocess-latest?py=py34&pytest=2.7.0 .. image:: bitbucket.png pytest plugin to manage external processes across test runs
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-xprocess-latest?py=py34&pytest=2.7.0 :target: http://bitbucket.org/hpk42/pytest-xprocess/
|
||||
`pytest-yamlwsgi <http://pypi.python.org/pypi/pytest-yamlwsgi>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0 ? Run tests against wsgi apps defined in yaml
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-yamlwsgi-latest?py=py34&pytest=2.7.0
|
||||
`pytest-zap <http://pypi.python.org/pypi/pytest-zap>`_ .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py27&pytest=2.7.0 .. image:: http://plugincompat.herokuapp.com/status/pytest-zap-latest?py=py34&pytest=2.7.0 .. image:: github.png OWASP ZAP plugin for py.test.
|
||||
:target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py27&pytest=2.7.0 :target: http://plugincompat.herokuapp.com/output/pytest-zap-latest?py=py34&pytest=2.7.0 :target: https://github.com/davehunt/pytest-zap
|
||||
|
||||
========================================================================================== ================================================================================================================= ================================================================================================================= ======================================================================================== =============================================================================================================================================
|
||||
============================================================================================ ================================================================================================================ ================================================================================================================ =========================================================================== =============================================================================================================================================
|
||||
|
||||
*(Updated on 2014-08-26)*
|
||||
*(Updated on 2015-02-28)*
|
||||
|
||||
@@ -10,7 +10,7 @@ This should be issued before every major documentation release to obtain latest
|
||||
versions from PyPI.
|
||||
|
||||
Also includes plugin compatibility between different python and pytest versions,
|
||||
obtained from http://pytest-plugs.herokuapp.com.
|
||||
obtained from http://plugincompat.herokuapp.com.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
from collections import namedtuple
|
||||
@@ -61,7 +61,7 @@ def get_latest_versions(plugins):
|
||||
yield name, str(loose_version)
|
||||
|
||||
|
||||
def obtain_plugins_table(plugins, client):
|
||||
def obtain_plugins_table(plugins, client, verbose, pytest_ver):
|
||||
"""
|
||||
Returns information to populate a table of plugins, their versions,
|
||||
authors, etc.
|
||||
@@ -72,7 +72,12 @@ def obtain_plugins_table(plugins, client):
|
||||
|
||||
:param plugins: list of (name, version)
|
||||
:param client: ServerProxy
|
||||
:param verbose: print plugin name and version as they are fetch
|
||||
:param pytest_ver: pytest version to use.
|
||||
"""
|
||||
if pytest_ver is None:
|
||||
pytest_ver = pytest.__version__
|
||||
|
||||
def get_repo_markup(repo):
|
||||
"""
|
||||
obtains appropriate markup for the given repository, as two lines
|
||||
@@ -96,7 +101,7 @@ def obtain_plugins_table(plugins, client):
|
||||
pad_right = ('%-' + str(len(target_markup)) + 's')
|
||||
return pad_right % image_markup, target_markup
|
||||
else:
|
||||
return ('`%s <%s>`_' % (target, target)), ''
|
||||
return ('`link <%s>`_' % target), ''
|
||||
|
||||
def sanitize_summary(summary):
|
||||
"""Make sure summaries don't break our table formatting.
|
||||
@@ -105,18 +110,18 @@ def obtain_plugins_table(plugins, client):
|
||||
|
||||
rows = []
|
||||
ColumnData = namedtuple('ColumnData', 'text link')
|
||||
headers = ['Name', 'Py27', 'Py34', 'Repo', 'Summary']
|
||||
pytest_version = pytest.__version__
|
||||
headers = ['Name', 'Py27', 'Py34', 'Home', 'Summary']
|
||||
repositories = obtain_override_repositories()
|
||||
print('*** pytest-{0} ***'.format(pytest_version))
|
||||
print('Generating plugins_index page (pytest-{0})'.format(pytest_ver))
|
||||
plugins = list(plugins)
|
||||
for index, (package_name, version) in enumerate(plugins):
|
||||
print(package_name, version, '...', end='')
|
||||
if verbose:
|
||||
print(package_name, version, '...', end='')
|
||||
|
||||
release_data = client.release_data(package_name, version)
|
||||
|
||||
common_params = dict(
|
||||
site='http://pytest-plugs.herokuapp.com',
|
||||
site='http://plugincompat.herokuapp.com',
|
||||
name=package_name,
|
||||
version=version)
|
||||
|
||||
@@ -128,10 +133,10 @@ def obtain_plugins_table(plugins, client):
|
||||
image_url = url.format(**common_params)
|
||||
image_url += '?py={py}&pytest={pytest}'
|
||||
row = (
|
||||
ColumnData(package_name + "-" + version, release_data['package_url']),
|
||||
ColumnData(image_url.format(py='py27', pytest=pytest_version),
|
||||
ColumnData(package_name, release_data['package_url']),
|
||||
ColumnData(image_url.format(py='py27', pytest=pytest_ver),
|
||||
None),
|
||||
ColumnData(image_url.format(py='py34', pytest=pytest_version),
|
||||
ColumnData(image_url.format(py='py34', pytest=pytest_ver),
|
||||
None),
|
||||
ColumnData(
|
||||
repo_markup_1,
|
||||
@@ -148,9 +153,9 @@ def obtain_plugins_table(plugins, client):
|
||||
|
||||
row = (
|
||||
ColumnData('', None),
|
||||
ColumnData(output_url.format(py='py27', pytest=pytest_version),
|
||||
ColumnData(output_url.format(py='py27', pytest=pytest_ver),
|
||||
None),
|
||||
ColumnData(output_url.format(py='py34', pytest=pytest_version),
|
||||
ColumnData(output_url.format(py='py34', pytest=pytest_ver),
|
||||
None),
|
||||
ColumnData(repo_markup_2, None),
|
||||
ColumnData('', None),
|
||||
@@ -159,7 +164,10 @@ def obtain_plugins_table(plugins, client):
|
||||
assert len(row) == len(headers)
|
||||
rows.append(row)
|
||||
|
||||
print('OK (%d%%)' % ((index + 1) * 100 / len(plugins)))
|
||||
if verbose:
|
||||
print('OK (%d%%)' % ((index + 1) * 100 / len(plugins)))
|
||||
|
||||
print('Done: %d plugins' % len(plugins))
|
||||
|
||||
return headers, rows
|
||||
|
||||
@@ -179,13 +187,14 @@ def obtain_override_repositories():
|
||||
}
|
||||
|
||||
|
||||
def generate_plugins_index_from_table(filename, headers, rows):
|
||||
def generate_plugins_index_from_table(filename, headers, rows, pytest_ver):
|
||||
"""
|
||||
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`
|
||||
:param pytest_ver: see `obtain_plugins_table`
|
||||
"""
|
||||
# creates a list of rows, each being a str containing appropriate column
|
||||
# text and link
|
||||
@@ -210,7 +219,7 @@ def generate_plugins_index_from_table(filename, headers, rows):
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
# header
|
||||
header_text = HEADER.format(pytest_version=pytest.__version__)
|
||||
header_text = HEADER.format(pytest_version=pytest_ver)
|
||||
print(header_text, file=f)
|
||||
print(file=f)
|
||||
|
||||
@@ -235,17 +244,20 @@ def generate_plugins_index_from_table(filename, headers, rows):
|
||||
print('*(Updated on %s)*' % today, file=f)
|
||||
|
||||
|
||||
def generate_plugins_index(client, filename):
|
||||
def generate_plugins_index(client, filename, verbose, pytest_ver):
|
||||
"""
|
||||
Generates an RST file with a table of the latest pytest plugins found in
|
||||
PyPI.
|
||||
|
||||
:param client: ServerProxy
|
||||
:param filename: output filename
|
||||
:param verbose: print name and version of each plugin as they are fetch
|
||||
:param pytest_ver: pytest version to use; if not given, use current pytest
|
||||
version.
|
||||
"""
|
||||
plugins = get_latest_versions(iter_plugins(client))
|
||||
headers, rows = obtain_plugins_table(plugins, client)
|
||||
generate_plugins_index_from_table(filename, headers, rows)
|
||||
headers, rows = obtain_plugins_table(plugins, client, verbose, pytest_ver)
|
||||
generate_plugins_index_from_table(filename, headers, rows, pytest_ver)
|
||||
|
||||
|
||||
def main(argv):
|
||||
@@ -262,13 +274,17 @@ def main(argv):
|
||||
help='output filename [default: %default]')
|
||||
parser.add_option('-u', '--url', default=url,
|
||||
help='url of PyPI server to obtain data from [default: %default]')
|
||||
parser.add_option('-v', '--verbose', default=False, action='store_true',
|
||||
help='verbose output')
|
||||
parser.add_option('--pytest-ver', default=None, action='store',
|
||||
help='generate index for this pytest version (default current version)')
|
||||
(options, _) = parser.parse_args(argv[1:])
|
||||
|
||||
client = get_proxy(options.url)
|
||||
generate_plugins_index(client, options.filename)
|
||||
generate_plugins_index(client, options.filename, options.verbose, options.pytest_ver)
|
||||
|
||||
print()
|
||||
print('%s Updated.' % options.filename)
|
||||
print('%s updated.' % options.filename)
|
||||
return 0
|
||||
|
||||
|
||||
@@ -283,7 +299,7 @@ their status when tested using py.test **{pytest_version}** and python 2.7 and
|
||||
3.3.
|
||||
|
||||
A complete listing can also be found at
|
||||
`pytest-plugs <http://pytest-plugs.herokuapp.com/>`_, which contains tests
|
||||
`plugincompat <http://plugincompat.herokuapp.com/>`_, which contains tests
|
||||
status against other py.test releases.
|
||||
'''
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ Here are some examples of projects using ``pytest`` (please send notes via :ref:
|
||||
`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
|
||||
* `Astropy <http://www.astropy.org/>`_ and `affiliated packages <http://www.astropy.org/affiliated/index.html>`_
|
||||
* `tox <http://testrun.org/tox>`_, virtualenv/Hudson integration tool
|
||||
* `PIDA <http://pida.co.uk>`_ framework for integrated development
|
||||
* `PyPM <http://code.activestate.com/pypm/>`_ ActiveState's package manager
|
||||
@@ -78,6 +79,6 @@ Some organisations using pytest
|
||||
* `Stups department of Heinrich Heine University Duesseldorf <http://www.stups.uni-duesseldorf.de/projects.php>`_
|
||||
* `cellzome <http://www.cellzome.com/>`_
|
||||
* `Open End, Gothenborg <http://www.openend.se>`_
|
||||
* `Laboraratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
|
||||
* `Laboratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
|
||||
* `merlinux, Germany <http://merlinux.eu>`_
|
||||
* many more ... (please be so kind to send a note via :ref:`contact`)
|
||||
|
||||
@@ -164,7 +164,8 @@ Running it with the report-on-xfail option gives this output::
|
||||
|
||||
example $ py.test -rx xfail_demo.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /home/hpk/p/pytest/doc/en, inifile: pytest.ini
|
||||
collected 7 items
|
||||
|
||||
xfail_demo.py xxxxxxx
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pytest development status
|
||||
================================
|
||||
|
||||
https://drone.io/bitbucket.org/hpk42/pytest
|
||||
https://drone.io/bitbucket.org/pytest-dev/pytest
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ Talks and Tutorials
|
||||
Talks and blog postings
|
||||
---------------------------------------------
|
||||
|
||||
.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/
|
||||
.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf
|
||||
.. _`tutorial1 repository`: http://bitbucket.org/pytest-dev/pytest-tutorial1/
|
||||
.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/pytest-dev/pytest-tutorial1/raw/tip/pytest-basic.pdf
|
||||
|
||||
- `Introduction to pytest, Andreas Pelme, EuroPython 2014
|
||||
<https://www.youtube.com/watch?v=LdVJj65ikRY>`_.
|
||||
|
||||
@@ -159,7 +159,7 @@ command line options
|
||||
|
||||
each: send each test to each available environment.
|
||||
|
||||
load: send each test to available environment.
|
||||
load: send each test to one available environment so it is run only once.
|
||||
|
||||
(default) no: run tests inprocess, don't distribute.
|
||||
``--tx=xspec``
|
||||
|
||||
@@ -29,7 +29,8 @@ Running this would result in a passed test except for the last
|
||||
|
||||
$ py.test test_tmpdir.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-129, inifile:
|
||||
collected 1 items
|
||||
|
||||
test_tmpdir.py F
|
||||
@@ -37,7 +38,7 @@ Running this would result in a passed test except for the last
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_create_file _____________________________
|
||||
|
||||
tmpdir = local('/tmp/pytest-19/test_create_file0')
|
||||
tmpdir = local('/tmp/pytest-216/test_create_file0')
|
||||
|
||||
def test_create_file(tmpdir):
|
||||
p = tmpdir.mkdir("sub").join("hello.txt")
|
||||
|
||||
@@ -88,7 +88,8 @@ the ``self.db`` values in the traceback::
|
||||
|
||||
$ py.test test_unittest_db.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.4.0 -- py-1.4.25 -- pytest-2.6.3
|
||||
platform linux -- Python 3.4.0 -- py-1.4.26 -- pytest-2.7.0
|
||||
rootdir: /tmp/doc-exec-130, inifile:
|
||||
collected 2 items
|
||||
|
||||
test_unittest_db.py FF
|
||||
@@ -101,7 +102,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.db_class.<locals>.DummyDB object at 0x2b938b865208>
|
||||
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2ab102a4bac8>
|
||||
E assert 0
|
||||
|
||||
test_unittest_db.py:9: AssertionError
|
||||
@@ -111,11 +112,11 @@ the ``self.db`` values in the traceback::
|
||||
|
||||
def test_method2(self):
|
||||
> assert 0, self.db # fail for demo purposes
|
||||
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2b938b865208>
|
||||
E AssertionError: <conftest.db_class.<locals>.DummyDB object at 0x2ab102a4bac8>
|
||||
E assert 0
|
||||
|
||||
test_unittest_db.py:12: AssertionError
|
||||
========================= 2 failed in 0.05 seconds =========================
|
||||
========================= 2 failed in 0.04 seconds =========================
|
||||
|
||||
This default pytest traceback shows that the two test methods
|
||||
share the same ``self.db`` instance which was our intention
|
||||
@@ -162,7 +163,7 @@ Running this test module ...::
|
||||
|
||||
$ py.test -q test_unittest_cleandir.py
|
||||
.
|
||||
1 passed in 0.05 seconds
|
||||
1 passed in 0.04 seconds
|
||||
|
||||
... gives us one passed test because the ``initdir`` fixture function
|
||||
was executed ahead of the ``test_method``.
|
||||
|
||||
@@ -87,6 +87,17 @@ failure situation::
|
||||
py.test -x --pdb # drop to PDB on first failure, then end test session
|
||||
py.test --pdb --maxfail=3 # drop to PDB for first three failures
|
||||
|
||||
Note that on any failure the exception information is stored on
|
||||
``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
|
||||
interactive use, this allows one to drop into postmortem debugging with
|
||||
any debug tool. One can also manually access the exception information,
|
||||
for example::
|
||||
|
||||
>> import sys
|
||||
>> sys.last_traceback.tb_lineno
|
||||
42
|
||||
>> sys.last_value
|
||||
AssertionError('assert result == "ok"',)
|
||||
|
||||
Setting a breakpoint / aka ``set_trace()``
|
||||
----------------------------------------------------
|
||||
|
||||
@@ -192,6 +192,6 @@ These directory specifications are relative to the directory
|
||||
where the configuration file was found.
|
||||
|
||||
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
|
||||
.. _`pytest-xdist repository`: http://bitbucket.org/hpk42/pytest-xdist
|
||||
.. _`pytest-xdist repository`: http://bitbucket.org/pytest-dev/pytest-xdist
|
||||
.. _`pytest`: http://pytest.org
|
||||
|
||||
|
||||
@@ -51,7 +51,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 seamlessly use the new syntax with ``with`` statements.
|
||||
Let's simplify the above ``passwd`` fixture::
|
||||
|
||||
159
doc/ja/Makefile
159
doc/ja/Makefile
@@ -1,159 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = _build
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||
|
||||
regen:
|
||||
PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.txt */*.txt
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
install: html
|
||||
rsync -avz _build/html/ pytest.org:/www/pytest.org/latest-ja
|
||||
|
||||
installpdf: latexpdf
|
||||
@scp $(BUILDDIR)/latex/pytest.pdf pytest.org:/www/pytest.org/latest
|
||||
|
||||
installall: clean install installpdf
|
||||
@echo "done"
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pytest.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pytest.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/pytest"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pytest"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
make -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
texinfo:
|
||||
mkdir -p $(BUILDDIR)/texinfo
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
mkdir -p $(BUILDDIR)/texinfo
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
@@ -1,343 +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 290px 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: 260px;
|
||||
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.sphinxsidebar #searchbox input[type="submit"] {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
|
||||
..
|
||||
Release announcements
|
||||
===========================================
|
||||
|
||||
リリースアナウンス
|
||||
==================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
release-2.2.4
|
||||
release-2.2.2
|
||||
release-2.2.1
|
||||
release-2.2.0
|
||||
release-2.1.3
|
||||
release-2.1.2
|
||||
release-2.1.1
|
||||
release-2.1.0
|
||||
release-2.0.3
|
||||
release-2.0.2
|
||||
release-2.0.1
|
||||
release-2.0.0
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
py.test 2.0.0: asserts++, unittest++, reporting++, config++, docs++
|
||||
===========================================================================
|
||||
|
||||
Welcome to pytest-2.0.0, a major new release of "py.test", the rapid
|
||||
easy Python testing tool. There are many new features and enhancements,
|
||||
see below for summary and detailed lists. A lot of long-deprecated code
|
||||
has been removed, resulting in a much smaller and cleaner
|
||||
implementation. See the new docs with examples here:
|
||||
|
||||
http://pytest.org/2.0.0/index.html
|
||||
|
||||
A note on packaging: pytest used to part of the "py" distribution up
|
||||
until version py-1.3.4 but this has changed now: pytest-2.0.0 only
|
||||
contains py.test related code and is expected to be backward-compatible
|
||||
to existing test code. If you want to install pytest, just type one of::
|
||||
|
||||
pip install -U pytest
|
||||
easy_install -U pytest
|
||||
|
||||
Many thanks to all issue reporters and people asking questions or
|
||||
complaining. Particular thanks to Floris Bruynooghe and Ronny Pfannschmidt
|
||||
for their great coding contributions and many others for feedback and help.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
|
||||
New Features
|
||||
-----------------------
|
||||
|
||||
- new invocations through Python interpreter and from Python::
|
||||
|
||||
python -m pytest # on all pythons >= 2.5
|
||||
|
||||
or from a python program::
|
||||
|
||||
import pytest ; pytest.main(arglist, pluginlist)
|
||||
|
||||
see http://pytest.org/2.0.0/usage.html for details.
|
||||
|
||||
- new and better reporting information in assert expressions
|
||||
if comparing lists, sequences or strings.
|
||||
|
||||
see http://pytest.org/2.0.0/assert.html#newreport
|
||||
|
||||
- new configuration through ini-files (setup.cfg or tox.ini recognized),
|
||||
for example::
|
||||
|
||||
[pytest]
|
||||
norecursedirs = .hg data* # don't ever recurse in such dirs
|
||||
addopts = -x --pyargs # add these command line options by default
|
||||
|
||||
see http://pytest.org/2.0.0/customize.html
|
||||
|
||||
- improved standard unittest support. In general py.test should now
|
||||
better be able to run custom unittest.TestCases like twisted trial
|
||||
or Django based TestCases. Also you can now run the tests of an
|
||||
installed 'unittest' package with py.test::
|
||||
|
||||
py.test --pyargs unittest
|
||||
|
||||
- new "-q" option which decreases verbosity and prints a more
|
||||
nose/unittest-style "dot" output.
|
||||
|
||||
- many many more detailed improvements details
|
||||
|
||||
Fixes
|
||||
-----------------------
|
||||
|
||||
- fix issue126 - introduce py.test.set_trace() to trace execution via
|
||||
PDB during the running of tests even if capturing is ongoing.
|
||||
- fix issue124 - make reporting more resilient against tests opening
|
||||
files on filedescriptor 1 (stdout).
|
||||
- fix issue109 - sibling conftest.py files will not be loaded.
|
||||
(and Directory collectors cannot be customized anymore from a Directory's
|
||||
conftest.py - this needs to happen at least one level up).
|
||||
- fix issue88 (finding custom test nodes from command line arg)
|
||||
- fix issue93 stdout/stderr is captured while importing conftest.py
|
||||
- fix bug: unittest collected functions now also can have "pytestmark"
|
||||
applied at class/module level
|
||||
|
||||
Important Notes
|
||||
--------------------
|
||||
|
||||
* The usual way in pre-2.0 times to use py.test in python code was
|
||||
to import "py" and then e.g. use "py.test.raises" for the helper.
|
||||
This remains valid and is not planned to be deprecated. However,
|
||||
in most examples and internal code you'll find "import pytest"
|
||||
and "pytest.raises" used as the recommended default way.
|
||||
|
||||
* pytest now first performs collection of the complete test suite
|
||||
before running any test. This changes for example the semantics of when
|
||||
pytest_collectstart/pytest_collectreport are called. Some plugins may
|
||||
need upgrading.
|
||||
|
||||
* The pytest package consists of a 400 LOC core.py and about 20 builtin plugins,
|
||||
summing up to roughly 5000 LOCs, including docstrings. To be fair, it also
|
||||
uses generic code from the "pylib", and the new "py" package to help
|
||||
with filesystem and introspection/code manipulation.
|
||||
|
||||
(Incompatible) Removals
|
||||
-----------------------------
|
||||
|
||||
- py.test.config is now only available if you are in a test run.
|
||||
|
||||
- the following (mostly already deprecated) functionality was removed:
|
||||
|
||||
- removed support for Module/Class/... collection node definitions
|
||||
in conftest.py files. They will cause nothing special.
|
||||
- removed support for calling the pre-1.0 collection API of "run()" and "join"
|
||||
- removed reading option values from conftest.py files or env variables.
|
||||
This can now be done much much better and easier through the ini-file
|
||||
mechanism and the "addopts" entry in particular.
|
||||
- removed the "disabled" attribute in test classes. Use the skipping
|
||||
and pytestmark mechanism to skip or xfail a test class.
|
||||
|
||||
- py.test.collect.Directory does not exist anymore and it
|
||||
is not possible to provide an own "Directory" object.
|
||||
If you have used this and don't know what to do, get
|
||||
in contact. We'll figure something out.
|
||||
|
||||
Note that pytest_collect_directory() is still called but
|
||||
any return value will be ignored. This allows to keep
|
||||
old code working that performed for example "py.test.skip()"
|
||||
in collect() to prevent recursion into directory trees
|
||||
if a certain dependency or command line option is missing.
|
||||
|
||||
|
||||
see :ref:`changelog` for more detailed changes.
|
||||
@@ -1,67 +0,0 @@
|
||||
py.test 2.0.1: bug fixes
|
||||
===========================================================================
|
||||
|
||||
Welcome to pytest-2.0.1, a maintenance and bug fix release of pytest,
|
||||
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||
and latest PyPy interpreters. See extensive docs with tested examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Many thanks to all issue reporters and people asking questions or
|
||||
complaining. Particular thanks to Floris Bruynooghe and Ronny Pfannschmidt
|
||||
for their great coding contributions and many others for feedback and help.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
Changes between 2.0.0 and 2.0.1
|
||||
----------------------------------------------
|
||||
|
||||
- refine and unify initial capturing so that it works nicely
|
||||
even if the logging module is used on an early-loaded conftest.py
|
||||
file or plugin.
|
||||
- fix issue12 - show plugin versions with "--version" and
|
||||
"--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)
|
||||
- fix issue10 (numpy arrays truth checking) by refining
|
||||
assertion interpretation in py lib
|
||||
- fix issue15: make nose compatibility tests compatible
|
||||
with python3 (now that nose-1.0 supports python3)
|
||||
- remove somewhat surprising "same-conftest" detection because
|
||||
it ignores conftest.py when they appear in several subdirs.
|
||||
- improve assertions ("not in"), thanks Floris Bruynooghe
|
||||
- improve behaviour/warnings when running on top of "python -OO"
|
||||
(assertions and docstrings are turned off, leading to potential
|
||||
false positives)
|
||||
- introduce a pytest_cmdline_processargs(args) hook
|
||||
to allow dynamic computation of command line arguments.
|
||||
This fixes a regression because py.test prior to 2.0
|
||||
allowed to set command line options from conftest.py
|
||||
files which so far pytest-2.0 only allowed from ini-files now.
|
||||
- fix issue7: assert failures in doctest modules.
|
||||
unexpected failures in doctests will not generally
|
||||
show nicer, i.e. within the doctest failing context.
|
||||
- fix issue9: setup/teardown functions for an xfail-marked
|
||||
test will report as xfail if they fail but report as normally
|
||||
passing (not xpassing) if they succeed. This only is true
|
||||
for "direct" setup/teardown invocations because teardown_class/
|
||||
teardown_module cannot closely relate to a single test.
|
||||
- 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
|
||||
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
|
||||
setup as with pytest 1.3.4. Note, however, that
|
||||
the recommended and much cleaner way to do test
|
||||
parametrization remains the "pytest_generate_tests"
|
||||
mechanism, see the docs.
|
||||
@@ -1,73 +0,0 @@
|
||||
py.test 2.0.2: bug fixes, improved xfail/skip expressions, speed ups
|
||||
===========================================================================
|
||||
|
||||
Welcome to pytest-2.0.2, a maintenance and bug fix release of pytest,
|
||||
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||
and latest PyPy interpreters. See the extensive docs with tested examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Many thanks to all issue reporters and people asking questions
|
||||
or complaining, particularly Jurko for his insistence,
|
||||
Laura, Victor and Brianna for helping with improving
|
||||
and Ronny for his general advise.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
Changes between 2.0.1 and 2.0.2
|
||||
----------------------------------------------
|
||||
|
||||
- tackle issue32 - speed up test runs of very quick test functions
|
||||
by reducing the relative overhead
|
||||
|
||||
- fix issue30 - extended xfail/skipif handling and improved reporting.
|
||||
If you have a syntax error in your skip/xfail
|
||||
expressions you now get nice error reports.
|
||||
|
||||
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
|
||||
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
|
||||
(or xfail-ing) tests.
|
||||
|
||||
- fix issue28 - setup_method and pytest_generate_tests work together
|
||||
The setup_method fixture method now gets called also for
|
||||
test function invocations generated from the pytest_generate_tests
|
||||
hook.
|
||||
|
||||
- fix issue27 - collectonly and keyword-selection (-k) now work together
|
||||
Also, if you do "py.test --collectonly -q" you now get a flat list
|
||||
of test ids that you can use to paste to the py.test commandline
|
||||
in order to execute a particular test.
|
||||
|
||||
- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
|
||||
|
||||
- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
|
||||
Starting with Python3.2 os.symlink may be supported. By requiring
|
||||
a newer py lib version the py.path.local() implementation acknowledges
|
||||
this.
|
||||
|
||||
- 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
|
||||
(thanks Amaury)
|
||||
|
||||
- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
|
||||
|
||||
- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
|
||||
@@ -1,40 +0,0 @@
|
||||
py.test 2.0.3: bug fixes and speed ups
|
||||
===========================================================================
|
||||
|
||||
Welcome to pytest-2.0.3, a maintenance and bug fix release of pytest,
|
||||
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||
and latest PyPy interpreters. See the extensive docs with tested examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
There also is a bugfix release 1.6 of pytest-xdist, the plugin
|
||||
that enables seemless distributed and "looponfail" testing for Python.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
Changes between 2.0.2 and 2.0.3
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue38: nicer tracebacks on calls to hooks, particularly early
|
||||
configure/sessionstart ones
|
||||
|
||||
- fix missing skip reason/meta information in junitxml files, reported
|
||||
via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
|
||||
|
||||
- fix issue34: avoid collection failure with "test" prefixed classes
|
||||
deriving from object.
|
||||
|
||||
- don't require zlib (and other libs) for genscript plugin without
|
||||
--genscript actually being used.
|
||||
|
||||
- speed up skips (by not doing a full traceback represenation
|
||||
internally)
|
||||
|
||||
- fix issue37: avoid invalid characters in junitxml's output
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
py.test 2.1.0: perfected assertions and bug fixes
|
||||
===========================================================================
|
||||
|
||||
Welcome to the release of pytest-2.1, a mature testing tool for Python,
|
||||
supporting CPython 2.4-3.2, Jython and latest PyPy interpreters. See
|
||||
the improved extensive docs (now also as PDF!) with tested examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
The single biggest news about this release are **perfected assertions**
|
||||
courtesy of Benjamin Peterson. You can now safely use ``assert``
|
||||
statements in test modules without having to worry about side effects
|
||||
or python optimization ("-OO") options. This is achieved by rewriting
|
||||
assert statements in test modules upon import, using a PEP302 hook.
|
||||
See http://pytest.org/assert.html#advanced-assertion-introspection for
|
||||
detailed information. The work has been partly sponsored by my company,
|
||||
merlinux GmbH.
|
||||
|
||||
For further details on bug fixes and smaller enhancements see below.
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
|
||||
Changes between 2.0.3 and 2.1.0
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue53 call nosestyle setup functions with correct ordering
|
||||
- fix issue58 and issue59: new assertion code fixes
|
||||
- merge Benjamin's assertionrewrite branch: now assertions
|
||||
for test modules on python 2.6 and above are done by rewriting
|
||||
the AST and saving the pyc file before the test module is imported.
|
||||
see doc/assert.txt for more info.
|
||||
- fix issue43: improve doctests with better traceback reporting on
|
||||
unexpected exceptions
|
||||
- fix issue47: timing output in junitxml for test cases is now correct
|
||||
- fix issue48: typo in MarkInfo repr leading to exception
|
||||
- fix issue49: avoid confusing error when initialization partially fails
|
||||
- fix issue44: env/username expansion for junitxml file path
|
||||
- show releaselevel information in test runs for pypy
|
||||
- reworked doc pages for better navigation and PDF generation
|
||||
- report KeyboardInterrupt even if interrupted during session startup
|
||||
- fix issue 35 - provide PDF doc version and download link from index page
|
||||
@@ -1,37 +0,0 @@
|
||||
py.test 2.1.1: assertion fixes and improved junitxml output
|
||||
===========================================================================
|
||||
|
||||
pytest-2.1.1 is a backward compatible maintenance release of the
|
||||
popular py.test testing tool. See extensive docs with examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
Most bug fixes address remaining issues with the perfected assertions
|
||||
introduced with 2.1.0 - many thanks to the bug reporters and to Benjamin
|
||||
Peterson for helping to fix them. Also, junitxml output now produces
|
||||
system-out/err tags which lead to better displays of tracebacks with Jenkins.
|
||||
|
||||
Also a quick note to package maintainers and others interested: there now
|
||||
is a "pytest" man page which can be generated with "make man" in doc/.
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
|
||||
Changes between 2.1.0 and 2.1.1
|
||||
----------------------------------------------
|
||||
|
||||
- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
|
||||
- fix issue60 / fix error conditions involving the creation of __pycache__
|
||||
- fix issue63 / assertion rewriting on inserts involving strings containing '%'
|
||||
- fix assertion rewriting on calls with a ** arg
|
||||
- don't cache rewritten modules if bytecode generation is disabled
|
||||
- fix assertion rewriting in read-only directories
|
||||
- fix issue59: provide system-out/err tags for junitxml output
|
||||
- fix issue61: assertion rewriting on boolean operations with 3 or more operands
|
||||
- you can now build a man page with "cd doc ; make man"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
py.test 2.1.2: bug fixes and fixes for jython
|
||||
===========================================================================
|
||||
|
||||
pytest-2.1.2 is a minor backward compatible maintenance release of the
|
||||
popular py.test testing tool. pytest is commonly used for unit,
|
||||
functional- and integration testing. See extensive docs with examples
|
||||
here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
Most bug fixes address remaining issues with the perfected assertions
|
||||
introduced in the 2.1 series - many thanks to the bug reporters and to Benjamin
|
||||
Peterson for helping to fix them. pytest should also work better with
|
||||
Jython-2.5.1 (and Jython trunk).
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
|
||||
Changes between 2.1.1 and 2.1.2
|
||||
----------------------------------------
|
||||
|
||||
- fix assertion rewriting on files with windows newlines on some Python versions
|
||||
- refine test discovery by package/module name (--pyargs), thanks Florian Mayer
|
||||
- fix issue69 / assertion rewriting fixed on some boolean operations
|
||||
- fix issue68 / packages now work with assertion rewriting
|
||||
- fix issue66: use different assertion rewriting caches when the -O option is passed
|
||||
- don't try assertion rewriting on Jython, use reinterp
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
py.test 2.1.3: just some more fixes
|
||||
===========================================================================
|
||||
|
||||
pytest-2.1.3 is a minor backward compatible maintenance release of the
|
||||
popular py.test testing tool. It is commonly used for unit, functional-
|
||||
and integration testing. See extensive docs with examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
The release contains another fix to the perfected assertions introduced
|
||||
with the 2.1 series as well as the new possibility to customize reporting
|
||||
for assertion expressions on a per-directory level.
|
||||
|
||||
If you want to install or upgrade pytest, just type one of::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Thanks to the bug reporters and to Ronny Pfannschmidt, Benjamin Peterson
|
||||
and Floris Bruynooghe who implemented the fixes.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
Changes between 2.1.2 and 2.1.3
|
||||
----------------------------------------
|
||||
|
||||
- fix issue79: assertion rewriting failed on some comparisons in boolops,
|
||||
- correctly handle zero length arguments (a la pytest '')
|
||||
- fix issue67 / junitxml now contains correct test durations
|
||||
- fix issue75 / skipping test failure on jython
|
||||
- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
|
||||
@@ -1,95 +0,0 @@
|
||||
py.test 2.2.0: test marking++, parametrization++ and duration profiling
|
||||
===========================================================================
|
||||
|
||||
pytest-2.2.0 is a test-suite compatible release of the popular
|
||||
py.test testing tool. Plugins might need upgrades. It comes
|
||||
with these improvements:
|
||||
|
||||
* easier and more powerful parametrization of tests:
|
||||
|
||||
- new @pytest.mark.parametrize decorator to run tests with different arguments
|
||||
- new metafunc.parametrize() API for parametrizing arguments independently
|
||||
- see examples at http://pytest.org/latest/example/parametrize.html
|
||||
- NOTE that parametrize() related APIs are still a bit experimental
|
||||
and might change in future releases.
|
||||
|
||||
* improved handling of test markers and refined marking mechanism:
|
||||
|
||||
- "-m markexpr" option for selecting tests according to their mark
|
||||
- a new "markers" ini-variable for registering test markers for your project
|
||||
- the new "--strict" bails out with an error if using unregistered markers.
|
||||
- see examples at http://pytest.org/latest/example/markers.html
|
||||
|
||||
* duration profiling: new "--duration=N" option showing the N slowest test
|
||||
execution or setup/teardown calls. This is most useful if you want to
|
||||
find out where your slowest test code is.
|
||||
|
||||
* also 2.2.0 performs more eager calling of teardown/finalizers functions
|
||||
resulting in better and more accurate reporting when they fail
|
||||
|
||||
Besides there is the usual set of bug fixes along with a cleanup of
|
||||
pytest's own test suite allowing it to run on a wider range of environments.
|
||||
|
||||
For general information, see extensive docs with examples here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
If you want to install or upgrade pytest you might just type::
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Thanks to Ronny Pfannschmidt, David Burns, Jeff Donner, Daniel Nouri, Alfredo Deza and all who gave feedback or sent bug reports.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
|
||||
notes on incompatibility
|
||||
------------------------------
|
||||
|
||||
While test suites should work unchanged you might need to upgrade plugins:
|
||||
|
||||
* You need a new version of the pytest-xdist plugin (1.7) for distributing
|
||||
test runs.
|
||||
|
||||
* Other plugins might need an upgrade if they implement
|
||||
the ``pytest_runtest_logreport`` hook which now is called unconditionally
|
||||
for the setup/teardown fixture phases of a test. You may choose to
|
||||
ignore setup/teardown failures by inserting "if rep.when != 'call': return"
|
||||
or something similar. Note that most code probably "just" works because
|
||||
the hook was already called for failing setup/teardown phases of a test
|
||||
so a plugin should have been ready to grok such reports already.
|
||||
|
||||
|
||||
Changes between 2.1.3 and 2.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
|
||||
parametrize test function arguments in multiple steps and therefore
|
||||
from independent plugins and places.
|
||||
- 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
|
||||
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
|
||||
will treat unregistered markers as errors
|
||||
allowing to avoid typos and maintain a well described set of markers
|
||||
for your test suite. See examples at http://pytest.org/latest/mark.html
|
||||
and its links.
|
||||
- issue50: introduce "-m marker" option to select tests based on markers
|
||||
(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
|
||||
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 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
|
||||
@@ -1,41 +0,0 @@
|
||||
pytest-2.2.1: bug fixes, perfect teardowns
|
||||
===========================================================================
|
||||
|
||||
|
||||
pytest-2.2.1 is a minor backward-compatible release of the the py.test
|
||||
testing tool. It contains bug fixes and little improvements, including
|
||||
documentation fixes. If you are using the distributed testing
|
||||
pluginmake sure to upgrade it to pytest-xdist-1.8.
|
||||
|
||||
For general information see here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
To install or upgrade pytest:
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Special thanks for helping on this release to Ronny Pfannschmidt, Jurko
|
||||
Gospodnetic and Ralf Schmitt.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
|
||||
Changes between 2.2.0 and 2.2.1
|
||||
----------------------------------------
|
||||
|
||||
- fix issue99 (in pytest and py) internallerrors with resultlog now
|
||||
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
|
||||
- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
|
||||
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
|
||||
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)
|
||||
@@ -1,43 +0,0 @@
|
||||
pytest-2.2.2: bug fixes
|
||||
===========================================================================
|
||||
|
||||
pytest-2.2.2 (updated to 2.2.3 to fix packaging issues) is a minor
|
||||
backward-compatible release of the versatile py.test testing tool. It
|
||||
contains bug fixes and a few refinements particularly to reporting with
|
||||
"--collectonly", see below for betails.
|
||||
|
||||
For general information see here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
To install or upgrade pytest:
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Special thanks for helping on this release to Ronny Pfannschmidt
|
||||
and Ralf Schmitt and the contributors of issues.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
|
||||
Changes between 2.2.1 and 2.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
|
||||
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.
|
||||
- fix issue107: actually perform session scope finalization
|
||||
- don't check in parametrize if indirect parameters are funcarg names
|
||||
- add chdir method to monkeypatch funcarg
|
||||
- fix crash resulting from calling monkeypatch undo a second time
|
||||
- fix issue115: make --collectonly robust against early failure
|
||||
(missing files/directories)
|
||||
- "-qq --collectonly" now shows only files and the number of tests in them
|
||||
- "-q --collectonly" now shows test ids
|
||||
- allow adding of attributes to test reports such that it also works
|
||||
with distributed testing (no upgrade of pytest-xdist needed)
|
||||
@@ -1,39 +0,0 @@
|
||||
pytest-2.2.4: bug fixes, better junitxml/unittest/python3 compat
|
||||
===========================================================================
|
||||
|
||||
pytest-2.2.4 is a minor backward-compatible release of the versatile
|
||||
py.test testing tool. It contains bug fixes and a few refinements
|
||||
to junitxml reporting, better unittest- and python3 compatibility.
|
||||
|
||||
For general information see here:
|
||||
|
||||
http://pytest.org/
|
||||
|
||||
To install or upgrade pytest:
|
||||
|
||||
pip install -U pytest # or
|
||||
easy_install -U pytest
|
||||
|
||||
Special thanks for helping on this release to Ronny Pfannschmidt
|
||||
and Benjamin Peterson and the contributors of issues.
|
||||
|
||||
best,
|
||||
holger krekel
|
||||
|
||||
Changes between 2.2.3 and 2.2.4
|
||||
-----------------------------------
|
||||
|
||||
- fix error message for rewritten assertions involving the % operator
|
||||
- fix issue 126: correctly match all invalid xml characters for junitxml
|
||||
binary escape
|
||||
- fix issue with unittest: now @unittest.expectedFailure markers should
|
||||
be processed correctly (you can also use @pytest.mark markers)
|
||||
- document integration with the extended distribute/setuptools test commands
|
||||
- fix issue 140: propperly get the real functions
|
||||
of bound classmethods for setup/teardown_class
|
||||
- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
|
||||
- fix issue #143: call unconfigure/sessionfinish always when
|
||||
configure/sessionstart where called
|
||||
- fix issue #144: better mangle test ids to junitxml classnames
|
||||
- upgrade distribute_setup.py to 0.6.27
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
|
||||
.. _apiref:
|
||||
|
||||
py.test リファレンスドキュメント
|
||||
================================
|
||||
|
||||
..
|
||||
py.test reference documentation
|
||||
================================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
builtin.txt
|
||||
customize.txt
|
||||
assert.txt
|
||||
funcargs.txt
|
||||
xunit_setup.txt
|
||||
capture.txt
|
||||
monkeypatch.txt
|
||||
xdist.txt
|
||||
tmpdir.txt
|
||||
skipping.txt
|
||||
mark.txt
|
||||
recwarn.txt
|
||||
unittest.txt
|
||||
nose.txt
|
||||
doctest.txt
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
|
||||
..
|
||||
The writing and reporting of assertions in tests
|
||||
==================================================
|
||||
|
||||
テストのアサーションにおける書き込みとレポート
|
||||
==============================================
|
||||
|
||||
.. _`assert with the assert statement`:
|
||||
|
||||
``assert`` 文によるアサーション
|
||||
-------------------------------
|
||||
|
||||
..
|
||||
Asserting with the ``assert`` statement
|
||||
---------------------------------------------------------
|
||||
|
||||
..
|
||||
``py.test`` allows you to use the standard python ``assert`` for verifying
|
||||
expectations and values in Python tests. For example, you can write the
|
||||
following::
|
||||
|
||||
``py.test`` は、テストで期待値と実際の値を検証するのに Python 標準の ``assert`` 文が使えます。例えば、次のようにテストを作成します::
|
||||
|
||||
# test_assert1.py の内容
|
||||
def f():
|
||||
return 3
|
||||
|
||||
def test_function():
|
||||
assert f() == 4
|
||||
|
||||
..
|
||||
to assert that your function returns a certain value. If this assertion fails
|
||||
you will see the return value of the function call::
|
||||
|
||||
このサンプルは、関数が特定の値を返すのをアサートします。このアサーションが失敗した場合、関数呼び出しの返り値が表示されます::
|
||||
|
||||
$ py.test test_assert1.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
collecting ... collected 1 items
|
||||
|
||||
test_assert1.py F
|
||||
|
||||
================================= FAILURES =================================
|
||||
______________________________ test_function _______________________________
|
||||
|
||||
def test_function():
|
||||
> assert f() == 4
|
||||
E assert 3 == 4
|
||||
E + where 3 = f()
|
||||
|
||||
test_assert1.py:5: AssertionError
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
..
|
||||
py.test 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
|
||||
introspection information.
|
||||
|
||||
py.test は、関数呼び出し、属性、比較、バイナリや単項演算子といった処理を含む通常の部分式の値を表示する機能があります (:ref:`tbreportdemo` を参照) 。この機能により、定型的なコードを必要とせず、Python イディオム的な概念も利用できます。その上でイントロスペクション情報を失うこともありません。
|
||||
|
||||
..
|
||||
However, if you specify a message with the assertion like this::
|
||||
|
||||
但し、次のようにアサーションと一緒にメッセージを指定した場合::
|
||||
|
||||
assert a % 2 == 0, "value was odd, should be even"
|
||||
|
||||
..
|
||||
then no assertion introspection takes places at all and the message
|
||||
will be simply shown in the traceback.
|
||||
|
||||
そこでアサートイントロスペクションを行わず、このメッセージは単純にトレースバックで表示されます。
|
||||
|
||||
..
|
||||
See :ref:`assert-details` for more information on assertion introspection.
|
||||
|
||||
アサートイントロスペクションの詳細については :ref:`assert-details` を参照してください。
|
||||
|
||||
..
|
||||
Assertions about expected exceptions
|
||||
------------------------------------------
|
||||
|
||||
例外発生を期待するアサーション
|
||||
------------------------------
|
||||
|
||||
..
|
||||
In order to write assertions about raised exceptions, you can use
|
||||
``pytest.raises`` as a context manager like this::
|
||||
|
||||
発生した例外のアサーションを行うには、次のようにコンテキスト マネージャーとして ``pytest.raises`` を使います::
|
||||
|
||||
import pytest
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
1 / 0
|
||||
|
||||
..
|
||||
and if you need to have access to the actual exception info you may use::
|
||||
|
||||
もし実際の例外の情報を調べる必要があるなら、次のように行います::
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
def f():
|
||||
f()
|
||||
f()
|
||||
|
||||
# excinfo.type, excinfo.value, excinfo.traceback といった関連する値を確認する
|
||||
|
||||
..
|
||||
If you want to write test code that works on Python 2.4 as well,
|
||||
you may also use two other ways to test for an expected exception::
|
||||
|
||||
Python 2.4 でも同じように動作するテストコードを書きたいなら、例外発生を期待するテストを行う別の方法が2つあります::
|
||||
|
||||
pytest.raises(ExpectedException, func, *args, **kwargs)
|
||||
pytest.raises(ExpectedException, "func(*args, **kwargs)")
|
||||
|
||||
..
|
||||
both of which execute the specified function with args and kwargs and
|
||||
asserts that the given ``ExpectedException`` is raised. The reporter will
|
||||
provide you with helpful output in case of failures such as *no
|
||||
exception* or *wrong exception*.
|
||||
|
||||
両方とも指定した関数へ args と kwargs を渡して実行し、引数として与えた ``ExpectedException`` が発生することをアサートします。このレポートは *no exception* または *wrong exception* といったテストに失敗したときに分かりやすい内容を表示します。
|
||||
|
||||
.. _newreport:
|
||||
|
||||
コンテキストに依存した内容の比較
|
||||
--------------------------------
|
||||
|
||||
..
|
||||
Making use of context-sensitive comparisons
|
||||
-------------------------------------------------
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
..
|
||||
py.test has rich support for providing context-sensitive information
|
||||
when it encounters comparisons. For example::
|
||||
|
||||
py.test は、比較するときにコンテキスト依存の情報を分かりやすく表示します。例えば、::
|
||||
|
||||
# test_assert2.py の内容
|
||||
|
||||
def test_set_comparison():
|
||||
set1 = set("1308")
|
||||
set2 = set("8035")
|
||||
assert set1 == set2
|
||||
|
||||
..
|
||||
if you run this module::
|
||||
|
||||
このモジュールを実行すると::
|
||||
|
||||
$ py.test test_assert2.py
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
collecting ... collected 1 items
|
||||
|
||||
test_assert2.py F
|
||||
|
||||
================================= FAILURES =================================
|
||||
___________________________ test_set_comparison ____________________________
|
||||
|
||||
def test_set_comparison():
|
||||
set1 = set("1308")
|
||||
set2 = set("8035")
|
||||
> assert set1 == set2
|
||||
E assert set(['0', '1', '3', '8']) == set(['0', '3', '5', '8'])
|
||||
E Extra items in the left set:
|
||||
E '1'
|
||||
E Extra items in the right set:
|
||||
E '5'
|
||||
|
||||
test_assert2.py:5: AssertionError
|
||||
========================= 1 failed in 0.01 seconds =========================
|
||||
|
||||
..
|
||||
Special comparisons are done for a number of cases:
|
||||
|
||||
複数のケースにおいて、特別な比較が行われます:
|
||||
|
||||
..
|
||||
* comparing long strings: a context diff is shown
|
||||
* comparing long sequences: first failing indices
|
||||
* comparing dicts: different entries
|
||||
|
||||
* 長い文字列の比較: コンテキスト diff を表示
|
||||
* 長いシーケンスの比較: 最初に失敗したインデックス
|
||||
* ディクショナリの比較: 異なるエントリ
|
||||
|
||||
..
|
||||
See the :ref:`reporting demo <tbreportdemo>` for many more examples.
|
||||
|
||||
より多くのサンプルについては :ref:`レポートのデモ <tbreportdemo>` 参照してください。
|
||||
|
||||
..
|
||||
Defining your own assertion comparison
|
||||
----------------------------------------------
|
||||
|
||||
アサーション比較の定義
|
||||
----------------------
|
||||
|
||||
..
|
||||
It is possible to add your own detailed explanations by implementing
|
||||
the ``pytest_assertrepr_compare`` hook.
|
||||
|
||||
``pytest_assertrepr_compare`` フックを実装することで独自の詳細説明を追加できます。
|
||||
|
||||
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
|
||||
|
||||
..
|
||||
As an example consider adding the following hook in a conftest.py which
|
||||
provides an alternative explanation for ``Foo`` objects::
|
||||
|
||||
例として、conftest.py に次のフックを追加してみます。これは ``Foo`` オブジェクトの別の説明を提供します::
|
||||
|
||||
# conftest.py の内容
|
||||
from test_foocompare import Foo
|
||||
def pytest_assertrepr_compare(op, left, right):
|
||||
if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
|
||||
return ['Comparing Foo instances:',
|
||||
' vals: %s != %s' % (left.val, right.val)]
|
||||
|
||||
..
|
||||
now, given this test module::
|
||||
|
||||
ここで次のテストモジュールがあります::
|
||||
|
||||
# test_foocompare.py の内容
|
||||
class Foo:
|
||||
def __init__(self, val):
|
||||
self.val = val
|
||||
|
||||
def test_compare():
|
||||
f1 = Foo(1)
|
||||
f2 = Foo(2)
|
||||
assert f1 == f2
|
||||
|
||||
..
|
||||
you can run the test module and get the custom output defined in
|
||||
the conftest file::
|
||||
|
||||
このテストモジュールを実行すると、conftest ファイルで定義した独自の出力内容が表示されます::
|
||||
|
||||
$ py.test -q test_foocompare.py
|
||||
collecting ... collected 1 items
|
||||
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
|
||||
|
||||
.. _assert-details:
|
||||
.. _`assert introspection`:
|
||||
|
||||
高度なアサートイントロスペクション
|
||||
----------------------------------
|
||||
|
||||
..
|
||||
Advanced assertion introspection
|
||||
----------------------------------
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
..
|
||||
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
|
||||
message, i.e. ``assert expr, message``, no assertion introspection takes place
|
||||
and the manually provided message will be rendered in tracebacks.
|
||||
|
||||
失敗するアサーションに関する詳細のレポートは、実行前に assert 文を書き換えるか、または assert 式を再評価して中間値を記録するかのどちらかの方法で行われます。どちらの方法を使うかは assert の位置、pytest の設定、pytest を実行するのに使われる Python バージョンに依存します。 ``assert expr, message`` のように直接コード内でメッセージを記述した assert 文は、アサートイントロスペクションが行われず、指定したメッセージがトレースバックに表示されることに注意してください。
|
||||
|
||||
..
|
||||
By default, if the Python version is greater than or equal to 2.6, py.test
|
||||
rewrites assert statements in test modules. Rewritten assert statements put
|
||||
introspection information into the assertion failure message. py.test 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.
|
||||
|
||||
デフォルトでは、Python バージョンが 2.6 以上の場合、py.test はテストモジュールの assert 文を書き換えます。書き換えられた assert 文は、イントロスペクション情報をアサーションの失敗メッセージに追加します。py.test は、テストコレクション処理で検出したテストモジュールのみを直接書き換えます。そのため、テストモジュールではないサポートライブラリの assert 文は書き換えられません。
|
||||
|
||||
.. 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
|
||||
``--assert=plain``. Additionally, rewriting will fail silently if it cannot
|
||||
write new pycs, i.e. in a read-only filesystem or a zipfile.
|
||||
|
||||
py.test は、インポート時にテストモジュールを書き換えます。新たに pyc ファイルを書き込むためにインポートフックを使うことでこの処理を行います。この処理はほとんど透過的に行われます。但し、自分でインポートを行ってごちゃごちゃになっている場合、そのインポートフックがインターフェースになる可能性があります。このようなケースでは、単純に ``--assert=reinterp`` か ``--assert=plain`` を使ってください。さらに、新たに pyc ファイルを書き込めない場合、書き換えはサイレントモードで失敗します。例えば、読み込み専用ファイルシステムや zip ファイルで行うようなときです。
|
||||
|
||||
..
|
||||
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.
|
||||
|
||||
assert 文が書き換えられない、または Python バージョン 2.6 よりも小さい場合、py.test はアサーションの再解釈を行います。アサーションの再解釈では、py.test が、assert 文の失敗する部分式を見つけるために assert 文を含む関数のフレームを辿ります。py.test にアサーションの再解釈を行うよう強制するには ``--assert=reinterp`` オプションを指定します。
|
||||
|
||||
..
|
||||
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
|
||||
intermediate values could not be determined safely. A common example of this
|
||||
issue is an assertion which reads from a file::
|
||||
|
||||
アサーションの再解釈は、assert 文の書き換えを行わないことの注意が必要です: それは assert 式の評価が副作用をもつ場合、中間値が安全に決定しないという警告を受け取るかもしれません。この問題の一般的な例として、ファイルを読み込むアサーションがあります::
|
||||
|
||||
assert f.read() != '...'
|
||||
|
||||
..
|
||||
If this assertion fails then the re-evaluation will probably succeed!
|
||||
This is because ``f.read()`` will return an empty string when it is
|
||||
called the second time during the re-evaluation. However, it is
|
||||
easy to rewrite the assertion and avoid any trouble::
|
||||
|
||||
このアサーションが失敗した場合、その再評価はおそらく成功します!つまり再評価において2回目に呼び出されたときに ``f.read()`` が空の文字列を返すからです。とはいえ、このアサーションを書き換えて、そういったトラブルを避けるのは簡単です::
|
||||
|
||||
content = f.read()
|
||||
assert content != '...'
|
||||
|
||||
..
|
||||
All assert introspection can be turned off by passing ``--assert=plain``.
|
||||
|
||||
全てのアサートイントロスペクションを無効にするには ``--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>`_.
|
||||
|
||||
詳細については、Benjamin Peterson が詳しくまとめた `Behind the scenes of py.test's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_ を参照してください。
|
||||
|
||||
..
|
||||
Add assert rewriting as an alternate introspection technique.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
代替イントロスペクション手法として assert 書き換え機能を追加
|
||||
|
||||
..
|
||||
Introduce the ``--assert`` option. Deprecate ``--no-assert`` and
|
||||
``--nomagic``.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
``--assert`` オプションを追加。 ``--no-assert`` と ``--nomagic`` を廃止。
|
||||
@@ -1,152 +0,0 @@
|
||||
|
||||
.. _`pytest helpers`:
|
||||
|
||||
Pytest 組み込みヘルパー機能
|
||||
===========================
|
||||
|
||||
..
|
||||
Pytest builtin helpers
|
||||
================================================
|
||||
|
||||
..
|
||||
builtin pytest.* functions and helping objects
|
||||
-----------------------------------------------------
|
||||
|
||||
組み込みの pytest.* 関数とヘルパーオブジェクト
|
||||
----------------------------------------------
|
||||
|
||||
..
|
||||
You can always use an interactive Python prompt and type::
|
||||
|
||||
Python インタープリターの対話モードから次のように入力すると::
|
||||
|
||||
import pytest
|
||||
help(pytest)
|
||||
|
||||
..
|
||||
to get an overview on the globally available helpers.
|
||||
|
||||
グローバルに利用できるヘルパー機能の概要を把握できます。
|
||||
|
||||
.. automodule:: pytest
|
||||
:members:
|
||||
|
||||
|
||||
.. _builtinfuncargs:
|
||||
|
||||
組み込み関数の引数
|
||||
------------------
|
||||
|
||||
..
|
||||
Builtin function arguments
|
||||
-----------------------------------------------------
|
||||
|
||||
..
|
||||
You can ask for available builtin or project-custom
|
||||
:ref:`function arguments <funcargs>` by typing::
|
||||
|
||||
次のように入力して、利用できる組み込みまたはプロジェクトカスタムの :ref:`関数の引数 <funcargs>` を確認できます。
|
||||
|
||||
| $ py.test --fixtures
|
||||
| ====================== test session starts =======================
|
||||
| platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
| collected 0 items
|
||||
| pytestconfig
|
||||
| pytest の config オブジェクトとコマンドラインオプションへのアクセス
|
||||
|
|
||||
| capsys
|
||||
| sys.stdout/sys.stderr への書き込み内容を取得できる
|
||||
| キャプチャした出力内容は ``(out, err)`` のタプルを返す
|
||||
| ``capsys.readouterr()`` メソッドで利用できる
|
||||
|
|
||||
| capfd
|
||||
| ファイルディスクリプタ 1 と 2 へ書き込み内容を取得できる
|
||||
| キャプチャした出力内容は ``(out, err)`` のタプルを返す
|
||||
| ``capsys.readouterr()`` メソッドで利用できる
|
||||
|
|
||||
| tmpdir
|
||||
| 基本となる一時ディレクトリ配下にサブディレクトリを作成して、
|
||||
| テスト関数の実行毎に一意な一時ディレクトリのオブジェクトを返す
|
||||
| これは py.path.local のパスオブジェクトが返される
|
||||
|
|
||||
| monkeypatch
|
||||
| オブジェクト、ディクショナリ、os.environ を変更する
|
||||
| 次のヘルパーメソッドを提供する ``monkeypatch`` オブジェクトが返される
|
||||
|
|
||||
| monkeypatch.setattr(obj, name, value, raising=True)
|
||||
| monkeypatch.delattr(obj, name, raising=True)
|
||||
| monkeypatch.setitem(mapping, name, value)
|
||||
| monkeypatch.delitem(obj, name, raising=True)
|
||||
| monkeypatch.setenv(name, value, prepend=False)
|
||||
| monkeypatch.delenv(name, value, raising=True)
|
||||
| monkeypatch.syspath_prepend(path)
|
||||
| monkeypatch.chdir(path)
|
||||
|
|
||||
| 全ての変更はテスト関数の呼び出しが終わった後で元に戻ります
|
||||
| ``raising`` パラメーターは、セット/削除の操作対象がないときに
|
||||
| KeyError や AttributeError を発生させるかどうかを決めます
|
||||
|
|
||||
| recwarn
|
||||
| 次のメソッドを提供する WarningsRecorder インスタンスを返す
|
||||
|
|
||||
| * ``pop(category=None)``: category に一致する最後の警告を返す
|
||||
| * ``clear()``: 警告のリストを削除する
|
||||
|
|
||||
| 警告については http://docs.python.org/library/warnings.html を
|
||||
| 参照してください
|
||||
|
|
||||
| ======================== in 0.00 seconds ========================
|
||||
|
||||
..
|
||||
$ py.test --fixtures
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
collected 0 items
|
||||
pytestconfig
|
||||
the pytest config object with access to command line opts.
|
||||
capsys
|
||||
enables capturing of writes to sys.stdout/sys.stderr and makes
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple.
|
||||
|
||||
capfd
|
||||
enables capturing of writes to file descriptors 1 and 2 and makes
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple.
|
||||
|
||||
tmpdir
|
||||
return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
created as a sub directory of the base temporary
|
||||
directory. The returned object is a `py.path.local`_
|
||||
path object.
|
||||
|
||||
monkeypatch
|
||||
The returned ``monkeypatch`` funcarg provides these
|
||||
helper methods to modify objects, dictionaries or os.environ::
|
||||
|
||||
monkeypatch.setattr(obj, name, value, raising=True)
|
||||
monkeypatch.delattr(obj, name, raising=True)
|
||||
monkeypatch.setitem(mapping, name, value)
|
||||
monkeypatch.delitem(obj, name, raising=True)
|
||||
monkeypatch.setenv(name, value, prepend=False)
|
||||
monkeypatch.delenv(name, value, raising=True)
|
||||
monkeypatch.syspath_prepend(path)
|
||||
monkeypatch.chdir(path)
|
||||
|
||||
All modifications will be undone after the requesting
|
||||
test function has finished. The ``raising``
|
||||
parameter determines if a KeyError or AttributeError
|
||||
will be raised if the set/deletion operation has no target.
|
||||
|
||||
recwarn
|
||||
Return a WarningsRecorder instance that provides these methods:
|
||||
|
||||
* ``pop(category=None)``: return last warning matching the category.
|
||||
* ``clear()``: clear list of warnings
|
||||
|
||||
See http://docs.python.org/library/warnings.html for information
|
||||
on warning categories.
|
||||
|
||||
|
||||
============================= in 0.00 seconds =============================
|
||||
@@ -1,170 +0,0 @@
|
||||
|
||||
.. _`captures`:
|
||||
|
||||
標準出力/標準エラーのキャプチャ
|
||||
===============================
|
||||
|
||||
..
|
||||
Capturing of the stdout/stderr output
|
||||
=========================================================
|
||||
|
||||
..
|
||||
Default stdout/stderr/stdin capturing behaviour
|
||||
---------------------------------------------------------
|
||||
|
||||
デフォルトの stdout/stderr/stdin のキャプチャ処理
|
||||
-------------------------------------------------
|
||||
|
||||
..
|
||||
During test execution any output sent to ``stdout`` and ``stderr`` is
|
||||
captured. If a test or a setup method fails its according captured
|
||||
output will usually be shown along with the failure traceback.
|
||||
|
||||
テストの実行中 ``stdout`` と ``stderr`` へ送られる全ての出力内容はキャプチャされます。テストまたはセットアップメソッドが失敗した場合、そこでキャプチャされた出力は、通常、エラートレースバックと一緒に表示されます。
|
||||
|
||||
..
|
||||
In addition, ``stdin`` is set to a "null" object which will
|
||||
fail on attempts to read from it because it is rarely desired
|
||||
to wait for interactive input when running automated tests.
|
||||
|
||||
加えて ``stdin`` は、その読み込みに失敗する "null" オブジェクトがセットされます。その理由は自動テストを実行するときに対話式の入力を待つのを考慮することはほとんどないからです。
|
||||
|
||||
..
|
||||
By default capturing is done by intercepting writes to low level
|
||||
file descriptors. This allows to capture output from simple
|
||||
print statements as well as output from a subprocess started by
|
||||
a test.
|
||||
|
||||
デフォルトのキャプチャは、低レベルのファイルディスクリプタへの書き込みを横取りします。単純な print 文からの出力も、あるテストが生成したサブプロセスからの出力も同じようにキャプチャできます。
|
||||
|
||||
..
|
||||
Setting capturing methods or disabling capturing
|
||||
-------------------------------------------------
|
||||
|
||||
メソッドをキャプチャする、または無効にする設定
|
||||
----------------------------------------------
|
||||
|
||||
..
|
||||
There are two ways in which ``py.test`` can perform capturing:
|
||||
|
||||
``py.test`` でキャプチャを実行する方法が2つあります:
|
||||
|
||||
..
|
||||
* file descriptor (FD) level capturing (default): All writes going to the
|
||||
operating system file descriptors 1 and 2 will be captured.
|
||||
|
||||
* ファイルディスクリプタ (FD) レベルのキャプチャ (デフォルト): オペレーティングシステムのファイルディスクリプタ1と2への全ての書き込みをキャプチャする
|
||||
|
||||
..
|
||||
* ``sys`` level capturing: Only writes to Python files ``sys.stdout``
|
||||
and ``sys.stderr`` will be captured. No capturing of writes to
|
||||
filedescriptors is performed.
|
||||
|
||||
* ``sys`` レベルのキャプチャ: Python ファイル ``sys.stdout`` と ``sys.stderr`` への書き込みのみキャプチャする、ファイルディスクリプタへの書き込みはキャプチャしない
|
||||
|
||||
..
|
||||
You can influence output capturing mechanisms from the command line::
|
||||
|
||||
.. _`disable capturing`:
|
||||
|
||||
コマンドラインから出力内容のキャプチャ設定を制御できます::
|
||||
|
||||
py.test -s # 全てのキャプチャを無効にする
|
||||
py.test --capture=sys # sys.stdout/stderr を in-mem ファイルに置き換える
|
||||
py.test --capture=fd # ファイルディスクリプタ1と2を一時ファイルに差し向ける
|
||||
|
||||
.. _printdebugging:
|
||||
|
||||
デバッグに print 文を使う
|
||||
-------------------------
|
||||
|
||||
..
|
||||
Using print statements for debugging
|
||||
---------------------------------------------------
|
||||
|
||||
..
|
||||
One primary benefit of the default capturing of stdout/stderr output
|
||||
is that you can use print statements for debugging::
|
||||
|
||||
デフォルトで stdout/stderr の出力をキャプチャする主な利点の1つとして、デバッグに print 文が使えます::
|
||||
|
||||
# test_module.py の内容
|
||||
def setup_function(function):
|
||||
print ("setting up %s" % function)
|
||||
|
||||
def test_func1():
|
||||
assert True
|
||||
|
||||
def test_func2():
|
||||
assert False
|
||||
|
||||
..
|
||||
and running this module will show you precisely the output
|
||||
of the failing function and hide the other one::
|
||||
|
||||
このモジュールを実行すると、失敗するテスト関数の出力を適切に表示して、成功するもう1つのテストを非表示にします::
|
||||
|
||||
$ py.test
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_module.py .F
|
||||
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_func2 ________________________________
|
||||
|
||||
def test_func2():
|
||||
> assert False
|
||||
E assert False
|
||||
|
||||
test_module.py:9: AssertionError
|
||||
----------------------------- Captured stdout ------------------------------
|
||||
setting up <function test_func2 at 0x20160c8>
|
||||
==================== 1 failed, 1 passed in 0.01 seconds ====================
|
||||
|
||||
..
|
||||
Accessing captured output from a test function
|
||||
---------------------------------------------------
|
||||
|
||||
テスト関数からキャプチャされた出力へのアクセス
|
||||
----------------------------------------------
|
||||
|
||||
..
|
||||
The :ref:`funcarg mechanism` allows test function a very easy
|
||||
way to access the captured output by simply using the names
|
||||
``capsys`` or ``capfd`` in the test function signature. Here
|
||||
is an example test function that performs some output related
|
||||
checks::
|
||||
|
||||
:ref:`funcarg mechanism` により、テスト関数のシグネチャに ``capsys`` または ``capfd`` という名前を使うだけで、簡単にキャプチャされた出力へアクセスできます。次に関連する値の確認を行うテスト関数のサンプルを紹介します::
|
||||
|
||||
def test_myoutput(capsys): # または fd レベルの "capfd" を使う
|
||||
print ("hello")
|
||||
sys.stderr.write("world\n")
|
||||
out, err = capsys.readouterr()
|
||||
assert out == "hello\n"
|
||||
assert err == "world\n"
|
||||
print "next"
|
||||
out, err = capsys.readouterr()
|
||||
assert out == "next\n"
|
||||
|
||||
..
|
||||
The ``readouterr()`` call snapshots the output so far -
|
||||
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
|
||||
own per-test capturing.
|
||||
|
||||
``readouterr()`` 呼び出しは、その時点での出力内容のスナップショットを返し、その後もキャプチャが続行されます。テスト関数が終了した後、元のストリームが復元されます。 ``capsys`` を使うことで、テスト内で出力ストリームをセット/リセットすることに注意を払わなくてよくなります。また、pytest が保持するテスト単位のキャプチャも扱えます。
|
||||
|
||||
..
|
||||
If you want to capture on ``fd`` level you can use
|
||||
the ``capfd`` function argument which offers the exact
|
||||
same interface.
|
||||
|
||||
``fd`` レベルのキャプチャを行う場合も全く同じインターフェースを提供する ``capfd`` という関数の引数を使います。
|
||||
|
||||
.. include:: links.inc
|
||||
@@ -1,11 +0,0 @@
|
||||
|
||||
.. _changelog:
|
||||
|
||||
変更履歴
|
||||
========
|
||||
|
||||
..
|
||||
Changelog history
|
||||
=================================
|
||||
|
||||
.. include:: ../../CHANGELOG
|
||||
@@ -1,17 +0,0 @@
|
||||
import py
|
||||
import subprocess
|
||||
def test_build_docs(tmpdir):
|
||||
doctrees = tmpdir.join("doctrees")
|
||||
htmldir = tmpdir.join("html")
|
||||
subprocess.check_call([
|
||||
"sphinx-build", "-W", "-bhtml",
|
||||
"-d", str(doctrees), ".", str(htmldir)])
|
||||
|
||||
def test_linkcheck(tmpdir):
|
||||
doctrees = tmpdir.join("doctrees")
|
||||
htmldir = tmpdir.join("html")
|
||||
subprocess.check_call(
|
||||
["sphinx-build", "-blinkcheck",
|
||||
"-d", str(doctrees), ".", str(htmldir)])
|
||||
|
||||
|
||||
284
doc/ja/conf.py
284
doc/ja/conf.py
@@ -1,284 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# pytest documentation build configuration file, created by
|
||||
# sphinx-quickstart on Fri Oct 8 17:54:28 2010.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.autosummary',
|
||||
'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.txt'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'contents'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pytest'
|
||||
copyright = u'2011, holger krekel et alii'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
# The short X.Y version.
|
||||
version = release = "2.2.4.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
language = "ja"
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['links.inc', '_build', 'naming20.txt', 'test/*',
|
||||
'example/attic.txt',
|
||||
]
|
||||
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'sphinxdoc'
|
||||
|
||||
# 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 = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
html_short_title = "pytest-%s" % release
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
#html_sidebars = {'index': 'indexsidebar.html'}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
#html_additional_pages = {'index': 'index.html'}
|
||||
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
html_use_index = False
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
html_show_sourcelink = False
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pytestdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
# The paper size ('letter' or 'a4').
|
||||
#latex_paper_size = 'letter'
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#latex_font_size = '10pt'
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('contents', 'pytest.tex', u'pytest Documentation',
|
||||
u'holger krekel et alii', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#latex_preamble = ''
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
latex_domain_indices = False
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('usage', 'pytest', u'pytest usage',
|
||||
[u'holger krekel at merlinux eu'], 1)
|
||||
]
|
||||
|
||||
|
||||
# -- Options for Epub output ---------------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'pytest'
|
||||
epub_author = u'holger krekel at merlinux eu'
|
||||
epub_publisher = u'holger krekel at merlinux eu'
|
||||
epub_copyright = u'2011, holger krekel et alii'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
#epub_exclude_files = []
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
|
||||
# -- Options for texinfo output ------------------------------------------------
|
||||
|
||||
texinfo_documents = [
|
||||
(master_doc, 'pytest', 'pytest Documentation',
|
||||
('Holger Krekel@*Benjamin Peterson@*Ronny Pfannschmidt@*'
|
||||
'Floris Bruynooghe@*others'),
|
||||
'pytest',
|
||||
'simple powerful testing with Pytho',
|
||||
'Programming',
|
||||
1),
|
||||
]
|
||||
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {} # 'http://docs.python.org/': None}
|
||||
def setup(app):
|
||||
#from sphinx.ext.autodoc import cut_lines
|
||||
#app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||
app.add_description_unit('confval', 'confval',
|
||||
objname='configuration value',
|
||||
indextemplate='pair: %s; configuration value')
|
||||
@@ -1 +0,0 @@
|
||||
collect_ignore = ["conf.py"]
|
||||
@@ -1,73 +0,0 @@
|
||||
|
||||
.. _`contact channels`:
|
||||
.. _`contact`:
|
||||
|
||||
連絡先
|
||||
======
|
||||
|
||||
..
|
||||
Contact channels
|
||||
===================================
|
||||
|
||||
..
|
||||
- `new issue tracker`_ to report bugs or suggest features (for version
|
||||
2.0 and above). You may also peek at the `old issue tracker`_ but please
|
||||
don't submit bugs there anymore.
|
||||
|
||||
- バグ報告や機能提案は `新イシュートラッカー`_ を使ってください (バージョン 2.0 以上) 。 `旧イシュートラッカー`_ を覗くこともあるかもしれませんが、そこには登録しないようにしてください。
|
||||
|
||||
..
|
||||
- `Testing In Python`_: a mailing list for Python testing tools and discussion.
|
||||
|
||||
- `Python におけるテスト`_ は Python のテストツールとその議論のためのメーリングリストです。
|
||||
|
||||
..
|
||||
- `py-dev developers list`_ pytest specific announcements and discussions.
|
||||
|
||||
- `py-dev 開発者のメーリングリスト`_ は pytest に特化したアナウンスと議論のメーリングリストです。
|
||||
|
||||
..
|
||||
- #pylib on irc.freenode.net IRC channel for random questions.
|
||||
|
||||
- あれこれ聞くための irc.freenode.net IRC チャネルは #pylib です。
|
||||
|
||||
..
|
||||
- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
|
||||
|
||||
- 慎重な対応を求める問題があるなら Holger.Krekel at gmail com 宛へメールしてください。
|
||||
|
||||
..
|
||||
- `commit mailing list`_
|
||||
|
||||
- `コミットメーリングリスト`_ です。
|
||||
|
||||
..
|
||||
- `merlinux.eu`_ offers on-site teaching and consulting services.
|
||||
|
||||
- `merlinux.eu`_ はオンサイト教育とコンサルティングサービスを提供しています。
|
||||
|
||||
.. _`new issue tracker`: http://bitbucket.org/hpk42/pytest/issues/
|
||||
.. _`新イシュートラッカー`: http://bitbucket.org/hpk42/pytest/issues/
|
||||
.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||
.. _`旧イシュートラッカー`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||
|
||||
.. _`merlinux.eu`: http://merlinux.eu
|
||||
|
||||
.. _`get an account`:
|
||||
|
||||
.. _tetamap: http://tetamap.wordpress.com
|
||||
|
||||
.. _`@pylibcommit`: http://twitter.com/pylibcommit
|
||||
|
||||
|
||||
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
|
||||
.. _`Python におけるテスト`: http://lists.idyll.org/listinfo/testing-in-python
|
||||
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
||||
.. _`py-dev`:
|
||||
.. _`development mailing list`:
|
||||
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`py-dev 開発者のメーリングリスト`: http://codespeak.net/mailman/listinfo/py-dev
|
||||
.. _`py-svn`:
|
||||
.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
|
||||
.. _`コミットメーリングリスト`: http://codespeak.net/mailman/listinfo/py-svn
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
.. _toc:
|
||||
|
||||
pytest ドキュメント
|
||||
===================
|
||||
|
||||
..
|
||||
Full pytest documentation
|
||||
===========================
|
||||
|
||||
..
|
||||
`Download latest version as PDF <pytest.pdf>`_
|
||||
|
||||
`PDF で最新バージョンをダウンロードする <pytest.pdf>`_
|
||||
|
||||
.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||
.. `PDF で最新バージョンをダウンロードする <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
example/index
|
||||
apiref
|
||||
plugins
|
||||
talks
|
||||
develop
|
||||
announce/index
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
||||
changelog.txt
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user