Merge from upstream
This commit is contained in:
commit
dd97a2e7c8
|
@ -4,5 +4,5 @@ Here's a quick checklist in what to include:
|
||||||
|
|
||||||
- [ ] Include a detailed description of the bug or suggestion
|
- [ ] Include a detailed description of the bug or suggestion
|
||||||
- [ ] `pip list` of the virtual environment you are using
|
- [ ] `pip list` of the virtual environment you are using
|
||||||
- [ ] py.test and operating system versions
|
- [ ] pytest and operating system versions
|
||||||
- [ ] Minimal example if possible
|
- [ ] Minimal example if possible
|
||||||
|
|
28
AUTHORS
28
AUTHORS
|
@ -5,6 +5,7 @@ Contributors include::
|
||||||
|
|
||||||
Abdeali JK
|
Abdeali JK
|
||||||
Abhijeet Kasurde
|
Abhijeet Kasurde
|
||||||
|
Alexei Kozlenok
|
||||||
Anatoly Bubenkoff
|
Anatoly Bubenkoff
|
||||||
Andreas Zeidler
|
Andreas Zeidler
|
||||||
Andy Freeland
|
Andy Freeland
|
||||||
|
@ -12,14 +13,17 @@ Anthon van der Neut
|
||||||
Armin Rigo
|
Armin Rigo
|
||||||
Aron Curzon
|
Aron Curzon
|
||||||
Aviv Palivoda
|
Aviv Palivoda
|
||||||
|
Ben Webb
|
||||||
Benjamin Peterson
|
Benjamin Peterson
|
||||||
Bob Ippolito
|
Bob Ippolito
|
||||||
Brian Dorsey
|
Brian Dorsey
|
||||||
Brian Okken
|
Brian Okken
|
||||||
Brianna Laugher
|
Brianna Laugher
|
||||||
Bruno Oliveira
|
Bruno Oliveira
|
||||||
|
Cal Leeming
|
||||||
Carl Friedrich Bolz
|
Carl Friedrich Bolz
|
||||||
Charles Cloud
|
Charles Cloud
|
||||||
|
Charnjit SiNGH (CCSJ)
|
||||||
Chris Lamb
|
Chris Lamb
|
||||||
Christian Theunert
|
Christian Theunert
|
||||||
Christian Tismer
|
Christian Tismer
|
||||||
|
@ -29,20 +33,24 @@ Daniel Hahler
|
||||||
Daniel Nuri
|
Daniel Nuri
|
||||||
Danielle Jenkins
|
Danielle Jenkins
|
||||||
Dave Hunt
|
Dave Hunt
|
||||||
|
David Díaz-Barquero
|
||||||
David Mohr
|
David Mohr
|
||||||
David Vierra
|
David Vierra
|
||||||
Edison Gustavo Muenz
|
Edison Gustavo Muenz
|
||||||
Eduardo Schettino
|
Eduardo Schettino
|
||||||
Endre Galaczi
|
|
||||||
Elizaveta Shashkova
|
Elizaveta Shashkova
|
||||||
|
Endre Galaczi
|
||||||
|
Eric Hunsberger
|
||||||
Eric Hunsberger
|
Eric Hunsberger
|
||||||
Eric Siegerman
|
Eric Siegerman
|
||||||
Erik M. Bray
|
Erik M. Bray
|
||||||
|
Feng Ma
|
||||||
Florian Bruhin
|
Florian Bruhin
|
||||||
Floris Bruynooghe
|
Floris Bruynooghe
|
||||||
Gabriel Reis
|
Gabriel Reis
|
||||||
Georgy Dyuldin
|
Georgy Dyuldin
|
||||||
Graham Horler
|
Graham Horler
|
||||||
|
Greg Price
|
||||||
Grig Gheorghiu
|
Grig Gheorghiu
|
||||||
Guido Wesdorp
|
Guido Wesdorp
|
||||||
Harald Armin Massa
|
Harald Armin Massa
|
||||||
|
@ -66,6 +74,7 @@ Mark Abramowitz
|
||||||
Markus Unterwaditzer
|
Markus Unterwaditzer
|
||||||
Martijn Faassen
|
Martijn Faassen
|
||||||
Martin Prusse
|
Martin Prusse
|
||||||
|
Martin K. Scherer
|
||||||
Matt Bachmann
|
Matt Bachmann
|
||||||
Matt Williams
|
Matt Williams
|
||||||
Michael Aquilina
|
Michael Aquilina
|
||||||
|
@ -73,6 +82,8 @@ Michael Birtwell
|
||||||
Michael Droettboom
|
Michael Droettboom
|
||||||
Mike Lundy
|
Mike Lundy
|
||||||
Nicolas Delaby
|
Nicolas Delaby
|
||||||
|
Oleg Pidsadnyi
|
||||||
|
Oliver Bestwalter
|
||||||
Omar Kohl
|
Omar Kohl
|
||||||
Pieter Mulder
|
Pieter Mulder
|
||||||
Piotr Banaszkiewicz
|
Piotr Banaszkiewicz
|
||||||
|
@ -83,19 +94,18 @@ Raphael Pierzina
|
||||||
Roman Bolshakov
|
Roman Bolshakov
|
||||||
Ronny Pfannschmidt
|
Ronny Pfannschmidt
|
||||||
Ross Lawley
|
Ross Lawley
|
||||||
|
Russel Winder
|
||||||
Ryan Wooden
|
Ryan Wooden
|
||||||
Samuele Pedroni
|
Samuele Pedroni
|
||||||
Steffen Allner
|
Steffen Allner
|
||||||
|
Stephan Obermann
|
||||||
Tareq Alayan
|
Tareq Alayan
|
||||||
|
Simon Gomizelj
|
||||||
|
Stefano Taschini
|
||||||
|
Stefan Farmbauer
|
||||||
|
Thomas Grainger
|
||||||
Tom Viner
|
Tom Viner
|
||||||
Trevor Bekolay
|
Trevor Bekolay
|
||||||
Vasily Kuznetsov
|
Vasily Kuznetsov
|
||||||
Wouter van Ackooy
|
Wouter van Ackooy
|
||||||
David Díaz-Barquero
|
Bernard Pratz
|
||||||
Eric Hunsberger
|
|
||||||
Simon Gomizelj
|
|
||||||
Russel Winder
|
|
||||||
Ben Webb
|
|
||||||
Alexei Kozlenok
|
|
||||||
Cal Leeming
|
|
||||||
Feng Ma
|
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
Can also show where fixtures are defined if combined with ``-v``.
|
Can also show where fixtures are defined if combined with ``-v``.
|
||||||
Thanks `@hackebrot`_ for the PR.
|
Thanks `@hackebrot`_ for the PR.
|
||||||
|
|
||||||
|
* Introduce pytest command as recommended entry point. Closes proposal
|
||||||
|
`#1629`_. Thanks `@obestwalter`_ and `@davehunt`_ for the complete PR
|
||||||
|
(`#1633`_)
|
||||||
|
|
||||||
* New cli flags:
|
* New cli flags:
|
||||||
``--setup-plan`` performs normal collection and reports the potential setup
|
``--setup-plan`` performs normal collection and reports the potential setup
|
||||||
and teardown, does not execute any fixtures and tests
|
and teardown, does not execute any fixtures and tests
|
||||||
|
@ -81,8 +85,58 @@
|
||||||
message to raise when no exception occurred.
|
message to raise when no exception occurred.
|
||||||
Thanks `@palaviv`_ for the complete PR (`#1616`_).
|
Thanks `@palaviv`_ for the complete PR (`#1616`_).
|
||||||
|
|
||||||
|
* ``conftest.py`` files now benefit from assertion rewriting; previously it
|
||||||
|
was only available for test modules. Thanks `@flub`_, `@sober7`_ and
|
||||||
|
`@nicoddemus`_ for the PR (`#1619`_).
|
||||||
|
|
||||||
|
* Text documents without any doctests no longer appear as "skipped".
|
||||||
|
Thanks `@graingert`_ for reporting and providing a full PR (`#1580`_).
|
||||||
|
|
||||||
|
* Fix internal error issue when ``method`` argument is missing for
|
||||||
|
``teardown_method()``. Fixes (`#1605`_).
|
||||||
|
|
||||||
|
* Fix exception visualization in case the current working directory (CWD) gets
|
||||||
|
deleted during testing. Fixes (`#1235`). Thanks `@bukzor`_ for reporting. PR by
|
||||||
|
`@marscher`. Thanks `@nicoddemus`_ for his help.
|
||||||
|
|
||||||
|
* Ensure that a module within a namespace package can be found when it
|
||||||
|
is specified on the command line together with the ``--pyargs``
|
||||||
|
option. Thanks to `@taschini`_ for the PR (`#1597`_).
|
||||||
|
|
||||||
|
* Raise helpful failure message, when requesting parametrized fixture at runtime,
|
||||||
|
e.g. with ``request.getfuncargvalue``. BACKWARD INCOMPAT: Previously these params
|
||||||
|
were simply never defined. So a fixture decorated like ``@pytest.fixture(params=[0, 1, 2])``
|
||||||
|
only ran once. Now a failure is raised. Fixes (`#460`_). Thanks to
|
||||||
|
`@nikratio`_ for bug report, `@RedBeardCode`_ and `@tomviner`_ for PR.
|
||||||
|
|
||||||
|
* Create correct diff for strings ending with newlines. Fixes (`#1553`_).
|
||||||
|
Thanks `@Vogtinator`_ for reporting. Thanks to `@RedBeardCode`_ and
|
||||||
|
`@tomviner`_ for PR.
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
|
.. _#1580: https://github.com/pytest-dev/pytest/pull/1580
|
||||||
|
.. _#1605: https://github.com/pytest-dev/pytest/issues/1605
|
||||||
|
.. _#1597: https://github.com/pytest-dev/pytest/pull/1597
|
||||||
|
.. _#460: https://github.com/pytest-dev/pytest/pull/460
|
||||||
|
.. _#1553: https://github.com/pytest-dev/pytest/issues/1553
|
||||||
|
|
||||||
|
.. _@graingert: https://github.com/graingert
|
||||||
|
.. _@taschini: https://github.com/taschini
|
||||||
|
.. _@nikratio: https://github.com/nikratio
|
||||||
|
.. _@RedBeardCode: https://github.com/RedBeardCode
|
||||||
|
.. _@Vogtinator: https://github.com/Vogtinator
|
||||||
|
|
||||||
|
* Fix `#1421`_: Exit tests if a collection error occurs and add
|
||||||
|
``--continue-on-collection-errors`` option to restore previous behaviour.
|
||||||
|
Thanks `@olegpidsadnyi`_ and `@omarkohl`_ for the complete PR (`#1628`_).
|
||||||
|
|
||||||
|
|
||||||
|
*
|
||||||
|
|
||||||
.. _@milliams: https://github.com/milliams
|
.. _@milliams: https://github.com/milliams
|
||||||
.. _@csaftoiu: https://github.com/csaftoiu
|
.. _@csaftoiu: https://github.com/csaftoiu
|
||||||
|
.. _@flub: https://github.com/flub
|
||||||
.. _@novas0x2a: https://github.com/novas0x2a
|
.. _@novas0x2a: https://github.com/novas0x2a
|
||||||
.. _@kalekundert: https://github.com/kalekundert
|
.. _@kalekundert: https://github.com/kalekundert
|
||||||
.. _@tareqalayan: https://github.com/tareqalayan
|
.. _@tareqalayan: https://github.com/tareqalayan
|
||||||
|
@ -90,7 +144,12 @@
|
||||||
.. _@palaviv: https://github.com/palaviv
|
.. _@palaviv: https://github.com/palaviv
|
||||||
.. _@omarkohl: https://github.com/omarkohl
|
.. _@omarkohl: https://github.com/omarkohl
|
||||||
.. _@mikofski: https://github.com/mikofski
|
.. _@mikofski: https://github.com/mikofski
|
||||||
|
.. _@sober7: https://github.com/sober7
|
||||||
|
.. _@olegpidsadnyi: https://github.com/olegpidsadnyi
|
||||||
|
.. _@obestwalter: https://github.com/obestwalter
|
||||||
|
.. _@davehunt: https://github.com/davehunt
|
||||||
|
|
||||||
|
.. _#1421: https://github.com/pytest-dev/pytest/issues/1421
|
||||||
.. _#1426: https://github.com/pytest-dev/pytest/issues/1426
|
.. _#1426: https://github.com/pytest-dev/pytest/issues/1426
|
||||||
.. _#1428: https://github.com/pytest-dev/pytest/pull/1428
|
.. _#1428: https://github.com/pytest-dev/pytest/pull/1428
|
||||||
.. _#1444: https://github.com/pytest-dev/pytest/pull/1444
|
.. _#1444: https://github.com/pytest-dev/pytest/pull/1444
|
||||||
|
@ -102,9 +161,13 @@
|
||||||
.. _#1474: https://github.com/pytest-dev/pytest/pull/1474
|
.. _#1474: https://github.com/pytest-dev/pytest/pull/1474
|
||||||
.. _#1502: https://github.com/pytest-dev/pytest/pull/1502
|
.. _#1502: https://github.com/pytest-dev/pytest/pull/1502
|
||||||
.. _#1520: https://github.com/pytest-dev/pytest/pull/1520
|
.. _#1520: https://github.com/pytest-dev/pytest/pull/1520
|
||||||
|
.. _#1619: https://github.com/pytest-dev/pytest/issues/1619
|
||||||
.. _#372: https://github.com/pytest-dev/pytest/issues/372
|
.. _#372: https://github.com/pytest-dev/pytest/issues/372
|
||||||
.. _#1544: https://github.com/pytest-dev/pytest/issues/1544
|
.. _#1544: https://github.com/pytest-dev/pytest/issues/1544
|
||||||
.. _#1616: https://github.com/pytest-dev/pytest/pull/1616
|
.. _#1616: https://github.com/pytest-dev/pytest/pull/1616
|
||||||
|
.. _#1628: https://github.com/pytest-dev/pytest/pull/1628
|
||||||
|
.. _#1629: https://github.com/pytest-dev/pytest/issues/1629
|
||||||
|
.. _#1633: https://github.com/pytest-dev/pytest/pull/1633
|
||||||
|
|
||||||
|
|
||||||
**Bug Fixes**
|
**Bug Fixes**
|
||||||
|
@ -271,7 +334,7 @@
|
||||||
Thanks `@biern`_ for the PR.
|
Thanks `@biern`_ for the PR.
|
||||||
|
|
||||||
* Fix `traceback style docs`_ to describe all of the available options
|
* Fix `traceback style docs`_ to describe all of the available options
|
||||||
(auto/long/short/line/native/no), with `auto` being the default since v2.6.
|
(auto/long/short/line/native/no), with ``auto`` being the default since v2.6.
|
||||||
Thanks `@hackebrot`_ for the PR.
|
Thanks `@hackebrot`_ for the PR.
|
||||||
|
|
||||||
* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
|
* Fix (`#1422`_): junit record_xml_property doesn't allow multiple records
|
||||||
|
|
|
@ -48,7 +48,7 @@ to fix the bug yet.
|
||||||
Fix bugs
|
Fix bugs
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Look through the GitHub issues for bugs. Here is sample filter you can use:
|
Look through the GitHub issues for bugs. Here is a filter you can use:
|
||||||
https://github.com/pytest-dev/pytest/labels/bug
|
https://github.com/pytest-dev/pytest/labels/bug
|
||||||
|
|
||||||
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
|
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
|
||||||
|
@ -60,8 +60,7 @@ Don't forget to check the issue trackers of your favourite plugins, too!
|
||||||
Implement features
|
Implement features
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
Look through the GitHub issues for enhancements. Here is sample filter you
|
Look through the GitHub issues for enhancements. Here is a filter you can use:
|
||||||
can use:
|
|
||||||
https://github.com/pytest-dev/pytest/labels/enhancement
|
https://github.com/pytest-dev/pytest/labels/enhancement
|
||||||
|
|
||||||
:ref:`Talk <contact>` to developers to find out how you can implement specific
|
:ref:`Talk <contact>` to developers to find out how you can implement specific
|
||||||
|
@ -70,16 +69,15 @@ features.
|
||||||
Write documentation
|
Write documentation
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
pytest could always use more documentation. What exactly is needed?
|
Pytest could always use more documentation. What exactly is needed?
|
||||||
|
|
||||||
* More complementary documentation. Have you perhaps found something unclear?
|
* More complementary documentation. Have you perhaps found something unclear?
|
||||||
* Documentation translations. We currently have only English.
|
* Documentation translations. We currently have only English.
|
||||||
* Docstrings. There can never be too many of them.
|
* Docstrings. There can never be too many of them.
|
||||||
* Blog posts, articles and such -- they're all very appreciated.
|
* Blog posts, articles and such -- they're all very appreciated.
|
||||||
|
|
||||||
You can also edit documentation files directly in the Github web interface
|
You can also edit documentation files directly in the GitHub web interface,
|
||||||
without needing to make a fork and local copy. This can be convenient for
|
without using a local copy. This can be convenient for small fixes.
|
||||||
small fixes.
|
|
||||||
|
|
||||||
|
|
||||||
.. _submitplugin:
|
.. _submitplugin:
|
||||||
|
@ -95,13 +93,14 @@ in repositories living under the ``pytest-dev`` organisations:
|
||||||
- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
|
- `pytest-dev on Bitbucket <https://bitbucket.org/pytest-dev>`_
|
||||||
|
|
||||||
All pytest-dev Contributors team members have write access to all contained
|
All pytest-dev Contributors team members have write access to all contained
|
||||||
repositories. pytest core and plugins are generally developed
|
repositories. Pytest core and plugins are generally developed
|
||||||
using `pull requests`_ to respective repositories.
|
using `pull requests`_ to respective repositories.
|
||||||
|
|
||||||
The objectives of the ``pytest-dev`` organisation are:
|
The objectives of the ``pytest-dev`` organisation are:
|
||||||
|
|
||||||
* Having a central location for popular pytest plugins
|
* Having a central location for popular pytest plugins
|
||||||
* Sharing some of the maintenance responsibility (in case a maintainer no longer whishes to maintain a plugin)
|
* Sharing some of the maintenance responsibility (in case a maintainer no
|
||||||
|
longer wishes to maintain a plugin)
|
||||||
|
|
||||||
You can submit your plugin by subscribing to the `pytest-dev mail list
|
You can submit your plugin by subscribing to the `pytest-dev mail list
|
||||||
<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
|
<https://mail.python.org/mailman/listinfo/pytest-dev>`_ and writing a
|
||||||
|
@ -127,27 +126,18 @@ transferred to the ``pytest-dev`` organisation.
|
||||||
Here's a rundown of how a repository transfer usually proceeds
|
Here's a rundown of how a repository transfer usually proceeds
|
||||||
(using a repository named ``joedoe/pytest-xyz`` as example):
|
(using a repository named ``joedoe/pytest-xyz`` as example):
|
||||||
|
|
||||||
* One of the ``pytest-dev`` administrators creates:
|
* ``joedoe`` transfers repository ownership to ``pytest-dev`` administrator ``calvin``.
|
||||||
|
* ``calvin`` creates ``pytest-xyz-admin`` and ``pytest-xyz-developers`` teams, inviting ``joedoe`` to both as **maintainer**.
|
||||||
|
* ``calvin`` transfers repository to ``pytest-dev`` and configures team access:
|
||||||
|
|
||||||
- ``pytest-xyz-admin`` team, with full administration rights to
|
- ``pytest-xyz-admin`` **admin** access;
|
||||||
``pytest-dev/pytest-xyz``.
|
- ``pytest-xyz-developers`` **write** access;
|
||||||
- ``pytest-xyz-developers`` team, with write access to
|
|
||||||
``pytest-dev/pytest-xyz``.
|
|
||||||
|
|
||||||
* ``joedoe`` is invited to the ``pytest-xyz-admin`` team;
|
|
||||||
|
|
||||||
* After accepting the invitation, ``joedoe`` transfers the repository from its
|
|
||||||
original location to ``pytest-dev/pytest-xyz`` (A nice feature is that GitHub handles URL redirection from
|
|
||||||
the old to the new location automatically).
|
|
||||||
|
|
||||||
* ``joedoe`` is free to add any other collaborators to the
|
|
||||||
``pytest-xyz-admin`` or ``pytest-xyz-developers`` team as desired.
|
|
||||||
|
|
||||||
The ``pytest-dev/Contributors`` team has write access to all projects, and
|
The ``pytest-dev/Contributors`` team has write access to all projects, and
|
||||||
every project administrator is in it. We recommend that each plugin has at least three
|
every project administrator is in it. We recommend that each plugin has at least three
|
||||||
people who have the right to release to PyPI.
|
people who have the right to release to PyPI.
|
||||||
|
|
||||||
Repository owners can be assured that no ``pytest-dev`` administrator will ever make
|
Repository owners can rest assured that no ``pytest-dev`` administrator will ever make
|
||||||
releases of your repository or take ownership in any way, except in rare cases
|
releases of your repository or take ownership in any way, except in rare cases
|
||||||
where someone becomes unresponsive after months of contact attempts.
|
where someone becomes unresponsive after months of contact attempts.
|
||||||
As stated, the objective is to share maintenance and avoid "plugin-abandon".
|
As stated, the objective is to share maintenance and avoid "plugin-abandon".
|
||||||
|
@ -159,15 +149,11 @@ As stated, the objective is to share maintenance and avoid "plugin-abandon".
|
||||||
Preparing Pull Requests on GitHub
|
Preparing Pull Requests on GitHub
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
There's an excellent tutorial on how Pull Requests work in the
|
|
||||||
`GitHub Help Center <https://help.github.com/articles/using-pull-requests/>`_
|
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
What is a "pull request"? It informs project's core developers about the
|
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
|
changes you want to review and merge. Pull requests are stored on
|
||||||
`GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
|
`GitHub servers <https://github.com/pytest-dev/pytest/pulls>`_.
|
||||||
Once you send pull request, we can discuss it's potential modifications and
|
Once you send a pull request, we can discuss its potential modifications and
|
||||||
even add more commits to it later on.
|
even add more commits to it later on.
|
||||||
|
|
||||||
There's an excellent tutorial on how Pull Requests work in the
|
There's an excellent tutorial on how Pull Requests work in the
|
||||||
|
@ -216,19 +202,19 @@ but here is a simple overview:
|
||||||
This command will run tests via the "tox" tool against Python 2.7 and 3.5
|
This command will run tests via the "tox" tool against Python 2.7 and 3.5
|
||||||
and also perform "lint" coding-style checks. ``runtox.py`` is
|
and also perform "lint" coding-style checks. ``runtox.py`` is
|
||||||
a thin wrapper around ``tox`` which installs from a development package
|
a thin wrapper around ``tox`` which installs from a development package
|
||||||
index where newer (not yet released to pypi) versions of dependencies
|
index where newer (not yet released to PyPI) versions of dependencies
|
||||||
(especially ``py``) might be present.
|
(especially ``py``) might be present.
|
||||||
|
|
||||||
#. You can now edit your local working copy.
|
#. You can now edit your local working copy.
|
||||||
|
|
||||||
You can now make the changes you want and run the tests again as necessary.
|
You can now make the changes you want and run the tests again as necessary.
|
||||||
|
|
||||||
To run tests on py27 and pass options to pytest (e.g. enter pdb on failure)
|
To run tests on Python 2.7 and pass options to pytest (e.g. enter pdb on
|
||||||
to pytest you can do::
|
failure) to pytest you can do::
|
||||||
|
|
||||||
$ python3 runtox.py -e py27 -- --pdb
|
$ python3 runtox.py -e py27 -- --pdb
|
||||||
|
|
||||||
or to only run tests in a particular test module on py35::
|
Or to only run tests in a particular test module on Python 3.5::
|
||||||
|
|
||||||
$ python3 runtox.py -e py35 -- testing/test_config.py
|
$ python3 runtox.py -e py35 -- testing/test_config.py
|
||||||
|
|
||||||
|
@ -237,9 +223,9 @@ but here is a simple overview:
|
||||||
$ git commit -a -m "<commit message>"
|
$ git commit -a -m "<commit message>"
|
||||||
$ git push -u
|
$ git push -u
|
||||||
|
|
||||||
Make sure you add a CHANGELOG message, and add yourself to AUTHORS. If you
|
Make sure you add a message to ``CHANGELOG.rst`` and add yourself to
|
||||||
are unsure about either of these steps, submit your pull request and we'll
|
``AUTHORS``. If you are unsure about either of these steps, submit your
|
||||||
help you fix it up.
|
pull request and we'll help you fix it up.
|
||||||
|
|
||||||
#. Finally, submit a pull request through the GitHub website using this data::
|
#. Finally, submit a pull request through the GitHub website using this data::
|
||||||
|
|
||||||
|
@ -248,6 +234,6 @@ but here is a simple overview:
|
||||||
|
|
||||||
base-fork: pytest-dev/pytest
|
base-fork: pytest-dev/pytest
|
||||||
base: master # if it's a bugfix
|
base: master # if it's a bugfix
|
||||||
base: feature # if it's a feature
|
base: features # if it's a feature
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ An example of a simple test:
|
||||||
|
|
||||||
To execute it::
|
To execute it::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.4.3, pytest-2.8.5, py-1.4.31, pluggy-0.3.1
|
||||||
collected 1 items
|
collected 1 items
|
||||||
|
@ -51,7 +51,7 @@ To execute it::
|
||||||
test_sample.py:5: AssertionError
|
test_sample.py:5: AssertionError
|
||||||
======= 1 failed in 0.12 seconds ========
|
======= 1 failed in 0.12 seconds ========
|
||||||
|
|
||||||
Due to ``py.test``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
|
Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://pytest.org/latest/getting-started.html#our-first-test-run>`_ for more examples.
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
__version__ = '2.10.0.dev1'
|
__version__ = '2.10.0.dev1'
|
||||||
|
|
|
@ -3,7 +3,6 @@ from inspect import CO_VARARGS, CO_VARKEYWORDS
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
builtin_repr = repr
|
builtin_repr = repr
|
||||||
|
|
||||||
reprlib = py.builtin._tryimport('repr', 'reprlib')
|
reprlib = py.builtin._tryimport('repr', 'reprlib')
|
||||||
|
@ -36,12 +35,16 @@ class Code(object):
|
||||||
def path(self):
|
def path(self):
|
||||||
""" return a path object pointing to source code (note that it
|
""" return a path object pointing to source code (note that it
|
||||||
might not point to an actually existing file). """
|
might not point to an actually existing file). """
|
||||||
p = py.path.local(self.raw.co_filename)
|
try:
|
||||||
# maybe don't try this checking
|
p = py.path.local(self.raw.co_filename)
|
||||||
if not p.check():
|
# maybe don't try this checking
|
||||||
|
if not p.check():
|
||||||
|
raise OSError("py.path check failed.")
|
||||||
|
except OSError:
|
||||||
# XXX maybe try harder like the weird logic
|
# XXX maybe try harder like the weird logic
|
||||||
# in the standard lib [linecache.updatecache] does?
|
# in the standard lib [linecache.updatecache] does?
|
||||||
p = self.raw.co_filename
|
p = self.raw.co_filename
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -4,6 +4,8 @@ support for presenting detailed information in failing assertions.
|
||||||
import py
|
import py
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from _pytest.config import hookimpl
|
||||||
from _pytest.monkeypatch import monkeypatch
|
from _pytest.monkeypatch import monkeypatch
|
||||||
from _pytest.assertion import util
|
from _pytest.assertion import util
|
||||||
|
|
||||||
|
@ -42,9 +44,13 @@ class AssertionState:
|
||||||
self.trace = config.trace.root.get("assertion")
|
self.trace = config.trace.root.get("assertion")
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
@hookimpl(tryfirst=True)
|
||||||
mode = config.getvalue("assertmode")
|
def pytest_load_initial_conftests(early_config, parser, args):
|
||||||
if config.getvalue("noassert") or config.getvalue("nomagic"):
|
ns, ns_unknown_args = parser.parse_known_and_unknown_args(args)
|
||||||
|
mode = ns.assertmode
|
||||||
|
no_assert = ns.noassert
|
||||||
|
no_magic = ns.nomagic
|
||||||
|
if no_assert or no_magic:
|
||||||
mode = "plain"
|
mode = "plain"
|
||||||
if mode == "rewrite":
|
if mode == "rewrite":
|
||||||
try:
|
try:
|
||||||
|
@ -57,25 +63,29 @@ def pytest_configure(config):
|
||||||
if (sys.platform.startswith('java') or
|
if (sys.platform.startswith('java') or
|
||||||
sys.version_info[:3] == (2, 6, 0)):
|
sys.version_info[:3] == (2, 6, 0)):
|
||||||
mode = "reinterp"
|
mode = "reinterp"
|
||||||
|
|
||||||
|
early_config._assertstate = AssertionState(early_config, mode)
|
||||||
|
warn_about_missing_assertion(mode, early_config.pluginmanager)
|
||||||
|
|
||||||
if mode != "plain":
|
if mode != "plain":
|
||||||
_load_modules(mode)
|
_load_modules(mode)
|
||||||
m = monkeypatch()
|
m = monkeypatch()
|
||||||
config._cleanup.append(m.undo)
|
early_config._cleanup.append(m.undo)
|
||||||
m.setattr(py.builtin.builtins, 'AssertionError',
|
m.setattr(py.builtin.builtins, 'AssertionError',
|
||||||
reinterpret.AssertionError) # noqa
|
reinterpret.AssertionError) # noqa
|
||||||
|
|
||||||
hook = None
|
hook = None
|
||||||
if mode == "rewrite":
|
if mode == "rewrite":
|
||||||
hook = rewrite.AssertionRewritingHook() # noqa
|
hook = rewrite.AssertionRewritingHook(early_config) # noqa
|
||||||
sys.meta_path.insert(0, hook)
|
sys.meta_path.insert(0, hook)
|
||||||
warn_about_missing_assertion(mode)
|
|
||||||
config._assertstate = AssertionState(config, mode)
|
early_config._assertstate.hook = hook
|
||||||
config._assertstate.hook = hook
|
early_config._assertstate.trace("configured with mode set to %r" % (mode,))
|
||||||
config._assertstate.trace("configured with mode set to %r" % (mode,))
|
|
||||||
def undo():
|
def undo():
|
||||||
hook = config._assertstate.hook
|
hook = early_config._assertstate.hook
|
||||||
if hook is not None and hook in sys.meta_path:
|
if hook is not None and hook in sys.meta_path:
|
||||||
sys.meta_path.remove(hook)
|
sys.meta_path.remove(hook)
|
||||||
config.add_cleanup(undo)
|
early_config.add_cleanup(undo)
|
||||||
|
|
||||||
|
|
||||||
def pytest_collection(session):
|
def pytest_collection(session):
|
||||||
|
@ -154,7 +164,7 @@ def _load_modules(mode):
|
||||||
from _pytest.assertion import rewrite # noqa
|
from _pytest.assertion import rewrite # noqa
|
||||||
|
|
||||||
|
|
||||||
def warn_about_missing_assertion(mode):
|
def warn_about_missing_assertion(mode, pluginmanager):
|
||||||
try:
|
try:
|
||||||
assert False
|
assert False
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
|
@ -166,10 +176,18 @@ def warn_about_missing_assertion(mode):
|
||||||
else:
|
else:
|
||||||
specifically = "failing tests may report as passing"
|
specifically = "failing tests may report as passing"
|
||||||
|
|
||||||
sys.stderr.write("WARNING: " + specifically +
|
# temporarily disable capture so we can print our warning
|
||||||
" because assert statements are not executed "
|
capman = pluginmanager.getplugin('capturemanager')
|
||||||
"by the underlying Python interpreter "
|
try:
|
||||||
"(are you using python -O?)\n")
|
out, err = capman.suspendcapture()
|
||||||
|
sys.stderr.write("WARNING: " + specifically +
|
||||||
|
" because assert statements are not executed "
|
||||||
|
"by the underlying Python interpreter "
|
||||||
|
"(are you using python -O?)\n")
|
||||||
|
finally:
|
||||||
|
capman.resumecapture()
|
||||||
|
sys.stdout.write(out)
|
||||||
|
sys.stderr.write(err)
|
||||||
|
|
||||||
|
|
||||||
# Expose this plugin's implementation for the pytest_assertrepr_compare hook
|
# Expose this plugin's implementation for the pytest_assertrepr_compare hook
|
||||||
|
|
|
@ -44,20 +44,18 @@ else:
|
||||||
class AssertionRewritingHook(object):
|
class AssertionRewritingHook(object):
|
||||||
"""PEP302 Import hook which rewrites asserts."""
|
"""PEP302 Import hook which rewrites asserts."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, config):
|
||||||
|
self.config = config
|
||||||
|
self.fnpats = config.getini("python_files")
|
||||||
self.session = None
|
self.session = None
|
||||||
self.modules = {}
|
self.modules = {}
|
||||||
self._register_with_pkg_resources()
|
self._register_with_pkg_resources()
|
||||||
|
|
||||||
def set_session(self, session):
|
def set_session(self, session):
|
||||||
self.fnpats = session.config.getini("python_files")
|
|
||||||
self.session = session
|
self.session = session
|
||||||
|
|
||||||
def find_module(self, name, path=None):
|
def find_module(self, name, path=None):
|
||||||
if self.session is None:
|
state = self.config._assertstate
|
||||||
return None
|
|
||||||
sess = self.session
|
|
||||||
state = sess.config._assertstate
|
|
||||||
state.trace("find_module called for: %s" % name)
|
state.trace("find_module called for: %s" % name)
|
||||||
names = name.rsplit(".", 1)
|
names = name.rsplit(".", 1)
|
||||||
lastname = names[-1]
|
lastname = names[-1]
|
||||||
|
@ -86,24 +84,11 @@ class AssertionRewritingHook(object):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
|
fn = os.path.join(pth, name.rpartition(".")[2] + ".py")
|
||||||
|
|
||||||
fn_pypath = py.path.local(fn)
|
fn_pypath = py.path.local(fn)
|
||||||
# Is this a test file?
|
if not self._should_rewrite(fn_pypath, state):
|
||||||
if not sess.isinitpath(fn):
|
return None
|
||||||
# We have to be very careful here because imports in this code can
|
|
||||||
# trigger a cycle.
|
|
||||||
self.session = None
|
|
||||||
try:
|
|
||||||
for pat in self.fnpats:
|
|
||||||
if fn_pypath.fnmatch(pat):
|
|
||||||
state.trace("matched test file %r" % (fn,))
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
finally:
|
|
||||||
self.session = sess
|
|
||||||
else:
|
|
||||||
state.trace("matched test file (was specified on cmdline): %r" %
|
|
||||||
(fn,))
|
|
||||||
# The requested module looks like a test file, so rewrite it. This is
|
# The requested module looks like a test file, so rewrite it. This is
|
||||||
# the most magical part of the process: load the source, rewrite the
|
# the most magical part of the process: load the source, rewrite the
|
||||||
# asserts, and load the rewritten source. We also cache the rewritten
|
# asserts, and load the rewritten source. We also cache the rewritten
|
||||||
|
@ -151,6 +136,32 @@ class AssertionRewritingHook(object):
|
||||||
self.modules[name] = co, pyc
|
self.modules[name] = co, pyc
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def _should_rewrite(self, fn_pypath, state):
|
||||||
|
# always rewrite conftest files
|
||||||
|
fn = str(fn_pypath)
|
||||||
|
if fn_pypath.basename == 'conftest.py':
|
||||||
|
state.trace("rewriting conftest file: %r" % (fn,))
|
||||||
|
return True
|
||||||
|
elif self.session is not None:
|
||||||
|
if self.session.isinitpath(fn):
|
||||||
|
state.trace("matched test file (was specified on cmdline): %r" %
|
||||||
|
(fn,))
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
# modules not passed explicitly on the command line are only
|
||||||
|
# rewritten if they match the naming convention for test files
|
||||||
|
session = self.session # avoid a cycle here
|
||||||
|
self.session = None
|
||||||
|
try:
|
||||||
|
for pat in self.fnpats:
|
||||||
|
if fn_pypath.fnmatch(pat):
|
||||||
|
state.trace("matched test file %r" % (fn,))
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
self.session = session
|
||||||
|
del session
|
||||||
|
return False
|
||||||
|
|
||||||
def load_module(self, name):
|
def load_module(self, name):
|
||||||
# If there is an existing module object named 'fullname' in
|
# If there is an existing module object named 'fullname' in
|
||||||
# sys.modules, the loader must use that existing module. (Otherwise,
|
# sys.modules, the loader must use that existing module. (Otherwise,
|
||||||
|
|
|
@ -225,9 +225,10 @@ def _diff_text(left, right, verbose=False):
|
||||||
'characters in diff, use -v to show') % i]
|
'characters in diff, use -v to show') % i]
|
||||||
left = left[:-i]
|
left = left[:-i]
|
||||||
right = right[:-i]
|
right = right[:-i]
|
||||||
|
keepends = True
|
||||||
explanation += [line.strip('\n')
|
explanation += [line.strip('\n')
|
||||||
for line in ndiff(left.splitlines(),
|
for line in ndiff(left.splitlines(keepends),
|
||||||
right.splitlines())]
|
right.splitlines(keepends))]
|
||||||
return explanation
|
return explanation
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -463,7 +463,7 @@ def _readline_workaround():
|
||||||
|
|
||||||
Pdb uses readline support where available--when not running from the Python
|
Pdb uses readline support where available--when not running from the Python
|
||||||
prompt, the readline module is not imported until running the pdb REPL. If
|
prompt, the readline module is not imported until running the pdb REPL. If
|
||||||
running py.test with the --pdb option this means the readline module is not
|
running pytest with the --pdb option this means the readline module is not
|
||||||
imported until after I/O capture has been started.
|
imported until after I/O capture has been started.
|
||||||
|
|
||||||
This is a problem for pyreadline, which is often used to implement readline
|
This is a problem for pyreadline, which is often used to implement readline
|
||||||
|
|
|
@ -146,23 +146,19 @@ def get_optionflags(parent):
|
||||||
return flag_acc
|
return flag_acc
|
||||||
|
|
||||||
|
|
||||||
class DoctestTextfile(DoctestItem, pytest.Module):
|
class DoctestTextfile(pytest.Module):
|
||||||
|
obj = None
|
||||||
|
|
||||||
def runtest(self):
|
def collect(self):
|
||||||
import doctest
|
import doctest
|
||||||
fixture_request = _setup_fixtures(self)
|
|
||||||
|
|
||||||
# inspired by doctest.testfile; ideally we would use it directly,
|
# inspired by doctest.testfile; ideally we would use it directly,
|
||||||
# but it doesn't support passing a custom checker
|
# but it doesn't support passing a custom checker
|
||||||
text = self.fspath.read()
|
text = self.fspath.read()
|
||||||
filename = str(self.fspath)
|
filename = str(self.fspath)
|
||||||
name = self.fspath.basename
|
name = self.fspath.basename
|
||||||
globs = dict(getfixture=fixture_request.getfuncargvalue)
|
globs = {'__name__': '__main__'}
|
||||||
if '__name__' not in globs:
|
|
||||||
globs['__name__'] = '__main__'
|
|
||||||
|
|
||||||
for name, value in fixture_request.getfuncargvalue('doctest_namespace').items():
|
|
||||||
globs[name] = value
|
|
||||||
|
|
||||||
optionflags = get_optionflags(self)
|
optionflags = get_optionflags(self)
|
||||||
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
|
runner = doctest.DebugRunner(verbose=0, optionflags=optionflags,
|
||||||
|
@ -170,8 +166,8 @@ class DoctestTextfile(DoctestItem, pytest.Module):
|
||||||
|
|
||||||
parser = doctest.DocTestParser()
|
parser = doctest.DocTestParser()
|
||||||
test = parser.get_doctest(text, globs, name, filename, 0)
|
test = parser.get_doctest(text, globs, name, filename, 0)
|
||||||
_check_all_skipped(test)
|
if test.examples:
|
||||||
runner.run(test)
|
yield DoctestItem(test.name, self, runner, test)
|
||||||
|
|
||||||
|
|
||||||
def _check_all_skipped(test):
|
def _check_all_skipped(test):
|
||||||
|
|
|
@ -99,7 +99,7 @@ def pytest_namespace():
|
||||||
|
|
||||||
def freeze_includes():
|
def freeze_includes():
|
||||||
"""
|
"""
|
||||||
Returns a list of module names used by py.test that should be
|
Returns a list of module names used by pytest that should be
|
||||||
included by cx_freeze.
|
included by cx_freeze.
|
||||||
"""
|
"""
|
||||||
result = list(_iter_all_modules(py))
|
result = list(_iter_all_modules(py))
|
||||||
|
|
|
@ -92,8 +92,8 @@ def showhelp(config):
|
||||||
tw.line()
|
tw.line()
|
||||||
tw.line()
|
tw.line()
|
||||||
|
|
||||||
tw.line("to see available markers type: py.test --markers")
|
tw.line("to see available markers type: pytest --markers")
|
||||||
tw.line("to see available fixtures type: py.test --fixtures")
|
tw.line("to see available fixtures type: pytest --fixtures")
|
||||||
tw.line("(shown according to specified file_or_dir or current dir "
|
tw.line("(shown according to specified file_or_dir or current dir "
|
||||||
"if not specified)")
|
"if not specified)")
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ def pytest_addoption(parser):
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
This function should be implemented only in plugins or ``conftest.py``
|
This function should be implemented only in plugins or ``conftest.py``
|
||||||
files situated at the tests root directory due to how py.test
|
files situated at the tests root directory due to how pytest
|
||||||
:ref:`discovers plugins during startup <pluginorder>`.
|
:ref:`discovers plugins during startup <pluginorder>`.
|
||||||
|
|
||||||
:arg parser: To add command line options, call
|
:arg parser: To add command line options, call
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
""" core implementation of testing process: init, session, runtest loop. """
|
""" core implementation of testing process: init, session, runtest loop. """
|
||||||
import imp
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
@ -25,8 +23,6 @@ EXIT_INTERNALERROR = 3
|
||||||
EXIT_USAGEERROR = 4
|
EXIT_USAGEERROR = 4
|
||||||
EXIT_NOTESTSCOLLECTED = 5
|
EXIT_NOTESTSCOLLECTED = 5
|
||||||
|
|
||||||
name_re = re.compile("^[a-zA-Z_]\w*$")
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addini("norecursedirs", "directory patterns to avoid for recursion",
|
parser.addini("norecursedirs", "directory patterns to avoid for recursion",
|
||||||
type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg'])
|
type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg'])
|
||||||
|
@ -53,6 +49,9 @@ def pytest_addoption(parser):
|
||||||
group.addoption('--setupplan', '--setup-plan', action="store_true",
|
group.addoption('--setupplan', '--setup-plan', action="store_true",
|
||||||
help="show what fixtures and tests would be executed but don't"
|
help="show what fixtures and tests would be executed but don't"
|
||||||
" execute anything.")
|
" execute anything.")
|
||||||
|
group._addoption("--continue-on-collection-errors", action="store_true",
|
||||||
|
default=False, dest="continue_on_collection_errors",
|
||||||
|
help="Force test execution even if collection errors occur.")
|
||||||
|
|
||||||
group = parser.getgroup("collect", "collection")
|
group = parser.getgroup("collect", "collection")
|
||||||
group.addoption('--collectonly', '--collect-only', action="store_true",
|
group.addoption('--collectonly', '--collect-only', action="store_true",
|
||||||
|
@ -138,20 +137,16 @@ def pytest_collection(session):
|
||||||
return session.perform_collect()
|
return session.perform_collect()
|
||||||
|
|
||||||
def pytest_runtestloop(session):
|
def pytest_runtestloop(session):
|
||||||
|
if (session.testsfailed and
|
||||||
|
not session.config.option.continue_on_collection_errors):
|
||||||
|
raise session.Interrupted(
|
||||||
|
"%d errors during collection" % session.testsfailed)
|
||||||
|
|
||||||
if session.config.option.collectonly:
|
if session.config.option.collectonly:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def getnextitem(i):
|
|
||||||
# this is a function to avoid python2
|
|
||||||
# keeping sys.exc_info set when calling into a test
|
|
||||||
# python2 keeps sys.exc_info till the frame is left
|
|
||||||
try:
|
|
||||||
return session.items[i+1]
|
|
||||||
except IndexError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
for i, item in enumerate(session.items):
|
for i, item in enumerate(session.items):
|
||||||
nextitem = getnextitem(i)
|
nextitem = session.items[i+1] if i+1 < len(session.items) else None
|
||||||
item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
|
item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
|
||||||
if session.shouldstop:
|
if session.shouldstop:
|
||||||
raise session.Interrupted(session.shouldstop)
|
raise session.Interrupted(session.shouldstop)
|
||||||
|
@ -397,7 +392,10 @@ class Node(object):
|
||||||
if self.config.option.fulltrace:
|
if self.config.option.fulltrace:
|
||||||
style="long"
|
style="long"
|
||||||
else:
|
else:
|
||||||
|
tb = _pytest._code.Traceback([excinfo.traceback[-1]])
|
||||||
self._prunetraceback(excinfo)
|
self._prunetraceback(excinfo)
|
||||||
|
if len(excinfo.traceback) == 0:
|
||||||
|
excinfo.traceback = tb
|
||||||
tbfilter = False # prunetraceback already does it
|
tbfilter = False # prunetraceback already does it
|
||||||
if style == "auto":
|
if style == "auto":
|
||||||
style = "long"
|
style = "long"
|
||||||
|
@ -408,7 +406,13 @@ class Node(object):
|
||||||
else:
|
else:
|
||||||
style = "long"
|
style = "long"
|
||||||
|
|
||||||
return excinfo.getrepr(funcargs=True,
|
try:
|
||||||
|
os.getcwd()
|
||||||
|
abspath = False
|
||||||
|
except OSError:
|
||||||
|
abspath = True
|
||||||
|
|
||||||
|
return excinfo.getrepr(funcargs=True, abspath=abspath,
|
||||||
showlocals=self.config.option.showlocals,
|
showlocals=self.config.option.showlocals,
|
||||||
style=style, tbfilter=tbfilter)
|
style=style, tbfilter=tbfilter)
|
||||||
|
|
||||||
|
@ -654,36 +658,32 @@ class Session(FSCollector):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _tryconvertpyarg(self, x):
|
def _tryconvertpyarg(self, x):
|
||||||
mod = None
|
"""Convert a dotted module name to path.
|
||||||
path = [os.path.abspath('.')] + sys.path
|
|
||||||
for name in x.split('.'):
|
|
||||||
# ignore anything that's not a proper name here
|
|
||||||
# else something like --pyargs will mess up '.'
|
|
||||||
# since imp.find_module will actually sometimes work for it
|
|
||||||
# but it's supposed to be considered a filesystem path
|
|
||||||
# not a package
|
|
||||||
if name_re.match(name) is None:
|
|
||||||
return x
|
|
||||||
try:
|
|
||||||
fd, mod, type_ = imp.find_module(name, path)
|
|
||||||
except ImportError:
|
|
||||||
return x
|
|
||||||
else:
|
|
||||||
if fd is not None:
|
|
||||||
fd.close()
|
|
||||||
|
|
||||||
if type_[2] != imp.PKG_DIRECTORY:
|
"""
|
||||||
path = [os.path.dirname(mod)]
|
import pkgutil
|
||||||
else:
|
try:
|
||||||
path = [mod]
|
loader = pkgutil.find_loader(x)
|
||||||
return mod
|
except ImportError:
|
||||||
|
return x
|
||||||
|
if loader is None:
|
||||||
|
return x
|
||||||
|
# This method is sometimes invoked when AssertionRewritingHook, which
|
||||||
|
# does not define a get_filename method, is already in place:
|
||||||
|
try:
|
||||||
|
path = loader.get_filename()
|
||||||
|
except AttributeError:
|
||||||
|
# Retrieve path from AssertionRewritingHook:
|
||||||
|
path = loader.modules[x][0].co_filename
|
||||||
|
if loader.is_package(x):
|
||||||
|
path = os.path.dirname(path)
|
||||||
|
return path
|
||||||
|
|
||||||
def _parsearg(self, arg):
|
def _parsearg(self, arg):
|
||||||
""" return (fspath, names) tuple after checking the file exists. """
|
""" return (fspath, names) tuple after checking the file exists. """
|
||||||
arg = str(arg)
|
|
||||||
if self.config.option.pyargs:
|
|
||||||
arg = self._tryconvertpyarg(arg)
|
|
||||||
parts = str(arg).split("::")
|
parts = str(arg).split("::")
|
||||||
|
if self.config.option.pyargs:
|
||||||
|
parts[0] = self._tryconvertpyarg(parts[0])
|
||||||
relpath = parts[0].replace("/", os.sep)
|
relpath = parts[0].replace("/", os.sep)
|
||||||
path = self.config.invocation_dir.join(relpath, abs=True)
|
path = self.config.invocation_dir.join(relpath, abs=True)
|
||||||
if not path.check():
|
if not path.check():
|
||||||
|
|
|
@ -123,15 +123,18 @@ def getexecutable(name, cache={}):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
executable = py.path.local.sysfind(name)
|
executable = py.path.local.sysfind(name)
|
||||||
if executable:
|
if executable:
|
||||||
|
import subprocess
|
||||||
|
popen = subprocess.Popen([str(executable), "--version"],
|
||||||
|
universal_newlines=True, stderr=subprocess.PIPE)
|
||||||
|
out, err = popen.communicate()
|
||||||
if name == "jython":
|
if name == "jython":
|
||||||
import subprocess
|
|
||||||
popen = subprocess.Popen([str(executable), "--version"],
|
|
||||||
universal_newlines=True, stderr=subprocess.PIPE)
|
|
||||||
out, err = popen.communicate()
|
|
||||||
if not err or "2.5" not in err:
|
if not err or "2.5" not in err:
|
||||||
executable = None
|
executable = None
|
||||||
if "2.5.2" in err:
|
if "2.5.2" in err:
|
||||||
executable = None # http://bugs.jython.org/issue1790
|
executable = None # http://bugs.jython.org/issue1790
|
||||||
|
elif popen.returncode != 0:
|
||||||
|
# Handle pyenv's 127.
|
||||||
|
executable = None
|
||||||
cache[name] = executable
|
cache[name] = executable
|
||||||
return executable
|
return executable
|
||||||
|
|
||||||
|
@ -374,10 +377,10 @@ class RunResult:
|
||||||
|
|
||||||
|
|
||||||
class Testdir:
|
class Testdir:
|
||||||
"""Temporary test directory with tools to test/run py.test itself.
|
"""Temporary test directory with tools to test/run pytest itself.
|
||||||
|
|
||||||
This is based on the ``tmpdir`` fixture but provides a number of
|
This is based on the ``tmpdir`` fixture but provides a number of
|
||||||
methods which aid with testing py.test itself. Unless
|
methods which aid with testing pytest itself. Unless
|
||||||
:py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
|
:py:meth:`chdir` is used all methods will use :py:attr:`tmpdir` as
|
||||||
current working directory.
|
current working directory.
|
||||||
|
|
||||||
|
@ -588,7 +591,7 @@ class Testdir:
|
||||||
"""Return the collection node of a file.
|
"""Return the collection node of a file.
|
||||||
|
|
||||||
This is like :py:meth:`getnode` but uses
|
This is like :py:meth:`getnode` but uses
|
||||||
:py:meth:`parseconfigure` to create the (configured) py.test
|
:py:meth:`parseconfigure` to create the (configured) pytest
|
||||||
Config instance.
|
Config instance.
|
||||||
|
|
||||||
:param path: A :py:class:`py.path.local` instance of the file.
|
:param path: A :py:class:`py.path.local` instance of the file.
|
||||||
|
@ -656,7 +659,7 @@ class Testdir:
|
||||||
:py:class:`HookRecorder` instance.
|
:py:class:`HookRecorder` instance.
|
||||||
|
|
||||||
This runs the :py:func:`pytest.main` function to run all of
|
This runs the :py:func:`pytest.main` function to run all of
|
||||||
py.test inside the test process itself like
|
pytest inside the test process itself like
|
||||||
:py:meth:`inline_run`. However the return value is a tuple of
|
:py:meth:`inline_run`. However the return value is a tuple of
|
||||||
the collection items and a :py:class:`HookRecorder` instance.
|
the collection items and a :py:class:`HookRecorder` instance.
|
||||||
|
|
||||||
|
@ -669,7 +672,7 @@ class Testdir:
|
||||||
"""Run ``pytest.main()`` in-process, returning a HookRecorder.
|
"""Run ``pytest.main()`` in-process, returning a HookRecorder.
|
||||||
|
|
||||||
This runs the :py:func:`pytest.main` function to run all of
|
This runs the :py:func:`pytest.main` function to run all of
|
||||||
py.test inside the test process itself. This means it can
|
pytest inside the test process itself. This means it can
|
||||||
return a :py:class:`HookRecorder` instance which gives more
|
return a :py:class:`HookRecorder` instance which gives more
|
||||||
detailed results from then run then can be done by matching
|
detailed results from then run then can be done by matching
|
||||||
stdout/stderr from :py:meth:`runpytest`.
|
stdout/stderr from :py:meth:`runpytest`.
|
||||||
|
@ -755,9 +758,9 @@ class Testdir:
|
||||||
return args
|
return args
|
||||||
|
|
||||||
def parseconfig(self, *args):
|
def parseconfig(self, *args):
|
||||||
"""Return a new py.test Config instance from given commandline args.
|
"""Return a new pytest Config instance from given commandline args.
|
||||||
|
|
||||||
This invokes the py.test bootstrapping code in _pytest.config
|
This invokes the pytest bootstrapping code in _pytest.config
|
||||||
to create a new :py:class:`_pytest.core.PluginManager` and
|
to create a new :py:class:`_pytest.core.PluginManager` and
|
||||||
call the pytest_cmdline_parse hook to create new
|
call the pytest_cmdline_parse hook to create new
|
||||||
:py:class:`_pytest.config.Config` instance.
|
:py:class:`_pytest.config.Config` instance.
|
||||||
|
@ -777,7 +780,7 @@ class Testdir:
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def parseconfigure(self, *args):
|
def parseconfigure(self, *args):
|
||||||
"""Return a new py.test configured Config instance.
|
"""Return a new pytest configured Config instance.
|
||||||
|
|
||||||
This returns a new :py:class:`_pytest.config.Config` instance
|
This returns a new :py:class:`_pytest.config.Config` instance
|
||||||
like :py:meth:`parseconfig`, but also calls the
|
like :py:meth:`parseconfig`, but also calls the
|
||||||
|
@ -792,7 +795,7 @@ class Testdir:
|
||||||
def getitem(self, source, funcname="test_func"):
|
def getitem(self, source, funcname="test_func"):
|
||||||
"""Return the test item for a test function.
|
"""Return the test item for a test function.
|
||||||
|
|
||||||
This writes the source to a python file and runs py.test's
|
This writes the source to a python file and runs pytest's
|
||||||
collection on the resulting module, returning the test item
|
collection on the resulting module, returning the test item
|
||||||
for the requested function name.
|
for the requested function name.
|
||||||
|
|
||||||
|
@ -812,7 +815,7 @@ class Testdir:
|
||||||
def getitems(self, source):
|
def getitems(self, source):
|
||||||
"""Return all test items collected from the module.
|
"""Return all test items collected from the module.
|
||||||
|
|
||||||
This writes the source to a python file and runs py.test's
|
This writes the source to a python file and runs pytest's
|
||||||
collection on the resulting module, returning all test items
|
collection on the resulting module, returning all test items
|
||||||
contained within.
|
contained within.
|
||||||
|
|
||||||
|
@ -824,7 +827,7 @@ class Testdir:
|
||||||
"""Return the module collection node for ``source``.
|
"""Return the module collection node for ``source``.
|
||||||
|
|
||||||
This writes ``source`` to a file using :py:meth:`makepyfile`
|
This writes ``source`` to a file using :py:meth:`makepyfile`
|
||||||
and then runs the py.test collection on it, returning the
|
and then runs the pytest collection on it, returning the
|
||||||
collection node for the test module.
|
collection node for the test module.
|
||||||
|
|
||||||
:param source: The source code of the module to collect.
|
:param source: The source code of the module to collect.
|
||||||
|
@ -924,7 +927,7 @@ class Testdir:
|
||||||
|
|
||||||
def _getpytestargs(self):
|
def _getpytestargs(self):
|
||||||
# we cannot use "(sys.executable,script)"
|
# we cannot use "(sys.executable,script)"
|
||||||
# because on windows the script is e.g. a py.test.exe
|
# because on windows the script is e.g. a pytest.exe
|
||||||
return (sys.executable, _pytest_fullpath,) # noqa
|
return (sys.executable, _pytest_fullpath,) # noqa
|
||||||
|
|
||||||
def runpython(self, script):
|
def runpython(self, script):
|
||||||
|
@ -939,7 +942,7 @@ class Testdir:
|
||||||
return self.run(sys.executable, "-c", command)
|
return self.run(sys.executable, "-c", command)
|
||||||
|
|
||||||
def runpytest_subprocess(self, *args, **kwargs):
|
def runpytest_subprocess(self, *args, **kwargs):
|
||||||
"""Run py.test as a subprocess with given arguments.
|
"""Run pytest as a subprocess with given arguments.
|
||||||
|
|
||||||
Any plugins added to the :py:attr:`plugins` list will added
|
Any plugins added to the :py:attr:`plugins` list will added
|
||||||
using the ``-p`` command line option. Addtionally
|
using the ``-p`` command line option. Addtionally
|
||||||
|
@ -967,9 +970,9 @@ class Testdir:
|
||||||
return self.run(*args)
|
return self.run(*args)
|
||||||
|
|
||||||
def spawn_pytest(self, string, expect_timeout=10.0):
|
def spawn_pytest(self, string, expect_timeout=10.0):
|
||||||
"""Run py.test using pexpect.
|
"""Run pytest using pexpect.
|
||||||
|
|
||||||
This makes sure to use the right py.test and sets up the
|
This makes sure to use the right pytest and sets up the
|
||||||
temporary directory locations.
|
temporary directory locations.
|
||||||
|
|
||||||
The pexpect child is returned.
|
The pexpect child is returned.
|
||||||
|
|
|
@ -2031,6 +2031,25 @@ class FixtureRequest(FuncargnamesCompatAttr):
|
||||||
except (AttributeError, ValueError):
|
except (AttributeError, ValueError):
|
||||||
param = NOTSET
|
param = NOTSET
|
||||||
param_index = 0
|
param_index = 0
|
||||||
|
if fixturedef.params is not None:
|
||||||
|
frame = inspect.stack()[3]
|
||||||
|
frameinfo = inspect.getframeinfo(frame[0])
|
||||||
|
source_path = frameinfo.filename
|
||||||
|
source_lineno = frameinfo.lineno
|
||||||
|
source_path = py.path.local(source_path)
|
||||||
|
if source_path.relto(funcitem.config.rootdir):
|
||||||
|
source_path = source_path.relto(funcitem.config.rootdir)
|
||||||
|
msg = (
|
||||||
|
"The requested fixture has no parameter defined for the "
|
||||||
|
"current test.\n\nRequested fixture '{0}' defined in:\n{1}"
|
||||||
|
"\n\nRequested here:\n{2}:{3}".format(
|
||||||
|
fixturedef.argname,
|
||||||
|
getlocation(fixturedef.func, funcitem.config.rootdir),
|
||||||
|
source_path,
|
||||||
|
source_lineno,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
pytest.fail(msg)
|
||||||
else:
|
else:
|
||||||
# indices might not be set if old-style metafunc.addcall() was used
|
# indices might not be set if old-style metafunc.addcall() was used
|
||||||
param_index = funcitem.callspec.indices.get(argname, 0)
|
param_index = funcitem.callspec.indices.get(argname, 0)
|
||||||
|
@ -2173,7 +2192,7 @@ class FixtureLookupError(LookupError):
|
||||||
available.append(name)
|
available.append(name)
|
||||||
msg = "fixture %r not found" % (self.argname,)
|
msg = "fixture %r not found" % (self.argname,)
|
||||||
msg += "\n available fixtures: %s" %(", ".join(available),)
|
msg += "\n available fixtures: %s" %(", ".join(available),)
|
||||||
msg += "\n use 'py.test --fixtures [testpath]' for help on them."
|
msg += "\n use 'pytest --fixtures [testpath]' for help on them."
|
||||||
|
|
||||||
return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
|
return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
|
||||||
|
|
||||||
|
@ -2369,7 +2388,7 @@ class FixtureManager:
|
||||||
else:
|
else:
|
||||||
if marker.name:
|
if marker.name:
|
||||||
name = marker.name
|
name = marker.name
|
||||||
assert not name.startswith(self._argprefix)
|
assert not name.startswith(self._argprefix), name
|
||||||
fixturedef = FixtureDef(self, nodeid, name, obj,
|
fixturedef = FixtureDef(self, nodeid, name, obj,
|
||||||
marker.scope, marker.params,
|
marker.scope, marker.params,
|
||||||
unittest=unittest, ids=marker.ids)
|
unittest=unittest, ids=marker.ids)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#
|
#
|
||||||
# If you're wondering how this is created: you can create it yourself if you
|
# 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-
|
# have a complete pytest installation by using this command on the command-
|
||||||
# line: ``py.test --genscript=runtests.py``.
|
# line: ``pytest --genscript=runtests.py``.
|
||||||
|
|
||||||
sources = """
|
sources = """
|
||||||
@SOURCES@"""
|
@SOURCES@"""
|
||||||
|
|
|
@ -7,7 +7,7 @@ Release announcements
|
||||||
|
|
||||||
|
|
||||||
sprint2016
|
sprint2016
|
||||||
release-2.9.1
|
release-2.9.2
|
||||||
release-2.9.1
|
release-2.9.1
|
||||||
release-2.9.0
|
release-2.9.0
|
||||||
release-2.8.7
|
release-2.8.7
|
||||||
|
|
|
@ -24,7 +24,7 @@ following::
|
||||||
to assert that your function returns a certain value. If this assertion fails
|
to assert that your function returns a certain value. If this assertion fails
|
||||||
you will see the return value of the function call::
|
you will see the return value of the function call::
|
||||||
|
|
||||||
$ py.test test_assert1.py
|
$ pytest test_assert1.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -168,7 +168,7 @@ when it encounters comparisons. For example::
|
||||||
|
|
||||||
if you run this module::
|
if you run this module::
|
||||||
|
|
||||||
$ py.test test_assert2.py
|
$ pytest test_assert2.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -237,7 +237,7 @@ now, given this test module::
|
||||||
you can run the test module and get the custom output defined in
|
you can run the test module and get the custom output defined in
|
||||||
the conftest file::
|
the conftest file::
|
||||||
|
|
||||||
$ py.test -q test_foocompare.py
|
$ pytest -q test_foocompare.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_compare ________
|
_______ test_compare ________
|
||||||
|
|
|
@ -18,11 +18,11 @@ For global activation of all argcomplete enabled python applications run::
|
||||||
|
|
||||||
For permanent (but not global) ``pytest`` activation, use::
|
For permanent (but not global) ``pytest`` activation, use::
|
||||||
|
|
||||||
register-python-argcomplete py.test >> ~/.bashrc
|
register-python-argcomplete pytest >> ~/.bashrc
|
||||||
|
|
||||||
For one-time activation of argcomplete for ``pytest`` only, use::
|
For one-time activation of argcomplete for ``pytest`` only, use::
|
||||||
|
|
||||||
eval "$(register-python-argcomplete py.test)"
|
eval "$(register-python-argcomplete pytest)"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ Builtin fixtures/function arguments
|
||||||
You can ask for available builtin or project-custom
|
You can ask for available builtin or project-custom
|
||||||
:ref:`fixtures <fixtures>` by typing::
|
:ref:`fixtures <fixtures>` by typing::
|
||||||
|
|
||||||
$ py.test -q --fixtures
|
$ pytest -q --fixtures
|
||||||
cache
|
cache
|
||||||
Return a cache object that can persist state between testing sessions.
|
Return a cache object that can persist state between testing sessions.
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ Usage
|
||||||
---------
|
---------
|
||||||
|
|
||||||
The plugin provides two command line options to rerun failures from the
|
The plugin provides two command line options to rerun failures from the
|
||||||
last ``py.test`` invocation:
|
last ``pytest`` invocation:
|
||||||
|
|
||||||
* ``--lf``, ``--last-failed`` - to only re-run the failures.
|
* ``--lf``, ``--last-failed`` - to only re-run the failures.
|
||||||
* ``--ff``, ``--failed-first`` - to run the failures first and then the rest of
|
* ``--ff``, ``--failed-first`` - to run the failures first and then the rest of
|
||||||
|
@ -25,7 +25,7 @@ For cleanup (usually not needed), a ``--cache-clear`` option allows to remove
|
||||||
all cross-session cache contents ahead of a test run.
|
all cross-session cache contents ahead of a test run.
|
||||||
|
|
||||||
Other plugins may access the `config.cache`_ object to set/get
|
Other plugins may access the `config.cache`_ object to set/get
|
||||||
**json encodable** values between ``py.test`` invocations.
|
**json encodable** values between ``pytest`` invocations.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ First, let's create 50 test invocation of which only 2 fail::
|
||||||
|
|
||||||
If you run this for the first time you will see two failures::
|
If you run this for the first time you will see two failures::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
.................F.......F........................
|
.................F.......F........................
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_num[17] ________
|
_______ test_num[17] ________
|
||||||
|
@ -78,7 +78,7 @@ If you run this for the first time you will see two failures::
|
||||||
|
|
||||||
If you then run it with ``--lf``::
|
If you then run it with ``--lf``::
|
||||||
|
|
||||||
$ py.test --lf
|
$ pytest --lf
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
run-last-failure: rerun last 2 failures
|
run-last-failure: rerun last 2 failures
|
||||||
|
@ -119,7 +119,7 @@ Now, if you run with the ``--ff`` option, all tests will be run but the first
|
||||||
previous failures will be executed first (as can be seen from the series
|
previous failures will be executed first (as can be seen from the series
|
||||||
of ``FF`` and dots)::
|
of ``FF`` and dots)::
|
||||||
|
|
||||||
$ py.test --ff
|
$ pytest --ff
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
run-last-failure: rerun last 2 failures first
|
run-last-failure: rerun last 2 failures first
|
||||||
|
@ -163,7 +163,7 @@ The new config.cache object
|
||||||
Plugins or conftest.py support code can get a cached value using the
|
Plugins or conftest.py support code can get a cached value using the
|
||||||
pytest ``config`` object. Here is a basic example plugin which
|
pytest ``config`` object. Here is a basic example plugin which
|
||||||
implements a :ref:`fixture` which re-uses previously created state
|
implements a :ref:`fixture` which re-uses previously created state
|
||||||
across py.test invocations::
|
across pytest invocations::
|
||||||
|
|
||||||
# content of test_caching.py
|
# content of test_caching.py
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -184,7 +184,7 @@ across py.test invocations::
|
||||||
If you run this command once, it will take a while because
|
If you run this command once, it will take a while because
|
||||||
of the sleep::
|
of the sleep::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_function ________
|
_______ test_function ________
|
||||||
|
@ -201,7 +201,7 @@ of the sleep::
|
||||||
If you run it a second time the value will be retrieved from
|
If you run it a second time the value will be retrieved from
|
||||||
the cache and this will be quick::
|
the cache and this will be quick::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_function ________
|
_______ test_function ________
|
||||||
|
@ -222,9 +222,9 @@ Inspecting Cache content
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
You can always peek at the content of the cache using the
|
You can always peek at the content of the cache using the
|
||||||
``--cache-clear`` command line option::
|
``--cache-show`` command line option::
|
||||||
|
|
||||||
$ py.test --cache-clear
|
$ py.test --cache-show
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -250,7 +250,7 @@ Clearing Cache content
|
||||||
You can instruct pytest to clear all cache files and values
|
You can instruct pytest to clear all cache files and values
|
||||||
by adding the ``--cache-clear`` option like this::
|
by adding the ``--cache-clear`` option like this::
|
||||||
|
|
||||||
py.test --cache-clear
|
pytest --cache-clear
|
||||||
|
|
||||||
This is recommended for invocations from Continous Integration
|
This is recommended for invocations from Continous Integration
|
||||||
servers where isolation and correctness is more important
|
servers where isolation and correctness is more important
|
||||||
|
|
|
@ -36,9 +36,9 @@ There are two ways in which ``pytest`` can perform capturing:
|
||||||
|
|
||||||
You can influence output capturing mechanisms from the command line::
|
You can influence output capturing mechanisms from the command line::
|
||||||
|
|
||||||
py.test -s # disable all capturing
|
pytest -s # disable all capturing
|
||||||
py.test --capture=sys # replace sys.stdout/stderr with in-mem files
|
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
|
||||||
py.test --capture=fd # also point filedescriptors 1 and 2 to temp file
|
pytest --capture=fd # also point filedescriptors 1 and 2 to temp file
|
||||||
|
|
||||||
.. _printdebugging:
|
.. _printdebugging:
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ is that you can use print statements for debugging::
|
||||||
and running this module will show you precisely the output
|
and running this module will show you precisely the output
|
||||||
of the failing function and hide the other one::
|
of the failing function and hide the other one::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
|
|
@ -7,7 +7,7 @@ Command line options and configuration file settings
|
||||||
You can get help on command line options and values in INI-style
|
You can get help on command line options and values in INI-style
|
||||||
configurations files by using the general help option::
|
configurations files by using the general help option::
|
||||||
|
|
||||||
py.test -h # prints options _and_ config file settings
|
pytest -h # prints options _and_ config file settings
|
||||||
|
|
||||||
This will display command line and configuration file settings
|
This will display command line and configuration file settings
|
||||||
which were registered by installed plugins.
|
which were registered by installed plugins.
|
||||||
|
@ -62,7 +62,7 @@ per-testrun information.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
py.test path/to/testdir path/other/
|
pytest path/to/testdir path/other/
|
||||||
|
|
||||||
will determine the common ancestor as ``path`` and then
|
will determine the common ancestor as ``path`` and then
|
||||||
check for ini-files as follows::
|
check for ini-files as follows::
|
||||||
|
@ -126,9 +126,9 @@ Builtin configuration file options
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
||||||
|
|
||||||
issuing ``py.test test_hello.py`` actually means::
|
issuing ``pytest test_hello.py`` actually means::
|
||||||
|
|
||||||
py.test --maxfail=2 -rf test_hello.py
|
pytest --maxfail=2 -rf test_hello.py
|
||||||
|
|
||||||
Default is to add no options.
|
Default is to add no options.
|
||||||
|
|
||||||
|
@ -218,7 +218,7 @@ Builtin configuration file options
|
||||||
.. confval:: doctest_optionflags
|
.. confval:: doctest_optionflags
|
||||||
|
|
||||||
One or more doctest flag names from the standard ``doctest`` module.
|
One or more doctest flag names from the standard ``doctest`` module.
|
||||||
:doc:`See how py.test handles doctests <doctest>`.
|
:doc:`See how pytest handles doctests <doctest>`.
|
||||||
|
|
||||||
.. confval:: confcutdir
|
.. confval:: confcutdir
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ By default all files matching the ``test*.txt`` pattern will
|
||||||
be run through the python standard ``doctest`` module. You
|
be run through the python standard ``doctest`` module. You
|
||||||
can change the pattern by issuing::
|
can change the pattern by issuing::
|
||||||
|
|
||||||
py.test --doctest-glob='*.rst'
|
pytest --doctest-glob='*.rst'
|
||||||
|
|
||||||
on the command line. Since version ``2.9``, ``--doctest-glob``
|
on the command line. Since version ``2.9``, ``--doctest-glob``
|
||||||
can be given multiple times in the command-line.
|
can be given multiple times in the command-line.
|
||||||
|
@ -15,7 +15,7 @@ You can also trigger running of doctests
|
||||||
from docstrings in all python modules (including regular
|
from docstrings in all python modules (including regular
|
||||||
python test modules)::
|
python test modules)::
|
||||||
|
|
||||||
py.test --doctest-modules
|
pytest --doctest-modules
|
||||||
|
|
||||||
You can make these changes permanent in your project by
|
You can make these changes permanent in your project by
|
||||||
putting them into a pytest.ini file like this:
|
putting them into a pytest.ini file like this:
|
||||||
|
@ -45,9 +45,9 @@ and another like this::
|
||||||
"""
|
"""
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
then you can just invoke ``py.test`` without command line options::
|
then you can just invoke ``pytest`` without command line options::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||||
|
@ -68,7 +68,7 @@ Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
|
||||||
when executing text doctest files.
|
when executing text doctest files.
|
||||||
|
|
||||||
The standard ``doctest`` module provides some setting flags to configure the
|
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
|
strictness of doctest tests. In pytest You can enable those flags those flags
|
||||||
using the configuration file. To make pytest ignore trailing whitespaces and
|
using the configuration file. To make pytest ignore trailing whitespaces and
|
||||||
ignore lengthy exception stack traces you can just write:
|
ignore lengthy exception stack traces you can just write:
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ ignore lengthy exception stack traces you can just write:
|
||||||
[pytest]
|
[pytest]
|
||||||
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
|
doctest_optionflags= NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL
|
||||||
|
|
||||||
py.test also introduces new options to allow doctests to run in Python 2 and
|
pytest also introduces new options to allow doctests to run in Python 2 and
|
||||||
Python 3 unchanged:
|
Python 3 unchanged:
|
||||||
|
|
||||||
* ``ALLOW_UNICODE``: when enabled, the ``u`` prefix is stripped from unicode
|
* ``ALLOW_UNICODE``: when enabled, the ``u`` prefix is stripped from unicode
|
||||||
|
|
|
@ -29,7 +29,7 @@ You can "mark" a test function with custom metadata like this::
|
||||||
|
|
||||||
You can then restrict a test run to only run tests marked with ``webtest``::
|
You can then restrict a test run to only run tests marked with ``webtest``::
|
||||||
|
|
||||||
$ py.test -v -m webtest
|
$ pytest -v -m webtest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -43,7 +43,7 @@ You can then restrict a test run to only run tests marked with ``webtest``::
|
||||||
|
|
||||||
Or the inverse, running all tests except the webtest ones::
|
Or the inverse, running all tests except the webtest ones::
|
||||||
|
|
||||||
$ py.test -v -m "not webtest"
|
$ pytest -v -m "not webtest"
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -64,7 +64,7 @@ You can provide one or more :ref:`node IDs <node-id>` as positional
|
||||||
arguments to select only specified tests. This makes it easy to select
|
arguments to select only specified tests. This makes it easy to select
|
||||||
tests based on their module, class, method, or function name::
|
tests based on their module, class, method, or function name::
|
||||||
|
|
||||||
$ py.test -v test_server.py::TestClass::test_method
|
$ pytest -v test_server.py::TestClass::test_method
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -77,7 +77,7 @@ tests based on their module, class, method, or function name::
|
||||||
|
|
||||||
You can also select on the class::
|
You can also select on the class::
|
||||||
|
|
||||||
$ py.test -v test_server.py::TestClass
|
$ pytest -v test_server.py::TestClass
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -90,7 +90,7 @@ You can also select on the class::
|
||||||
|
|
||||||
Or select multiple nodes::
|
Or select multiple nodes::
|
||||||
|
|
||||||
$ py.test -v test_server.py::TestClass test_server.py::test_send_http
|
$ pytest -v test_server.py::TestClass test_server.py::test_send_http
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -115,8 +115,8 @@ Or select multiple nodes::
|
||||||
``module.py::function[param]``.
|
``module.py::function[param]``.
|
||||||
|
|
||||||
Node IDs for failing tests are displayed in the test summary info
|
Node IDs for failing tests are displayed in the test summary info
|
||||||
when running py.test with the ``-rf`` option. You can also
|
when running pytest with the ``-rf`` option. You can also
|
||||||
construct Node IDs from the output of ``py.test --collectonly``.
|
construct Node IDs from the output of ``pytest --collectonly``.
|
||||||
|
|
||||||
Using ``-k expr`` to select tests based on their name
|
Using ``-k expr`` to select tests based on their name
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
@ -128,7 +128,7 @@ which implements a substring match on the test names instead of the
|
||||||
exact match on markers that ``-m`` provides. This makes it easy to
|
exact match on markers that ``-m`` provides. This makes it easy to
|
||||||
select tests based on their names::
|
select tests based on their names::
|
||||||
|
|
||||||
$ py.test -v -k http # running with the above defined example module
|
$ pytest -v -k http # running with the above defined example module
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -142,7 +142,7 @@ select tests based on their names::
|
||||||
|
|
||||||
And you can also run all tests except the ones that match the keyword::
|
And you can also run all tests except the ones that match the keyword::
|
||||||
|
|
||||||
$ py.test -k "not send_http" -v
|
$ pytest -k "not send_http" -v
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -158,7 +158,7 @@ And you can also run all tests except the ones that match the keyword::
|
||||||
|
|
||||||
Or to select "http" and "quick" tests::
|
Or to select "http" and "quick" tests::
|
||||||
|
|
||||||
$ py.test -k "http or quick" -v
|
$ pytest -k "http or quick" -v
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -198,7 +198,7 @@ Registering markers for your test suite is simple::
|
||||||
|
|
||||||
You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
|
You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
|
||||||
|
|
||||||
$ py.test --markers
|
$ pytest --markers
|
||||||
@pytest.mark.webtest: mark a test as a webtest.
|
@pytest.mark.webtest: mark a test as a webtest.
|
||||||
|
|
||||||
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
||||||
|
@ -225,7 +225,7 @@ For an example on how to add and work with markers from a plugin, see
|
||||||
|
|
||||||
* there is one place in your test suite defining your markers
|
* there is one place in your test suite defining your markers
|
||||||
|
|
||||||
* asking for existing markers via ``py.test --markers`` gives good output
|
* asking for existing markers via ``pytest --markers`` gives good output
|
||||||
|
|
||||||
* typos in function markers are treated as an error if you use
|
* typos in function markers are treated as an error if you use
|
||||||
the ``--strict`` option. Future versions of ``pytest`` are probably
|
the ``--strict`` option. Future versions of ``pytest`` are probably
|
||||||
|
@ -350,7 +350,7 @@ A test file using this local plugin::
|
||||||
and an example invocations specifying a different environment than what
|
and an example invocations specifying a different environment than what
|
||||||
the test needs::
|
the test needs::
|
||||||
|
|
||||||
$ py.test -E stage2
|
$ pytest -E stage2
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -362,7 +362,7 @@ the test needs::
|
||||||
|
|
||||||
and here is one that specifies exactly the environment needed::
|
and here is one that specifies exactly the environment needed::
|
||||||
|
|
||||||
$ py.test -E stage1
|
$ pytest -E stage1
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -374,7 +374,7 @@ and here is one that specifies exactly the environment needed::
|
||||||
|
|
||||||
The ``--markers`` option always gives you a list of available markers::
|
The ``--markers`` option always gives you a list of available markers::
|
||||||
|
|
||||||
$ py.test --markers
|
$ pytest --markers
|
||||||
@pytest.mark.env(name): mark test to run only on named environment
|
@pytest.mark.env(name): mark test to run only on named environment
|
||||||
|
|
||||||
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
||||||
|
@ -427,7 +427,7 @@ test function. From a conftest file we can read it like this::
|
||||||
|
|
||||||
Let's run this without capturing output and see what we get::
|
Let's run this without capturing output and see what we get::
|
||||||
|
|
||||||
$ py.test -q -s
|
$ pytest -q -s
|
||||||
glob args=('function',) kwargs={'x': 3}
|
glob args=('function',) kwargs={'x': 3}
|
||||||
glob args=('class',) kwargs={'x': 2}
|
glob args=('class',) kwargs={'x': 2}
|
||||||
glob args=('module',) kwargs={'x': 1}
|
glob args=('module',) kwargs={'x': 1}
|
||||||
|
@ -483,7 +483,7 @@ Let's do a little test file to show how this looks like::
|
||||||
|
|
||||||
then you will see two test skipped and two executed tests as expected::
|
then you will see two test skipped and two executed tests as expected::
|
||||||
|
|
||||||
$ py.test -rs # this option reports skip reasons
|
$ pytest -rs # this option reports skip reasons
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -497,7 +497,7 @@ then you will see two test skipped and two executed tests as expected::
|
||||||
|
|
||||||
Note that if you specify a platform via the marker-command line option like this::
|
Note that if you specify a platform via the marker-command line option like this::
|
||||||
|
|
||||||
$ py.test -m linux2
|
$ pytest -m linux2
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -549,7 +549,7 @@ We want to dynamically define two markers and can do it in a
|
||||||
|
|
||||||
We can now use the ``-m option`` to select one set::
|
We can now use the ``-m option`` to select one set::
|
||||||
|
|
||||||
$ py.test -m interface --tb=short
|
$ pytest -m interface --tb=short
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -571,7 +571,7 @@ We can now use the ``-m option`` to select one set::
|
||||||
|
|
||||||
or to select both "event" and "interface" tests::
|
or to select both "event" and "interface" tests::
|
||||||
|
|
||||||
$ py.test -m "interface or event" --tb=short
|
$ pytest -m "interface or event" --tb=short
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
|
|
@ -25,7 +25,7 @@ You can create a simple example file:
|
||||||
and if you installed `PyYAML`_ or a compatible YAML-parser you can
|
and if you installed `PyYAML`_ or a compatible YAML-parser you can
|
||||||
now execute the test specification::
|
now execute the test specification::
|
||||||
|
|
||||||
nonpython $ py.test test_simple.yml
|
nonpython $ pytest test_simple.yml
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||||
|
@ -57,7 +57,7 @@ your own domain specific testing language this way.
|
||||||
``reportinfo()`` is used for representing the test location and is also
|
``reportinfo()`` is used for representing the test location and is also
|
||||||
consulted when reporting in ``verbose`` mode::
|
consulted when reporting in ``verbose`` mode::
|
||||||
|
|
||||||
nonpython $ py.test -v
|
nonpython $ pytest -v
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -79,7 +79,7 @@ consulted when reporting in ``verbose`` mode::
|
||||||
While developing your custom test collection and execution it's also
|
While developing your custom test collection and execution it's also
|
||||||
interesting to just look at the collection tree::
|
interesting to just look at the collection tree::
|
||||||
|
|
||||||
nonpython $ py.test --collect-only
|
nonpython $ pytest --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||||
|
|
|
@ -44,14 +44,14 @@ Now we add a test configuration like this::
|
||||||
|
|
||||||
This means that we only run 2 tests if we do not pass ``--all``::
|
This means that we only run 2 tests if we do not pass ``--all``::
|
||||||
|
|
||||||
$ py.test -q test_compute.py
|
$ pytest -q test_compute.py
|
||||||
..
|
..
|
||||||
2 passed in 0.12 seconds
|
2 passed in 0.12 seconds
|
||||||
|
|
||||||
We run only two computations, so we see two dots.
|
We run only two computations, so we see two dots.
|
||||||
let's run the full monty::
|
let's run the full monty::
|
||||||
|
|
||||||
$ py.test -q --all
|
$ pytest -q --all
|
||||||
....F
|
....F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_compute[4] ________
|
_______ test_compute[4] ________
|
||||||
|
@ -128,7 +128,7 @@ label generated by ``idfn``, but because we didn't generate a label for ``timede
|
||||||
objects, they are still using the default pytest representation::
|
objects, they are still using the default pytest representation::
|
||||||
|
|
||||||
|
|
||||||
$ py.test test_time.py --collect-only
|
$ pytest test_time.py --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -179,7 +179,7 @@ only have to work a bit to construct the correct arguments for pytest's
|
||||||
|
|
||||||
this is a fully self-contained example which you can run with::
|
this is a fully self-contained example which you can run with::
|
||||||
|
|
||||||
$ py.test test_scenarios.py
|
$ pytest test_scenarios.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -192,7 +192,7 @@ this is a fully self-contained example which you can run with::
|
||||||
If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function::
|
If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function::
|
||||||
|
|
||||||
|
|
||||||
$ py.test --collect-only test_scenarios.py
|
$ pytest --collect-only test_scenarios.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -257,7 +257,7 @@ creates a database object for the actual test invocations::
|
||||||
|
|
||||||
Let's first see how it looks like at collection time::
|
Let's first see how it looks like at collection time::
|
||||||
|
|
||||||
$ py.test test_backends.py --collect-only
|
$ pytest test_backends.py --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -270,7 +270,7 @@ Let's first see how it looks like at collection time::
|
||||||
|
|
||||||
And then when we run the test::
|
And then when we run the test::
|
||||||
|
|
||||||
$ py.test -q test_backends.py
|
$ pytest -q test_backends.py
|
||||||
.F
|
.F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_db_initialized[d2] ________
|
_______ test_db_initialized[d2] ________
|
||||||
|
@ -318,7 +318,7 @@ will be passed to respective fixture function::
|
||||||
|
|
||||||
The result of this test will be successful::
|
The result of this test will be successful::
|
||||||
|
|
||||||
$ py.test test_indirect_list.py --collect-only
|
$ pytest test_indirect_list.py --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -366,7 +366,7 @@ parametrizer`_ but in a lot less code::
|
||||||
Our test generator looks up a class-level definition which specifies which
|
Our test generator looks up a class-level definition which specifies which
|
||||||
argument sets to use for each test function. Let's run it::
|
argument sets to use for each test function. Let's run it::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
F..
|
F..
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ TestClass.test_equals[1-2] ________
|
_______ TestClass.test_equals[1-2] ________
|
||||||
|
@ -396,7 +396,7 @@ 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)::
|
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
|
. $ pytest -rs -q multipython.py
|
||||||
...........................
|
...........................
|
||||||
27 passed in 0.12 seconds
|
27 passed in 0.12 seconds
|
||||||
|
|
||||||
|
@ -443,7 +443,7 @@ And finally a little test module::
|
||||||
|
|
||||||
If you run this with reporting for skips enabled::
|
If you run this with reporting for skips enabled::
|
||||||
|
|
||||||
$ py.test -rs test_module.py
|
$ pytest -rs test_module.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
# run this with $ py.test --collect-only test_collectonly.py
|
# run this with $ pytest --collect-only test_collectonly.py
|
||||||
#
|
#
|
||||||
def test_function():
|
def test_function():
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -80,7 +80,7 @@ that match ``*_check``. For example, if we have::
|
||||||
|
|
||||||
then the test collection looks like this::
|
then the test collection looks like this::
|
||||||
|
|
||||||
$ py.test --collect-only
|
$ pytest --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile: setup.cfg
|
rootdir: $REGENDOC_TMPDIR, inifile: setup.cfg
|
||||||
|
@ -107,7 +107,7 @@ interpreting arguments as python package names, deriving
|
||||||
their file system path and then running the test. For
|
their file system path and then running the test. For
|
||||||
example if you have unittest2 installed you can type::
|
example if you have unittest2 installed you can type::
|
||||||
|
|
||||||
py.test --pyargs unittest2.test.test_skipping -q
|
pytest --pyargs unittest2.test.test_skipping -q
|
||||||
|
|
||||||
which would run the respective test module. Like with
|
which would run the respective test module. Like with
|
||||||
other options, through an ini-file and the :confval:`addopts` option you
|
other options, through an ini-file and the :confval:`addopts` option you
|
||||||
|
@ -117,7 +117,7 @@ can make this change more permanently::
|
||||||
[pytest]
|
[pytest]
|
||||||
addopts = --pyargs
|
addopts = --pyargs
|
||||||
|
|
||||||
Now a simple invocation of ``py.test NAME`` will check
|
Now a simple invocation of ``pytest NAME`` will check
|
||||||
if NAME exists as an importable package/module and otherwise
|
if NAME exists as an importable package/module and otherwise
|
||||||
treat it as a filesystem path.
|
treat it as a filesystem path.
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ Finding out what is collected
|
||||||
|
|
||||||
You can always peek at the collection tree without running tests like this::
|
You can always peek at the collection tree without running tests like this::
|
||||||
|
|
||||||
. $ py.test --collect-only pythoncollection.py
|
. $ pytest --collect-only pythoncollection.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||||
|
@ -180,7 +180,7 @@ and a setup.py dummy file like this::
|
||||||
then a pytest run on Python2 will find the one test and will leave out the
|
then a pytest run on Python2 will find the one test and will leave out the
|
||||||
setup.py file::
|
setup.py file::
|
||||||
|
|
||||||
#$ py.test --collect-only
|
#$ pytest --collect-only
|
||||||
====== test session starts ======
|
====== test session starts ======
|
||||||
platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
|
platform linux2 -- Python 2.7.10, pytest-2.9.1, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||||
|
@ -193,7 +193,7 @@ setup.py file::
|
||||||
If you run with a Python3 interpreter both the one test and the setup.py file
|
If you run with a Python3 interpreter both the one test and the setup.py file
|
||||||
will be left out::
|
will be left out::
|
||||||
|
|
||||||
$ py.test --collect-only
|
$ pytest --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||||
|
|
|
@ -11,7 +11,7 @@ get on the terminal - we are working on that):
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
assertion $ py.test failure_demo.py
|
assertion $ pytest failure_demo.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
|
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
|
||||||
|
|
|
@ -37,7 +37,7 @@ provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`::
|
||||||
|
|
||||||
Let's run this without supplying our new option::
|
Let's run this without supplying our new option::
|
||||||
|
|
||||||
$ py.test -q test_sample.py
|
$ pytest -q test_sample.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_answer ________
|
_______ test_answer ________
|
||||||
|
@ -59,7 +59,7 @@ Let's run this without supplying our new option::
|
||||||
|
|
||||||
And now with supplying a command line option::
|
And now with supplying a command line option::
|
||||||
|
|
||||||
$ py.test -q --cmdopt=type2
|
$ pytest -q --cmdopt=type2
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_answer ________
|
_______ test_answer ________
|
||||||
|
@ -106,7 +106,7 @@ you will now always perform test runs using a number
|
||||||
of subprocesses close to your CPU. Running in an empty
|
of subprocesses close to your CPU. Running in an empty
|
||||||
directory with the above conftest.py::
|
directory with the above conftest.py::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -154,7 +154,7 @@ We can now write a test module like this::
|
||||||
|
|
||||||
and when running it will see a skipped "slow" test::
|
and when running it will see a skipped "slow" test::
|
||||||
|
|
||||||
$ py.test -rs # "-rs" means report details on the little 's'
|
$ pytest -rs # "-rs" means report details on the little 's'
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -168,7 +168,7 @@ and when running it will see a skipped "slow" test::
|
||||||
|
|
||||||
Or run it including the ``slow`` marked test::
|
Or run it including the ``slow`` marked test::
|
||||||
|
|
||||||
$ py.test --runslow
|
$ pytest --runslow
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -204,7 +204,7 @@ of tracebacks: the ``checkconfig`` function will not be shown
|
||||||
unless the ``--full-trace`` command line option is specified.
|
unless the ``--full-trace`` command line option is specified.
|
||||||
Let's run our little function::
|
Let's run our little function::
|
||||||
|
|
||||||
$ py.test -q test_checkconfig.py
|
$ pytest -q test_checkconfig.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_something ________
|
_______ test_something ________
|
||||||
|
@ -282,7 +282,7 @@ It's easy to present extra information in a ``pytest`` run::
|
||||||
|
|
||||||
which will add the string to the test header accordingly::
|
which will add the string to the test header accordingly::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
project deps: mylib-1.1
|
project deps: mylib-1.1
|
||||||
|
@ -295,18 +295,18 @@ which will add the string to the test header accordingly::
|
||||||
|
|
||||||
You can also return a list of strings which will be considered as several
|
You can also return a list of strings which will be considered as several
|
||||||
lines of information. You can of course also make the amount of reporting
|
lines of information. You can of course also make the amount of reporting
|
||||||
information on e.g. the value of ``config.option.verbose`` so that
|
information on e.g. the value of ``config.getoption('verbose')`` so that
|
||||||
you present more information appropriately::
|
you present more information appropriately::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
|
|
||||||
def pytest_report_header(config):
|
def pytest_report_header(config):
|
||||||
if config.option.verbose > 0:
|
if config.getoption('verbose') > 0:
|
||||||
return ["info1: did you know that ...", "did you?"]
|
return ["info1: did you know that ...", "did you?"]
|
||||||
|
|
||||||
which will add info only when run with "--v"::
|
which will add info only when run with "--v"::
|
||||||
|
|
||||||
$ py.test -v
|
$ pytest -v
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -319,7 +319,7 @@ which will add info only when run with "--v"::
|
||||||
|
|
||||||
and nothing when run plainly::
|
and nothing when run plainly::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -352,7 +352,7 @@ out which tests are the slowest. Let's make an artificial test suite::
|
||||||
|
|
||||||
Now we can profile which test functions execute the slowest::
|
Now we can profile which test functions execute the slowest::
|
||||||
|
|
||||||
$ py.test --durations=3
|
$ pytest --durations=3
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -414,7 +414,7 @@ tests in a class. Here is a test module example::
|
||||||
|
|
||||||
If we run this::
|
If we run this::
|
||||||
|
|
||||||
$ py.test -rx
|
$ pytest -rx
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -485,7 +485,7 @@ the ``db`` fixture::
|
||||||
|
|
||||||
We can run this::
|
We can run this::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -502,7 +502,7 @@ We can run this::
|
||||||
def test_root(db): # no db here, will error out
|
def test_root(db): # no db here, will error out
|
||||||
fixture 'db' not found
|
fixture 'db' not found
|
||||||
available fixtures: tmpdir_factory, cache, tmpdir, pytestconfig, recwarn, monkeypatch, capfd, record_xml_property, capsys
|
available fixtures: tmpdir_factory, cache, tmpdir, pytestconfig, recwarn, monkeypatch, capfd, record_xml_property, capsys
|
||||||
use 'py.test --fixtures [testpath]' for help on them.
|
use 'pytest --fixtures [testpath]' for help on them.
|
||||||
|
|
||||||
$REGENDOC_TMPDIR/b/test_error.py:1
|
$REGENDOC_TMPDIR/b/test_error.py:1
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
|
@ -589,7 +589,7 @@ if you then have failing tests::
|
||||||
|
|
||||||
and run them::
|
and run them::
|
||||||
|
|
||||||
$ py.test test_module.py
|
$ pytest test_module.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -679,7 +679,7 @@ if you then have failing tests::
|
||||||
|
|
||||||
and run it::
|
and run it::
|
||||||
|
|
||||||
$ py.test -s test_module.py
|
$ pytest -s test_module.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -767,6 +767,6 @@ over to ``pytest`` instead. For example::
|
||||||
...
|
...
|
||||||
|
|
||||||
This makes it convenient to execute your tests from within your frozen
|
This makes it convenient to execute your tests from within your frozen
|
||||||
application, using standard ``py.test`` command-line options::
|
application, using standard ``pytest`` command-line options::
|
||||||
|
|
||||||
./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
|
./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
|
||||||
|
|
|
@ -59,7 +59,7 @@ will be called ahead of running any tests::
|
||||||
|
|
||||||
If you run this without output capturing::
|
If you run this without output capturing::
|
||||||
|
|
||||||
$ py.test -q -s test_module.py
|
$ pytest -q -s test_module.py
|
||||||
callattr_ahead_of_alltests called
|
callattr_ahead_of_alltests called
|
||||||
callme called!
|
callme called!
|
||||||
callme other called
|
callme other called
|
||||||
|
|
|
@ -81,18 +81,17 @@ You can also turn off all assertion interaction using the
|
||||||
.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
|
.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
|
||||||
|
|
||||||
|
|
||||||
Why a ``py.test`` instead of a ``pytest`` command?
|
Why can I use both ``pytest`` and ``py.test`` commands?
|
||||||
++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
Some of the reasons are historic, others are practical. ``pytest``
|
pytest used to be part of the py package, which provided several developer
|
||||||
used to be part of the ``py`` package which provided several developer
|
utilities, all starting with ``py.<TAB>``, thus providing nice TAB-completion.
|
||||||
utilities, all starting with ``py.<TAB>``, thus providing nice
|
If you install ``pip install pycmd`` you get these tools from a separate
|
||||||
TAB-completion. If
|
package. Once ``pytest`` became a separate package, the ``py.test`` name was
|
||||||
you install ``pip install pycmd`` you get these tools from a separate
|
retained due to avoid a naming conflict with another tool. This conflict was
|
||||||
package. These days the command line tool could be called ``pytest``
|
eventually resolved, and the ``pytest`` command was therefore introduced. In
|
||||||
but since many people have gotten used to the old name and there
|
future versions of pytest, we may deprecate and later remove the ``py.test``
|
||||||
is another tool named "pytest" we just decided to stick with
|
command to avoid perpetuating the confusion.
|
||||||
``py.test`` for now.
|
|
||||||
|
|
||||||
pytest fixtures, parametrized tests
|
pytest fixtures, parametrized tests
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
|
@ -68,7 +68,7 @@ Here, the ``test_ehlo`` needs the ``smtp`` fixture value. pytest
|
||||||
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
|
will discover and call the :py:func:`@pytest.fixture <_pytest.python.fixture>`
|
||||||
marked ``smtp`` fixture function. Running the test looks like this::
|
marked ``smtp`` fixture function. Running the test looks like this::
|
||||||
|
|
||||||
$ py.test test_smtpsimple.py
|
$ pytest test_smtpsimple.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -113,7 +113,7 @@ with a list of available function arguments.
|
||||||
|
|
||||||
You can always issue::
|
You can always issue::
|
||||||
|
|
||||||
py.test --fixtures test_simplefactory.py
|
pytest --fixtures test_simplefactory.py
|
||||||
|
|
||||||
to see available fixtures.
|
to see available fixtures.
|
||||||
|
|
||||||
|
@ -186,7 +186,7 @@ function (in or below the directory where ``conftest.py`` is located)::
|
||||||
We deliberately insert failing ``assert 0`` statements in order to
|
We deliberately insert failing ``assert 0`` statements in order to
|
||||||
inspect what is going on and can now run the tests::
|
inspect what is going on and can now run the tests::
|
||||||
|
|
||||||
$ py.test test_module.py
|
$ pytest test_module.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -262,7 +262,7 @@ the fixture in the module has finished execution, regardless of the exception st
|
||||||
|
|
||||||
Let's execute it::
|
Let's execute it::
|
||||||
|
|
||||||
$ py.test -s -q --tb=no
|
$ pytest -s -q --tb=no
|
||||||
FFteardown smtp
|
FFteardown smtp
|
||||||
|
|
||||||
2 failed in 0.12 seconds
|
2 failed in 0.12 seconds
|
||||||
|
@ -350,7 +350,7 @@ We use the ``request.module`` attribute to optionally obtain an
|
||||||
``smtpserver`` attribute from the test module. If we just execute
|
``smtpserver`` attribute from the test module. If we just execute
|
||||||
again, nothing much has changed::
|
again, nothing much has changed::
|
||||||
|
|
||||||
$ py.test -s -q --tb=no
|
$ pytest -s -q --tb=no
|
||||||
FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
|
FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
|
||||||
|
|
||||||
2 failed in 0.12 seconds
|
2 failed in 0.12 seconds
|
||||||
|
@ -367,7 +367,7 @@ server URL in its module namespace::
|
||||||
|
|
||||||
Running it::
|
Running it::
|
||||||
|
|
||||||
$ py.test -qq --tb=short test_anothersmtp.py
|
$ pytest -qq --tb=short test_anothersmtp.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_showhelo ________
|
_______ test_showhelo ________
|
||||||
|
@ -414,7 +414,7 @@ for each of which the fixture function will execute and can access
|
||||||
a value via ``request.param``. No test function code needs to change.
|
a value via ``request.param``. No test function code needs to change.
|
||||||
So let's just do another run::
|
So let's just do another run::
|
||||||
|
|
||||||
$ py.test -q test_module.py
|
$ pytest -q test_module.py
|
||||||
FFFF
|
FFFF
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_ehlo[smtp.gmail.com] ________
|
_______ test_ehlo[smtp.gmail.com] ________
|
||||||
|
@ -514,7 +514,7 @@ return ``None`` then pytest's auto-generated ID will be used.
|
||||||
|
|
||||||
Running the above tests results in the following test IDs being used::
|
Running the above tests results in the following test IDs being used::
|
||||||
|
|
||||||
$ py.test --collect-only
|
$ pytest --collect-only
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -565,7 +565,7 @@ and instantiate an object ``app`` where we stick the already defined
|
||||||
Here we declare an ``app`` fixture which receives the previously defined
|
Here we declare an ``app`` fixture which receives the previously defined
|
||||||
``smtp`` fixture and instantiates an ``App`` object with it. Let's run it::
|
``smtp`` fixture and instantiates an ``App`` object with it. Let's run it::
|
||||||
|
|
||||||
$ py.test -v test_appsetup.py
|
$ pytest -v test_appsetup.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -634,7 +634,7 @@ to show the setup/teardown flow::
|
||||||
|
|
||||||
Let's run the tests in verbose mode and with looking at the print-output::
|
Let's run the tests in verbose mode and with looking at the print-output::
|
||||||
|
|
||||||
$ py.test -v -s test_module.py
|
$ pytest -v -s test_module.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 -- $PYTHON_PREFIX/bin/python3.5
|
||||||
cachedir: .cache
|
cachedir: .cache
|
||||||
|
@ -736,7 +736,7 @@ will be required for the execution of each test method, just as if
|
||||||
you specified a "cleandir" function argument to each of them. Let's run it
|
you specified a "cleandir" function argument to each of them. Let's run it
|
||||||
to verify our fixture is activated and the tests pass::
|
to verify our fixture is activated and the tests pass::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
..
|
..
|
||||||
2 passed in 0.12 seconds
|
2 passed in 0.12 seconds
|
||||||
|
|
||||||
|
@ -817,7 +817,7 @@ class-level ``usefixtures`` decorator.
|
||||||
|
|
||||||
If we run it, we get two passing tests::
|
If we run it, we get two passing tests::
|
||||||
|
|
||||||
$ py.test -q
|
$ pytest -q
|
||||||
..
|
..
|
||||||
2 passed in 0.12 seconds
|
2 passed in 0.12 seconds
|
||||||
|
|
||||||
|
|
|
@ -180,9 +180,9 @@ and obsolete many prior uses of pytest hooks.
|
||||||
funcargs/fixture discovery now happens at collection time
|
funcargs/fixture discovery now happens at collection time
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
pytest-2.3 takes care to discover fixture/funcarg factories
|
Since pytest-2.3, discovery of fixture/funcarg factories are taken care of
|
||||||
at collection time. This is more efficient especially for large test suites.
|
at collection time. This is more efficient especially for large test suites.
|
||||||
Moreover, a call to "py.test --collect-only" should be able to in the future
|
Moreover, a call to "pytest --collect-only" should be able to in the future
|
||||||
show a lot of setup-information and thus presents a nice method to get an
|
show a lot of setup-information and thus presents a nice method to get an
|
||||||
overview of fixture management in your project.
|
overview of fixture management in your project.
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ Installation options::
|
||||||
|
|
||||||
To check your installation has installed the correct version::
|
To check your installation has installed the correct version::
|
||||||
|
|
||||||
$ py.test --version
|
$ pytest --version
|
||||||
This is pytest version 2.9.2, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
This is pytest version 2.9.2, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py
|
||||||
|
|
||||||
If you get an error checkout :ref:`installation issues`.
|
If you get an error checkout :ref:`installation issues`.
|
||||||
|
@ -47,7 +47,7 @@ Let's create a first test file with a simple test function::
|
||||||
|
|
||||||
That's it. You can execute the test function now::
|
That's it. You can execute the test function now::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -102,7 +102,7 @@ use the ``raises`` helper::
|
||||||
|
|
||||||
Running it with, this time in "quiet" reporting mode::
|
Running it with, this time in "quiet" reporting mode::
|
||||||
|
|
||||||
$ py.test -q test_sysexit.py
|
$ pytest -q test_sysexit.py
|
||||||
.
|
.
|
||||||
1 passed in 0.12 seconds
|
1 passed in 0.12 seconds
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ The two tests are found because of the standard :ref:`test discovery`.
|
||||||
There is no need to subclass anything. We can simply
|
There is no need to subclass anything. We can simply
|
||||||
run the module by passing its filename::
|
run the module by passing its filename::
|
||||||
|
|
||||||
$ py.test -q test_class.py
|
$ pytest -q test_class.py
|
||||||
.F
|
.F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ TestClass.test_two ________
|
_______ TestClass.test_two ________
|
||||||
|
@ -163,7 +163,7 @@ We list the name ``tmpdir`` in the test function signature and
|
||||||
``pytest`` will lookup and call a fixture factory to create the resource
|
``pytest`` will lookup and call a fixture factory to create the resource
|
||||||
before performing the test function call. Let's just run it::
|
before performing the test function call. Let's just run it::
|
||||||
|
|
||||||
$ py.test -q test_tmpdir.py
|
$ pytest -q test_tmpdir.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_needsfiles ________
|
_______ test_needsfiles ________
|
||||||
|
@ -185,7 +185,7 @@ was created. More info at :ref:`tmpdir handling`.
|
||||||
|
|
||||||
You can find out what kind of builtin :ref:`fixtures` exist by typing::
|
You can find out what kind of builtin :ref:`fixtures` exist by typing::
|
||||||
|
|
||||||
py.test --fixtures # shows builtin and custom fixtures
|
pytest --fixtures # shows builtin and custom fixtures
|
||||||
|
|
||||||
Where to go next
|
Where to go next
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
@ -213,12 +213,12 @@ easy_install or pip not found?
|
||||||
Install `setuptools`_ to get ``easy_install`` which allows to install
|
Install `setuptools`_ to get ``easy_install`` which allows to install
|
||||||
``.egg`` binary format packages in addition to source-based ones.
|
``.egg`` binary format packages in addition to source-based ones.
|
||||||
|
|
||||||
py.test not found on Windows despite installation?
|
pytest not found on Windows despite installation?
|
||||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
|
.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
|
||||||
|
|
||||||
- **Windows**: If "easy_install" or "py.test" are not found
|
- **Windows**: If "easy_install" or "pytest" are not found
|
||||||
you need to add the Python script path to your ``PATH``, see here:
|
you need to add the Python script path to your ``PATH``, see here:
|
||||||
`Python for Windows`_. You may alternatively use an `ActivePython install`_
|
`Python for Windows`_. You may alternatively use an `ActivePython install`_
|
||||||
which does this for you automatically.
|
which does this for you automatically.
|
||||||
|
@ -228,8 +228,8 @@ py.test not found on Windows despite installation?
|
||||||
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
|
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
|
||||||
|
|
||||||
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
|
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
|
||||||
so ``py.test`` will not work correctly. You may install py.test on
|
so ``pytest`` will not work correctly. You may install pytest on
|
||||||
CPython and type ``py.test --genscript=mytest`` and then use
|
CPython and type ``pytest --genscript=mytest`` and then use
|
||||||
``jython mytest`` to run your tests with Jython using ``pytest``.
|
``jython mytest`` to run your tests with Jython using ``pytest``.
|
||||||
|
|
||||||
:ref:`examples` for more complex examples
|
:ref:`examples` for more complex examples
|
||||||
|
|
|
@ -72,17 +72,17 @@ Important notes relating to both schemes:
|
||||||
|
|
||||||
- With inlined tests you might put ``__init__.py`` into test
|
- With inlined tests you might put ``__init__.py`` into test
|
||||||
directories and make them installable as part of your application.
|
directories and make them installable as part of your application.
|
||||||
Using the ``py.test --pyargs mypkg`` invocation pytest will
|
Using the ``pytest --pyargs mypkg`` invocation pytest will
|
||||||
discover where mypkg is installed and collect tests from there.
|
discover where mypkg is installed and collect tests from there.
|
||||||
With the "external" test you can still distribute tests but they
|
With the "external" test you can still distribute tests but they
|
||||||
will not be installed or become importable.
|
will not be installed or become importable.
|
||||||
|
|
||||||
Typically you can run tests by pointing to test directories or modules::
|
Typically you can run tests by pointing to test directories or modules::
|
||||||
|
|
||||||
py.test tests/test_app.py # for external test dirs
|
pytest tests/test_app.py # for external test dirs
|
||||||
py.test mypkg/test/test_app.py # for inlined test dirs
|
pytest mypkg/test/test_app.py # for inlined test dirs
|
||||||
py.test mypkg # run tests in all below test directories
|
pytest mypkg # run tests in all below test directories
|
||||||
py.test # run all tests below current dir
|
pytest # run all tests below current dir
|
||||||
...
|
...
|
||||||
|
|
||||||
Because of the above ``editable install`` mode you can change your
|
Because of the above ``editable install`` mode you can change your
|
||||||
|
@ -193,7 +193,7 @@ If you now type::
|
||||||
this will execute your tests using ``pytest-runner``. As this is a
|
this will execute your tests using ``pytest-runner``. As this is a
|
||||||
standalone version of ``pytest`` no prior installation whatsoever is
|
standalone version of ``pytest`` no prior installation whatsoever is
|
||||||
required for calling the test command. You can also pass additional
|
required for calling the test command. You can also pass additional
|
||||||
arguments to py.test such as your test directory or other
|
arguments to pytest such as your test directory or other
|
||||||
options using ``--addopts``.
|
options using ``--addopts``.
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ your own setuptools Test command for invoking pytest.
|
||||||
|
|
||||||
|
|
||||||
class PyTest(TestCommand):
|
class PyTest(TestCommand):
|
||||||
user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")]
|
user_options = [('pytest-args=', 'a', "Arguments to pass to pytest")]
|
||||||
|
|
||||||
def initialize_options(self):
|
def initialize_options(self):
|
||||||
TestCommand.initialize_options(self)
|
TestCommand.initialize_options(self)
|
||||||
|
@ -240,7 +240,7 @@ using the ``--pytest-args`` or ``-a`` command-line option. For example::
|
||||||
|
|
||||||
python setup.py test -a "--durations=5"
|
python setup.py test -a "--durations=5"
|
||||||
|
|
||||||
is equivalent to running ``py.test --durations=5``.
|
is equivalent to running ``pytest --durations=5``.
|
||||||
|
|
||||||
|
|
||||||
.. _standalone:
|
.. _standalone:
|
||||||
|
@ -268,7 +268,7 @@ If you are a maintainer or application developer and want people
|
||||||
who don't deal with python much to easily run tests you may generate
|
who don't deal with python much to easily run tests you may generate
|
||||||
a standalone ``pytest`` script::
|
a standalone ``pytest`` script::
|
||||||
|
|
||||||
py.test --genscript=runtests.py
|
pytest --genscript=runtests.py
|
||||||
|
|
||||||
This generates a ``runtests.py`` script which is a fully functional basic
|
This generates a ``runtests.py`` script which is a fully functional basic
|
||||||
``pytest`` script, running unchanged under Python2 and Python3.
|
``pytest`` script, running unchanged under Python2 and Python3.
|
||||||
|
|
|
@ -13,7 +13,7 @@ Usage
|
||||||
After :ref:`installation` type::
|
After :ref:`installation` type::
|
||||||
|
|
||||||
python setup.py develop # make sure tests can import our package
|
python setup.py develop # make sure tests can import our package
|
||||||
py.test # instead of 'nosetests'
|
pytest # instead of 'nosetests'
|
||||||
|
|
||||||
and you should be able to run your nose style tests and
|
and you should be able to run your nose style tests and
|
||||||
make use of pytest's capabilities.
|
make use of pytest's capabilities.
|
||||||
|
|
|
@ -53,7 +53,7 @@ Here, the ``@parametrize`` decorator defines three different ``(test_input,expec
|
||||||
tuples so that the ``test_eval`` function will run three times using
|
tuples so that the ``test_eval`` function will run three times using
|
||||||
them in turn::
|
them in turn::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -101,7 +101,7 @@ for example with the builtin ``mark.xfail``::
|
||||||
|
|
||||||
Let's run this::
|
Let's run this::
|
||||||
|
|
||||||
$ py.test
|
$ pytest
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -171,13 +171,13 @@ command line option and the parametrization of our test function::
|
||||||
|
|
||||||
If we now pass two stringinput values, our test will run twice::
|
If we now pass two stringinput values, our test will run twice::
|
||||||
|
|
||||||
$ py.test -q --stringinput="hello" --stringinput="world" test_strings.py
|
$ pytest -q --stringinput="hello" --stringinput="world" test_strings.py
|
||||||
..
|
..
|
||||||
2 passed in 0.12 seconds
|
2 passed in 0.12 seconds
|
||||||
|
|
||||||
Let's also run with a stringinput that will lead to a failing test::
|
Let's also run with a stringinput that will lead to a failing test::
|
||||||
|
|
||||||
$ py.test -q --stringinput="!" test_strings.py
|
$ pytest -q --stringinput="!" test_strings.py
|
||||||
F
|
F
|
||||||
======= FAILURES ========
|
======= FAILURES ========
|
||||||
_______ test_valid_string[!] ________
|
_______ test_valid_string[!] ________
|
||||||
|
@ -198,7 +198,7 @@ If you don't specify a stringinput it will be skipped because
|
||||||
``metafunc.parametrize()`` will be called with an empty parameter
|
``metafunc.parametrize()`` will be called with an empty parameter
|
||||||
list::
|
list::
|
||||||
|
|
||||||
$ py.test -q -rs test_strings.py
|
$ pytest -q -rs test_strings.py
|
||||||
s
|
s
|
||||||
======= short test summary info ========
|
======= short test summary info ========
|
||||||
SKIP [1] test_strings.py:1: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
|
SKIP [1] test_strings.py:1: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
|
||||||
|
|
|
@ -59,7 +59,7 @@ Here is a little annotated list for some popular plugins:
|
||||||
a plugin to run javascript unittests in live browsers.
|
a plugin to run javascript unittests in live browsers.
|
||||||
|
|
||||||
To see a complete list of all plugins with their latest testing
|
To see a complete list of all plugins with their latest testing
|
||||||
status against different py.test and Python versions, please visit
|
status against different pytest and Python versions, please visit
|
||||||
`plugincompat <http://plugincompat.herokuapp.com/>`_.
|
`plugincompat <http://plugincompat.herokuapp.com/>`_.
|
||||||
|
|
||||||
You may also discover more plugins through a `pytest- pypi.python.org search`_.
|
You may also discover more plugins through a `pytest- pypi.python.org search`_.
|
||||||
|
@ -90,7 +90,7 @@ Finding out which plugins are active
|
||||||
If you want to find out which plugins are active in your
|
If you want to find out which plugins are active in your
|
||||||
environment you can type::
|
environment you can type::
|
||||||
|
|
||||||
py.test --trace-config
|
pytest --trace-config
|
||||||
|
|
||||||
and will get an extended test header which shows activated plugins
|
and will get an extended test header which shows activated plugins
|
||||||
and their names. It will also print local plugins aka
|
and their names. It will also print local plugins aka
|
||||||
|
@ -103,7 +103,7 @@ Deactivating / unregistering a plugin by name
|
||||||
|
|
||||||
You can prevent plugins from loading or unregister them::
|
You can prevent plugins from loading or unregister them::
|
||||||
|
|
||||||
py.test -p no:NAME
|
pytest -p no:NAME
|
||||||
|
|
||||||
This means that any subsequent try to activate/load the named
|
This means that any subsequent try to activate/load the named
|
||||||
plugin will not work.
|
plugin will not work.
|
||||||
|
|
|
@ -19,7 +19,7 @@ information about skipped/xfailed tests is not shown by default to avoid
|
||||||
cluttering the output. You can use the ``-r`` option to see details
|
cluttering the output. You can use the ``-r`` option to see details
|
||||||
corresponding to the "short" letters shown in the test progress::
|
corresponding to the "short" letters shown in the test progress::
|
||||||
|
|
||||||
py.test -rxs # show extra info on skips and xfails
|
pytest -rxs # show extra info on skips and xfails
|
||||||
|
|
||||||
(See :ref:`how to change command line options defaults`)
|
(See :ref:`how to change command line options defaults`)
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ Here is a simple test file with the several usages:
|
||||||
|
|
||||||
Running it with the report-on-xfail option gives this output::
|
Running it with the report-on-xfail option gives this output::
|
||||||
|
|
||||||
example $ py.test -rx xfail_demo.py
|
example $ pytest -rx xfail_demo.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR/example, inifile:
|
rootdir: $REGENDOC_TMPDIR/example, inifile:
|
||||||
|
@ -368,6 +368,6 @@ The equivalent with "boolean conditions" is::
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
You cannot use ``pytest.config.getvalue()`` in code
|
You cannot use ``pytest.config.getvalue()`` in code
|
||||||
imported before py.test's argument parsing takes place. For example,
|
imported before pytest's argument parsing takes place. For example,
|
||||||
``conftest.py`` files are imported before command line parsing and thus
|
``conftest.py`` files are imported before command line parsing and thus
|
||||||
``config.getvalue()`` will not execute correctly.
|
``config.getvalue()`` will not execute correctly.
|
||||||
|
|
|
@ -21,7 +21,7 @@ but note that project specific settings will be considered
|
||||||
first. There is a flag that helps you debugging your
|
first. There is a flag that helps you debugging your
|
||||||
conftest.py configurations::
|
conftest.py configurations::
|
||||||
|
|
||||||
py.test --trace-config
|
pytest --trace-config
|
||||||
|
|
||||||
|
|
||||||
customizing the collecting and running process
|
customizing the collecting and running process
|
||||||
|
|
|
@ -5,7 +5,7 @@ Mission
|
||||||
``pytest`` strives to make testing a fun and no-boilerplate effort.
|
``pytest`` strives to make testing a fun and no-boilerplate effort.
|
||||||
|
|
||||||
The tool is distributed as a `pytest` package. Its project independent
|
The tool is distributed as a `pytest` package. Its project independent
|
||||||
``py.test`` command line tool helps you to:
|
``pytest`` command line tool helps you to:
|
||||||
|
|
||||||
* rapidly collect and run tests
|
* rapidly collect and run tests
|
||||||
* run unit- or doctests, functional or integration tests
|
* run unit- or doctests, functional or integration tests
|
||||||
|
|
|
@ -53,7 +53,7 @@ subprocesses.
|
||||||
|
|
||||||
Running centralised testing::
|
Running centralised testing::
|
||||||
|
|
||||||
py.test --cov myproj tests/
|
pytest --cov myproj tests/
|
||||||
|
|
||||||
Shows a terminal report::
|
Shows a terminal report::
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ file system. Each slave will have it's subprocesses measured.
|
||||||
|
|
||||||
Running distributed testing with dist mode set to load::
|
Running distributed testing with dist mode set to load::
|
||||||
|
|
||||||
py.test --cov myproj -n 2 tests/
|
pytest --cov myproj -n 2 tests/
|
||||||
|
|
||||||
Shows a terminal report::
|
Shows a terminal report::
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ Shows a terminal report::
|
||||||
|
|
||||||
Again but spread over different hosts and different directories::
|
Again but spread over different hosts and different directories::
|
||||||
|
|
||||||
py.test --cov myproj --dist load
|
pytest --cov myproj --dist load
|
||||||
--tx ssh=memedough@host1//chdir=testenv1
|
--tx ssh=memedough@host1//chdir=testenv1
|
||||||
--tx ssh=memedough@host2//chdir=/tmp/testenv2//python=/tmp/env1/bin/python
|
--tx ssh=memedough@host2//chdir=/tmp/testenv2//python=/tmp/env1/bin/python
|
||||||
--rsyncdir myproj --rsyncdir tests --rsync examples
|
--rsyncdir myproj --rsyncdir tests --rsync examples
|
||||||
|
@ -119,7 +119,7 @@ environments.
|
||||||
|
|
||||||
Running distributed testing with dist mode set to each::
|
Running distributed testing with dist mode set to each::
|
||||||
|
|
||||||
py.test --cov myproj --dist each
|
pytest --cov myproj --dist each
|
||||||
--tx popen//chdir=/tmp/testenv3//python=/usr/local/python27/bin/python
|
--tx popen//chdir=/tmp/testenv3//python=/usr/local/python27/bin/python
|
||||||
--tx ssh=memedough@host2//chdir=/tmp/testenv4//python=/tmp/env2/bin/python
|
--tx ssh=memedough@host2//chdir=/tmp/testenv4//python=/tmp/env2/bin/python
|
||||||
--rsyncdir myproj --rsyncdir tests --rsync examples
|
--rsyncdir myproj --rsyncdir tests --rsync examples
|
||||||
|
@ -149,7 +149,7 @@ annotated source code.
|
||||||
|
|
||||||
The terminal report without line numbers (default)::
|
The terminal report without line numbers (default)::
|
||||||
|
|
||||||
py.test --cov-report term --cov myproj tests/
|
pytest --cov-report term --cov myproj tests/
|
||||||
|
|
||||||
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
Name Stmts Miss Cover
|
Name Stmts Miss Cover
|
||||||
|
@ -163,7 +163,7 @@ The terminal report without line numbers (default)::
|
||||||
|
|
||||||
The terminal report with line numbers::
|
The terminal report with line numbers::
|
||||||
|
|
||||||
py.test --cov-report term-missing --cov myproj tests/
|
pytest --cov-report term-missing --cov myproj tests/
|
||||||
|
|
||||||
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
Name Stmts Miss Cover Missing
|
Name Stmts Miss Cover Missing
|
||||||
|
@ -178,7 +178,7 @@ The terminal report with line numbers::
|
||||||
The remaining three reports output to files without showing anything on the terminal (useful for
|
The remaining three reports output to files without showing anything on the terminal (useful for
|
||||||
when the output is going to a continuous integration server)::
|
when the output is going to a continuous integration server)::
|
||||||
|
|
||||||
py.test --cov-report html --cov-report xml --cov-report annotate --cov myproj tests/
|
pytest --cov-report html --cov-report xml --cov-report annotate --cov myproj tests/
|
||||||
|
|
||||||
|
|
||||||
Coverage Data File
|
Coverage Data File
|
||||||
|
|
|
@ -26,7 +26,7 @@ Usage
|
||||||
|
|
||||||
To get full test coverage reports for a particular package type::
|
To get full test coverage reports for a particular package type::
|
||||||
|
|
||||||
py.test --cover-report=report
|
pytest --cover-report=report
|
||||||
|
|
||||||
command line options
|
command line options
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
@ -24,7 +24,7 @@ Usage
|
||||||
|
|
||||||
After installation you can simply type::
|
After installation you can simply type::
|
||||||
|
|
||||||
py.test --figleaf [...]
|
pytest --figleaf [...]
|
||||||
|
|
||||||
to enable figleaf coverage in your test run. A default ".figleaf" data file
|
to enable figleaf coverage in your test run. A default ".figleaf" data file
|
||||||
and "html" directory will be created. You can use command line options
|
and "html" directory will be created. You can use command line options
|
||||||
|
|
|
@ -14,7 +14,7 @@ Usage
|
||||||
|
|
||||||
type::
|
type::
|
||||||
|
|
||||||
py.test # instead of 'nosetests'
|
pytest # instead of 'nosetests'
|
||||||
|
|
||||||
and you should be able to run nose style tests and at the same
|
and you should be able to run nose style tests and at the same
|
||||||
time can make full use of pytest's capabilities.
|
time can make full use of pytest's capabilities.
|
||||||
|
@ -38,7 +38,7 @@ Unsupported idioms / issues
|
||||||
|
|
||||||
If you find other issues or have suggestions please run::
|
If you find other issues or have suggestions please run::
|
||||||
|
|
||||||
py.test --pastebin=all
|
pytest --pastebin=all
|
||||||
|
|
||||||
and send the resulting URL to a ``pytest`` contact channel,
|
and send the resulting URL to a ``pytest`` contact channel,
|
||||||
at best to the mailing list.
|
at best to the mailing list.
|
||||||
|
|
|
@ -36,7 +36,7 @@ Speed up test runs by sending tests to multiple CPUs
|
||||||
|
|
||||||
To send tests to multiple CPUs, type::
|
To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
py.test -n NUM
|
pytest -n NUM
|
||||||
|
|
||||||
Especially for longer running tests or tests requiring
|
Especially for longer running tests or tests requiring
|
||||||
a lot of IO this can lead to considerable speed ups.
|
a lot of IO this can lead to considerable speed ups.
|
||||||
|
@ -47,7 +47,7 @@ Running tests in a Python subprocess
|
||||||
|
|
||||||
To instantiate a python2.4 sub process and send tests to it, you may type::
|
To instantiate a python2.4 sub process and send tests to it, you may type::
|
||||||
|
|
||||||
py.test -d --tx popen//python=python2.4
|
pytest -d --tx popen//python=python2.4
|
||||||
|
|
||||||
This will start a subprocess which is run with the "python2.4"
|
This will start a subprocess which is run with the "python2.4"
|
||||||
Python interpreter, found in your system binary lookup path.
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
@ -68,7 +68,7 @@ tests that you can successfully run locally. And you
|
||||||
have a ssh-reachable machine ``myhost``. Then
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
you can ad-hoc distribute your tests by typing::
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
pytest -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
This will synchronize your ``mypkg`` package directory
|
This will synchronize your ``mypkg`` package directory
|
||||||
to an remote ssh account and then locally collect tests
|
to an remote ssh account and then locally collect tests
|
||||||
|
@ -97,7 +97,7 @@ It will tell you that it starts listening on the default
|
||||||
port. You can now on your home machine specify this
|
port. You can now on your home machine specify this
|
||||||
new socket host with something like this::
|
new socket host with something like this::
|
||||||
|
|
||||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
pytest -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
|
||||||
.. _`atonce`:
|
.. _`atonce`:
|
||||||
|
@ -107,7 +107,7 @@ Running tests on many platforms at once
|
||||||
|
|
||||||
The basic command to run tests on multiple platforms is::
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
py.test --dist=each --tx=spec1 --tx=spec2
|
pytest --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
If you specify a windows host, an OSX host and a Linux
|
If you specify a windows host, an OSX host and a Linux
|
||||||
environment this command will send each tests to all
|
environment this command will send each tests to all
|
||||||
|
|
|
@ -27,7 +27,7 @@ and more. Here is an example test usage::
|
||||||
Running this would result in a passed test except for the last
|
Running this would result in a passed test except for the last
|
||||||
``assert 0`` line which we use to look at values::
|
``assert 0`` line which we use to look at values::
|
||||||
|
|
||||||
$ py.test test_tmpdir.py
|
$ pytest test_tmpdir.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -100,7 +100,7 @@ than 3 temporary directories will be removed.
|
||||||
|
|
||||||
You can override the default temporary directory setting like this::
|
You can override the default temporary directory setting like this::
|
||||||
|
|
||||||
py.test --basetemp=mydir
|
pytest --basetemp=mydir
|
||||||
|
|
||||||
When distributing tests on the local machine, ``pytest`` takes care to
|
When distributing tests on the local machine, ``pytest`` takes care to
|
||||||
configure a basetemp directory for the sub processes such that all temporary
|
configure a basetemp directory for the sub processes such that all temporary
|
||||||
|
|
|
@ -21,7 +21,7 @@ Usage
|
||||||
|
|
||||||
After :ref:`installation` type::
|
After :ref:`installation` type::
|
||||||
|
|
||||||
py.test
|
pytest
|
||||||
|
|
||||||
and you should be able to run your unittest-style tests if they
|
and you should be able to run your unittest-style tests if they
|
||||||
are contained in ``test_*`` modules. If that works for you then
|
are contained in ``test_*`` modules. If that works for you then
|
||||||
|
@ -86,7 +86,7 @@ the pytest fixture function ``db_class`` is called once per class.
|
||||||
Due to the deliberately failing assert statements, we can take a look at
|
Due to the deliberately failing assert statements, we can take a look at
|
||||||
the ``self.db`` values in the traceback::
|
the ``self.db`` values in the traceback::
|
||||||
|
|
||||||
$ py.test test_unittest_db.py
|
$ pytest test_unittest_db.py
|
||||||
======= test session starts ========
|
======= test session starts ========
|
||||||
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
platform linux -- Python 3.5.1, pytest-2.9.2, py-1.4.31, pluggy-0.3.1
|
||||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||||
|
@ -161,7 +161,7 @@ on the class like in the previous example.
|
||||||
|
|
||||||
Running this test module ...::
|
Running this test module ...::
|
||||||
|
|
||||||
$ py.test -q test_unittest_cleandir.py
|
$ pytest -q test_unittest_cleandir.py
|
||||||
.
|
.
|
||||||
1 passed in 0.12 seconds
|
1 passed in 0.12 seconds
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ You can invoke testing through the Python interpreter from the command line::
|
||||||
|
|
||||||
python -m pytest [...]
|
python -m pytest [...]
|
||||||
|
|
||||||
This is equivalent to invoking the command line script ``py.test [...]``
|
This is equivalent to invoking the command line script ``pytest [...]``
|
||||||
directly.
|
directly.
|
||||||
|
|
||||||
Getting help on version, option names, environment variables
|
Getting help on version, option names, environment variables
|
||||||
|
@ -24,9 +24,9 @@ Getting help on version, option names, environment variables
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
py.test --version # shows where pytest was imported from
|
pytest --version # shows where pytest was imported from
|
||||||
py.test --fixtures # show available builtin function arguments
|
pytest --fixtures # show available builtin function arguments
|
||||||
py.test -h | --help # show help on command line and config file options
|
pytest -h | --help # show help on command line and config file options
|
||||||
|
|
||||||
|
|
||||||
Stopping after the first (or N) failures
|
Stopping after the first (or N) failures
|
||||||
|
@ -34,45 +34,45 @@ Stopping after the first (or N) failures
|
||||||
|
|
||||||
To stop the testing process after the first (N) failures::
|
To stop the testing process after the first (N) failures::
|
||||||
|
|
||||||
py.test -x # stop after first failure
|
pytest -x # stop after first failure
|
||||||
py.test --maxfail=2 # stop after two failures
|
pytest --maxfail=2 # stop after two failures
|
||||||
|
|
||||||
Specifying tests / selecting tests
|
Specifying tests / selecting tests
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
Several test run options::
|
Several test run options::
|
||||||
|
|
||||||
py.test test_mod.py # run tests in module
|
pytest test_mod.py # run tests in module
|
||||||
py.test somepath # run all tests below somepath
|
pytest somepath # run all tests below somepath
|
||||||
py.test -k stringexpr # only run tests with names that match the
|
pytest -k stringexpr # only run tests with names that match the
|
||||||
# "string expression", e.g. "MyClass and not method"
|
# "string expression", e.g. "MyClass and not method"
|
||||||
# will select TestMyClass.test_something
|
# will select TestMyClass.test_something
|
||||||
# but not TestMyClass.test_method_simple
|
# but not TestMyClass.test_method_simple
|
||||||
py.test test_mod.py::test_func # only run tests that match the "node ID",
|
pytest test_mod.py::test_func # only run tests that match the "node ID",
|
||||||
# e.g "test_mod.py::test_func" will select
|
# e.g "test_mod.py::test_func" will select
|
||||||
# only test_func in test_mod.py
|
# only test_func in test_mod.py
|
||||||
py.test test_mod.py::TestClass::test_method # run a single method in
|
pytest test_mod.py::TestClass::test_method # run a single method in
|
||||||
# a single class
|
# a single class
|
||||||
|
|
||||||
Import 'pkg' and use its filesystem location to find and run tests::
|
Import 'pkg' and use its filesystem location to find and run tests::
|
||||||
|
|
||||||
py.test --pyargs pkg # run all tests found below directory of pkg
|
pytest --pyargs pkg # run all tests found below directory of pkg
|
||||||
|
|
||||||
Modifying Python traceback printing
|
Modifying Python traceback printing
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
Examples for modifying traceback printing::
|
Examples for modifying traceback printing::
|
||||||
|
|
||||||
py.test --showlocals # show local variables in tracebacks
|
pytest --showlocals # show local variables in tracebacks
|
||||||
py.test -l # show local variables (shortcut)
|
pytest -l # show local variables (shortcut)
|
||||||
|
|
||||||
py.test --tb=auto # (default) 'long' tracebacks for the first and last
|
pytest --tb=auto # (default) 'long' tracebacks for the first and last
|
||||||
# entry, but 'short' style for the other entries
|
# entry, but 'short' style for the other entries
|
||||||
py.test --tb=long # exhaustive, informative traceback formatting
|
pytest --tb=long # exhaustive, informative traceback formatting
|
||||||
py.test --tb=short # shorter traceback format
|
pytest --tb=short # shorter traceback format
|
||||||
py.test --tb=line # only one line per failure
|
pytest --tb=line # only one line per failure
|
||||||
py.test --tb=native # Python standard library formatting
|
pytest --tb=native # Python standard library formatting
|
||||||
py.test --tb=no # no traceback at all
|
pytest --tb=no # no traceback at all
|
||||||
|
|
||||||
The ``--full-trace`` causes very long traces to be printed on error (longer
|
The ``--full-trace`` causes very long traces to be printed on error (longer
|
||||||
than ``--tb=long``). It also ensures that a stack trace is printed on
|
than ``--tb=long``). It also ensures that a stack trace is printed on
|
||||||
|
@ -90,14 +90,14 @@ Dropping to PDB_ (Python Debugger) on failures
|
||||||
Python comes with a builtin Python debugger called PDB_. ``pytest``
|
Python comes with a builtin Python debugger called PDB_. ``pytest``
|
||||||
allows one to drop into the PDB_ prompt via a command line option::
|
allows one to drop into the PDB_ prompt via a command line option::
|
||||||
|
|
||||||
py.test --pdb
|
pytest --pdb
|
||||||
|
|
||||||
This will invoke the Python debugger on every failure. Often you might
|
This will invoke the Python debugger on every failure. Often you might
|
||||||
only want to do this for the first failing test to understand a certain
|
only want to do this for the first failing test to understand a certain
|
||||||
failure situation::
|
failure situation::
|
||||||
|
|
||||||
py.test -x --pdb # drop to PDB on first failure, then end test session
|
pytest -x --pdb # drop to PDB on first failure, then end test session
|
||||||
py.test --pdb --maxfail=3 # drop to PDB for first three failures
|
pytest --pdb --maxfail=3 # drop to PDB for first three failures
|
||||||
|
|
||||||
Note that on any failure the exception information is stored on
|
Note that on any failure the exception information is stored on
|
||||||
``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
|
``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
|
||||||
|
@ -125,7 +125,7 @@ can use a helper::
|
||||||
.. versionadded: 2.0.0
|
.. versionadded: 2.0.0
|
||||||
|
|
||||||
Prior to pytest version 2.0.0 you could only enter PDB_ tracing if you disabled
|
Prior to pytest version 2.0.0 you could only enter PDB_ tracing if you disabled
|
||||||
capturing on the command line via ``py.test -s``. In later versions, pytest
|
capturing on the command line via ``pytest -s``. In later versions, pytest
|
||||||
automatically disables its output capture when you enter PDB_ tracing:
|
automatically disables its output capture when you enter PDB_ tracing:
|
||||||
|
|
||||||
* Output capture in other tests is not affected.
|
* Output capture in other tests is not affected.
|
||||||
|
@ -141,7 +141,7 @@ automatically disables its output capture when you enter PDB_ tracing:
|
||||||
Since pytest version 2.4.0 you can also use the native Python
|
Since pytest version 2.4.0 you can also use the native Python
|
||||||
``import pdb;pdb.set_trace()`` call to enter PDB_ tracing without having to use
|
``import pdb;pdb.set_trace()`` call to enter PDB_ tracing without having to use
|
||||||
the ``pytest.set_trace()`` wrapper or explicitly disable pytest's output
|
the ``pytest.set_trace()`` wrapper or explicitly disable pytest's output
|
||||||
capturing via ``py.test -s``.
|
capturing via ``pytest -s``.
|
||||||
|
|
||||||
.. _durations:
|
.. _durations:
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ Profiling test execution duration
|
||||||
|
|
||||||
To get a list of the slowest 10 test durations::
|
To get a list of the slowest 10 test durations::
|
||||||
|
|
||||||
py.test --durations=10
|
pytest --durations=10
|
||||||
|
|
||||||
|
|
||||||
Creating JUnitXML format files
|
Creating JUnitXML format files
|
||||||
|
@ -161,7 +161,7 @@ Creating JUnitXML format files
|
||||||
To create result files which can be read by Jenkins_ or other Continuous
|
To create result files which can be read by Jenkins_ or other Continuous
|
||||||
integration servers, use this invocation::
|
integration servers, use this invocation::
|
||||||
|
|
||||||
py.test --junitxml=path
|
pytest --junitxml=path
|
||||||
|
|
||||||
to create an XML file at ``path``.
|
to create an XML file at ``path``.
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ Creating resultlog format files
|
||||||
|
|
||||||
To create plain-text machine-readable result files you can issue::
|
To create plain-text machine-readable result files you can issue::
|
||||||
|
|
||||||
py.test --resultlog=path
|
pytest --resultlog=path
|
||||||
|
|
||||||
and look at the content at the ``path`` location. Such files are used e.g.
|
and look at the content at the ``path`` location. Such files are used e.g.
|
||||||
by the `PyPy-test`_ web page to show test results over several revisions.
|
by the `PyPy-test`_ web page to show test results over several revisions.
|
||||||
|
@ -266,7 +266,7 @@ Sending test report to online pastebin service
|
||||||
|
|
||||||
**Creating a URL for each test failure**::
|
**Creating a URL for each test failure**::
|
||||||
|
|
||||||
py.test --pastebin=failed
|
pytest --pastebin=failed
|
||||||
|
|
||||||
This will submit test run information to a remote Paste service and
|
This will submit test run information to a remote Paste service and
|
||||||
provide a URL for each failure. You may select tests as usual or add
|
provide a URL for each failure. You may select tests as usual or add
|
||||||
|
@ -274,7 +274,7 @@ for example ``-x`` if you only want to send one particular failure.
|
||||||
|
|
||||||
**Creating a URL for a whole test session log**::
|
**Creating a URL for a whole test session log**::
|
||||||
|
|
||||||
py.test --pastebin=all
|
pytest --pastebin=all
|
||||||
|
|
||||||
Currently only pasting to the http://bpaste.net service is implemented.
|
Currently only pasting to the http://bpaste.net service is implemented.
|
||||||
|
|
||||||
|
@ -285,9 +285,9 @@ To disable loading specific plugins at invocation time, use the ``-p`` option
|
||||||
together with the prefix ``no:``.
|
together with the prefix ``no:``.
|
||||||
|
|
||||||
Example: to disable loading the plugin ``doctest``, which is responsible for
|
Example: to disable loading the plugin ``doctest``, which is responsible for
|
||||||
executing doctest tests from text files, invoke py.test like this::
|
executing doctest tests from text files, invoke pytest like this::
|
||||||
|
|
||||||
py.test -p no:doctest
|
pytest -p no:doctest
|
||||||
|
|
||||||
.. _`pytest.main-usage`:
|
.. _`pytest.main-usage`:
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ You can invoke ``pytest`` from Python code directly::
|
||||||
|
|
||||||
pytest.main()
|
pytest.main()
|
||||||
|
|
||||||
this acts as if you would call "py.test" from the command line.
|
this acts as if you would call "pytest" from the command line.
|
||||||
It will not raise ``SystemExit`` but return the exitcode instead.
|
It will not raise ``SystemExit`` but return the exitcode instead.
|
||||||
You can pass in options and arguments::
|
You can pass in options and arguments::
|
||||||
|
|
||||||
|
|
|
@ -87,8 +87,8 @@ sub directory but not for other directories::
|
||||||
|
|
||||||
Here is how you might run it::
|
Here is how you might run it::
|
||||||
|
|
||||||
py.test test_flat.py # will not show "setting up"
|
pytest test_flat.py # will not show "setting up"
|
||||||
py.test a/test_sub.py # will show "setting up"
|
pytest a/test_sub.py # will show "setting up"
|
||||||
|
|
||||||
.. Note::
|
.. Note::
|
||||||
If you have ``conftest.py`` files which do not reside in a
|
If you have ``conftest.py`` files which do not reside in a
|
||||||
|
|
|
@ -52,7 +52,7 @@ Speed up test runs by sending tests to multiple CPUs
|
||||||
|
|
||||||
To send tests to multiple CPUs, type::
|
To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
py.test -n NUM
|
pytest -n NUM
|
||||||
|
|
||||||
Especially for longer running tests or tests requiring
|
Especially for longer running tests or tests requiring
|
||||||
a lot of I/O this can lead to considerable speed ups.
|
a lot of I/O this can lead to considerable speed ups.
|
||||||
|
@ -63,14 +63,14 @@ Running tests in a Python subprocess
|
||||||
|
|
||||||
To instantiate a Python-2.7 subprocess and send tests to it, you may type::
|
To instantiate a Python-2.7 subprocess and send tests to it, you may type::
|
||||||
|
|
||||||
py.test -d --tx popen//python=python2.7
|
pytest -d --tx popen//python=python2.7
|
||||||
|
|
||||||
This will start a subprocess which is run with the "python2.7"
|
This will start a subprocess which is run with the "python2.7"
|
||||||
Python interpreter, found in your system binary lookup path.
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
|
||||||
If you prefix the --tx option value like this::
|
If you prefix the --tx option value like this::
|
||||||
|
|
||||||
py.test -d --tx 3*popen//python=python2.7
|
pytest -d --tx 3*popen//python=python2.7
|
||||||
|
|
||||||
then three subprocesses would be created and the tests
|
then three subprocesses would be created and the tests
|
||||||
will be distributed to three subprocesses and run simultanously.
|
will be distributed to three subprocesses and run simultanously.
|
||||||
|
@ -84,7 +84,7 @@ Running tests in looponfailing mode
|
||||||
For refactoring a project with a medium or large test suite
|
For refactoring a project with a medium or large test suite
|
||||||
you can use the looponfailing mode. Simply add the ``--f`` option::
|
you can use the looponfailing mode. Simply add the ``--f`` option::
|
||||||
|
|
||||||
py.test -f
|
pytest -f
|
||||||
|
|
||||||
and ``pytest`` will run your tests. Assuming you have failures it will then
|
and ``pytest`` will run your tests. Assuming you have failures it will then
|
||||||
wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
|
wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
|
||||||
|
@ -104,7 +104,7 @@ tests that you can successfully run locally. And you also
|
||||||
have a ssh-reachable machine ``myhost``. Then
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
you can ad-hoc distribute your tests by typing::
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
pytest -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
This will synchronize your ``mypkg`` package directory
|
This will synchronize your ``mypkg`` package directory
|
||||||
with a remote ssh account and then collect and run your
|
with a remote ssh account and then collect and run your
|
||||||
|
@ -135,7 +135,7 @@ It will tell you that it starts listening on the default
|
||||||
port. You can now on your home machine specify this
|
port. You can now on your home machine specify this
|
||||||
new socket host with something like this::
|
new socket host with something like this::
|
||||||
|
|
||||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
pytest -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
|
||||||
.. _`atonce`:
|
.. _`atonce`:
|
||||||
|
@ -145,7 +145,7 @@ Running tests on many platforms at once
|
||||||
|
|
||||||
The basic command to run tests on multiple platforms is::
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
py.test --dist=each --tx=spec1 --tx=spec2
|
pytest --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
If you specify a windows host, an OSX host and a Linux
|
If you specify a windows host, an OSX host and a Linux
|
||||||
environment this command will send each tests to all
|
environment this command will send each tests to all
|
||||||
|
@ -174,7 +174,7 @@ You can also add default environments like this::
|
||||||
|
|
||||||
and then just type::
|
and then just type::
|
||||||
|
|
||||||
py.test --dist=each
|
pytest --dist=each
|
||||||
|
|
||||||
to run tests in each of the environments.
|
to run tests in each of the environments.
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,3 @@
|
||||||
|
|
||||||
Marking functions as ``yield_fixture`` is still supported, but deprecated and should not
|
Marking functions as ``yield_fixture`` is still supported, but deprecated and should not
|
||||||
be used in new code.
|
be used in new code.
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,17 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
cd ../pytest-pep8
|
cd ../pytest-pep8
|
||||||
py.test
|
pytest
|
||||||
cd ../pytest-instafail
|
cd ../pytest-instafail
|
||||||
py.test
|
pytest
|
||||||
cd ../pytest-cache
|
cd ../pytest-cache
|
||||||
py.test
|
pytest
|
||||||
cd ../pytest-xprocess
|
cd ../pytest-xprocess
|
||||||
py.test
|
pytest
|
||||||
#cd ../pytest-cov
|
#cd ../pytest-cov
|
||||||
#py.test
|
#pytest
|
||||||
cd ../pytest-capturelog
|
cd ../pytest-capturelog
|
||||||
py.test
|
pytest
|
||||||
cd ../pytest-xdist
|
cd ../pytest-xdist
|
||||||
py.test
|
pytest
|
||||||
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -91,6 +91,7 @@ def cmdline_entrypoints(versioninfo, platform, basename):
|
||||||
else: # cpython
|
else: # cpython
|
||||||
points = {'py.test-%s.%s' % versioninfo[:2] : target}
|
points = {'py.test-%s.%s' % versioninfo[:2] : target}
|
||||||
points['py.test'] = target
|
points['py.test'] = target
|
||||||
|
points['pytest'] = target
|
||||||
return points
|
return points
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
|
@ -120,7 +122,7 @@ class TestGeneralUsage:
|
||||||
"ImportError while importing test module*",
|
"ImportError while importing test module*",
|
||||||
"'No module named *does_not_work*",
|
"'No module named *does_not_work*",
|
||||||
])
|
])
|
||||||
assert result.ret == 1
|
assert result.ret == 2
|
||||||
|
|
||||||
def test_not_collectable_arguments(self, testdir):
|
def test_not_collectable_arguments(self, testdir):
|
||||||
p1 = testdir.makepyfile("")
|
p1 = testdir.makepyfile("")
|
||||||
|
@ -513,12 +515,11 @@ class TestInvocationVariants:
|
||||||
path = testdir.mkpydir("tpkg")
|
path = testdir.mkpydir("tpkg")
|
||||||
path.join("test_hello.py").write('raise ImportError')
|
path.join("test_hello.py").write('raise ImportError')
|
||||||
|
|
||||||
result = testdir.runpytest("--pyargs", "tpkg.test_hello")
|
result = testdir.runpytest_subprocess("--pyargs", "tpkg.test_hello")
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
# FIXME: It would be more natural to match NOT
|
|
||||||
# "ERROR*file*or*package*not*found*".
|
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*collected 0 items*"
|
"collected*0*items*/*1*errors"
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_cmdline_python_package(self, testdir, monkeypatch):
|
def test_cmdline_python_package(self, testdir, monkeypatch):
|
||||||
|
@ -540,7 +541,7 @@ class TestInvocationVariants:
|
||||||
def join_pythonpath(what):
|
def join_pythonpath(what):
|
||||||
cur = py.std.os.environ.get('PYTHONPATH')
|
cur = py.std.os.environ.get('PYTHONPATH')
|
||||||
if cur:
|
if cur:
|
||||||
return str(what) + ':' + cur
|
return str(what) + os.pathsep + cur
|
||||||
return what
|
return what
|
||||||
empty_package = testdir.mkpydir("empty_package")
|
empty_package = testdir.mkpydir("empty_package")
|
||||||
monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(empty_package))
|
||||||
|
@ -551,11 +552,72 @@ class TestInvocationVariants:
|
||||||
])
|
])
|
||||||
|
|
||||||
monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(testdir))
|
||||||
path.join('test_hello.py').remove()
|
result = testdir.runpytest("--pyargs", "tpkg.test_missing")
|
||||||
result = testdir.runpytest("--pyargs", "tpkg.test_hello")
|
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
result.stderr.fnmatch_lines([
|
result.stderr.fnmatch_lines([
|
||||||
"*not*found*test_hello*",
|
"*not*found*test_missing*",
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_cmdline_python_namespace_package(self, testdir, monkeypatch):
|
||||||
|
"""
|
||||||
|
test --pyargs option with namespace packages (#1567)
|
||||||
|
"""
|
||||||
|
monkeypatch.delenv('PYTHONDONTWRITEBYTECODE', raising=False)
|
||||||
|
|
||||||
|
search_path = []
|
||||||
|
for dirname in "hello", "world":
|
||||||
|
d = testdir.mkdir(dirname)
|
||||||
|
search_path.append(d)
|
||||||
|
ns = d.mkdir("ns_pkg")
|
||||||
|
ns.join("__init__.py").write(
|
||||||
|
"__import__('pkg_resources').declare_namespace(__name__)")
|
||||||
|
lib = ns.mkdir(dirname)
|
||||||
|
lib.ensure("__init__.py")
|
||||||
|
lib.join("test_{0}.py".format(dirname)). \
|
||||||
|
write("def test_{0}(): pass\n"
|
||||||
|
"def test_other():pass".format(dirname))
|
||||||
|
|
||||||
|
# The structure of the test directory is now:
|
||||||
|
# .
|
||||||
|
# ├── hello
|
||||||
|
# │ └── ns_pkg
|
||||||
|
# │ ├── __init__.py
|
||||||
|
# │ └── hello
|
||||||
|
# │ ├── __init__.py
|
||||||
|
# │ └── test_hello.py
|
||||||
|
# └── world
|
||||||
|
# └── ns_pkg
|
||||||
|
# ├── __init__.py
|
||||||
|
# └── world
|
||||||
|
# ├── __init__.py
|
||||||
|
# └── test_world.py
|
||||||
|
|
||||||
|
def join_pythonpath(*dirs):
|
||||||
|
cur = py.std.os.environ.get('PYTHONPATH')
|
||||||
|
if cur:
|
||||||
|
dirs += (cur,)
|
||||||
|
return os.pathsep.join(str(p) for p in dirs)
|
||||||
|
monkeypatch.setenv('PYTHONPATH', join_pythonpath(*search_path))
|
||||||
|
for p in search_path:
|
||||||
|
monkeypatch.syspath_prepend(p)
|
||||||
|
|
||||||
|
# mixed module and filenames:
|
||||||
|
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "world/ns_pkg")
|
||||||
|
assert result.ret == 0
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*test_hello.py::test_hello*PASSED",
|
||||||
|
"*test_hello.py::test_other*PASSED",
|
||||||
|
"*test_world.py::test_world*PASSED",
|
||||||
|
"*test_world.py::test_other*PASSED",
|
||||||
|
"*4 passed*"
|
||||||
|
])
|
||||||
|
|
||||||
|
# specify tests within a module
|
||||||
|
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.world.test_world::test_other")
|
||||||
|
assert result.ret == 0
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*test_world.py::test_other*PASSED",
|
||||||
|
"*1 passed*"
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_cmdline_python_package_not_exists(self, testdir):
|
def test_cmdline_python_package_not_exists(self, testdir):
|
||||||
|
@ -665,11 +727,13 @@ class TestDurations:
|
||||||
testdir.makepyfile(self.source)
|
testdir.makepyfile(self.source)
|
||||||
testdir.makepyfile(test_collecterror="""xyz""")
|
testdir.makepyfile(test_collecterror="""xyz""")
|
||||||
result = testdir.runpytest("--durations=2", "-k test_1")
|
result = testdir.runpytest("--durations=2", "-k test_1")
|
||||||
assert result.ret != 0
|
assert result.ret == 2
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*durations*",
|
"*Interrupted: 1 errors during collection*",
|
||||||
"*call*test_1*",
|
|
||||||
])
|
])
|
||||||
|
# Collection errors abort test execution, therefore no duration is
|
||||||
|
# output
|
||||||
|
assert "duration" not in result.stdout.str()
|
||||||
|
|
||||||
def test_with_not(self, testdir):
|
def test_with_not(self, testdir):
|
||||||
testdir.makepyfile(self.source)
|
testdir.makepyfile(self.source)
|
||||||
|
@ -698,4 +762,3 @@ class TestDurationWithFixture:
|
||||||
* setup *test_1*
|
* setup *test_1*
|
||||||
* call *test_1*
|
* call *test_1*
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
|
@ -1066,3 +1066,15 @@ def test_repr_traceback_with_unicode(style, encoding):
|
||||||
formatter = FormattedExcinfo(style=style)
|
formatter = FormattedExcinfo(style=style)
|
||||||
repr_traceback = formatter.repr_traceback(e_info)
|
repr_traceback = formatter.repr_traceback(e_info)
|
||||||
assert repr_traceback is not None
|
assert repr_traceback is not None
|
||||||
|
|
||||||
|
|
||||||
|
def test_cwd_deleted(testdir):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
def test(tmpdir):
|
||||||
|
tmpdir.chdir()
|
||||||
|
tmpdir.remove()
|
||||||
|
assert False
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines(['* 1 failed in *'])
|
||||||
|
assert 'INTERNALERROR' not in result.stdout.str() + result.stderr.str()
|
|
@ -1,6 +1,6 @@
|
||||||
"""
|
"""
|
||||||
This is the script that is actually frozen into an executable: simply executes
|
This is the script that is actually frozen into an executable: simply executes
|
||||||
py.test main().
|
pytest main().
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -8,7 +8,7 @@ if __name__ == '__main__':
|
||||||
setup(
|
setup(
|
||||||
name="runtests",
|
name="runtests",
|
||||||
version="0.1",
|
version="0.1",
|
||||||
description="exemple of how embedding py.test into an executable using cx_freeze",
|
description="exemple of how embedding pytest into an executable using cx_freeze",
|
||||||
executables=[Executable("runtests_script.py")],
|
executables=[Executable("runtests_script.py")],
|
||||||
options={"build_exe": {'includes': pytest.freeze_includes()}},
|
options={"build_exe": {'includes': pytest.freeze_includes()}},
|
||||||
)
|
)
|
||||||
|
|
|
@ -490,6 +490,20 @@ class TestRequestBasic:
|
||||||
print(ss.stack)
|
print(ss.stack)
|
||||||
assert teardownlist == [1]
|
assert teardownlist == [1]
|
||||||
|
|
||||||
|
def test_mark_as_fixture_with_prefix_and_decorator_fails(self, testdir):
|
||||||
|
testdir.makeconftest("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def pytest_funcarg__marked_with_prefix_and_decorator():
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest_subprocess()
|
||||||
|
assert result.ret != 0
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*AssertionError:*pytest_funcarg__marked_with_prefix_and_decorator*"
|
||||||
|
])
|
||||||
|
|
||||||
def test_request_addfinalizer_failing_setup(self, testdir):
|
def test_request_addfinalizer_failing_setup(self, testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -2704,3 +2718,108 @@ class TestContextManagerFixtureFuncs:
|
||||||
""".format(flavor=flavor))
|
""".format(flavor=flavor))
|
||||||
result = testdir.runpytest("-s")
|
result = testdir.runpytest("-s")
|
||||||
result.stdout.fnmatch_lines("*mew*")
|
result.stdout.fnmatch_lines("*mew*")
|
||||||
|
class TestParameterizedSubRequest:
|
||||||
|
def test_call_from_fixture(self, testdir):
|
||||||
|
testfile = testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[0, 1, 2])
|
||||||
|
def fix_with_param(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def get_named_fixture(request):
|
||||||
|
return request.getfuncargvalue('fix_with_param')
|
||||||
|
|
||||||
|
def test_foo(request, get_named_fixture):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines("""
|
||||||
|
E*Failed: The requested fixture has no parameter defined for the current test.
|
||||||
|
E*
|
||||||
|
E*Requested fixture 'fix_with_param' defined in:
|
||||||
|
E*{0}:4
|
||||||
|
E*Requested here:
|
||||||
|
E*{1}:9
|
||||||
|
*1 error*
|
||||||
|
""".format(testfile.basename, testfile.basename))
|
||||||
|
|
||||||
|
def test_call_from_test(self, testdir):
|
||||||
|
testfile = testdir.makepyfile("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[0, 1, 2])
|
||||||
|
def fix_with_param(request):
|
||||||
|
return request.param
|
||||||
|
|
||||||
|
def test_foo(request):
|
||||||
|
request.getfuncargvalue('fix_with_param')
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines("""
|
||||||
|
E*Failed: The requested fixture has no parameter defined for the current test.
|
||||||
|
E*
|
||||||
|
E*Requested fixture 'fix_with_param' defined in:
|
||||||
|
E*{0}:4
|
||||||
|
E*Requested here:
|
||||||
|
E*{1}:8
|
||||||
|
*1 failed*
|
||||||
|
""".format(testfile.basename, testfile.basename))
|
||||||
|
|
||||||
|
def test_external_fixture(self, testdir):
|
||||||
|
conffile = testdir.makeconftest("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[0, 1, 2])
|
||||||
|
def fix_with_param(request):
|
||||||
|
return request.param
|
||||||
|
""")
|
||||||
|
|
||||||
|
testfile = testdir.makepyfile("""
|
||||||
|
def test_foo(request):
|
||||||
|
request.getfuncargvalue('fix_with_param')
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines("""
|
||||||
|
E*Failed: The requested fixture has no parameter defined for the current test.
|
||||||
|
E*
|
||||||
|
E*Requested fixture 'fix_with_param' defined in:
|
||||||
|
E*{0}:4
|
||||||
|
E*Requested here:
|
||||||
|
E*{1}:2
|
||||||
|
*1 failed*
|
||||||
|
""".format(conffile.basename, testfile.basename))
|
||||||
|
|
||||||
|
def test_non_relative_path(self, testdir):
|
||||||
|
tests_dir = testdir.mkdir('tests')
|
||||||
|
fixdir = testdir.mkdir('fixtures')
|
||||||
|
fixfile = fixdir.join("fix.py")
|
||||||
|
fixfile.write(_pytest._code.Source("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
@pytest.fixture(params=[0, 1, 2])
|
||||||
|
def fix_with_param(request):
|
||||||
|
return request.param
|
||||||
|
"""))
|
||||||
|
|
||||||
|
testfile = tests_dir.join("test_foos.py")
|
||||||
|
testfile.write(_pytest._code.Source("""
|
||||||
|
from fix import fix_with_param
|
||||||
|
|
||||||
|
def test_foo(request):
|
||||||
|
request.getfuncargvalue('fix_with_param')
|
||||||
|
"""))
|
||||||
|
|
||||||
|
tests_dir.chdir()
|
||||||
|
testdir.syspathinsert(fixdir)
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines("""
|
||||||
|
E*Failed: The requested fixture has no parameter defined for the current test.
|
||||||
|
E*
|
||||||
|
E*Requested fixture 'fix_with_param' defined in:
|
||||||
|
E*{0}:5
|
||||||
|
E*Requested here:
|
||||||
|
E*{1}:5
|
||||||
|
*1 failed*
|
||||||
|
""".format(fixfile.strpath, testfile.basename))
|
||||||
|
|
|
@ -428,7 +428,7 @@ def test_assert_compare_truncate_longmessage(monkeypatch, testdir):
|
||||||
"*- 3",
|
"*- 3",
|
||||||
"*- 5",
|
"*- 5",
|
||||||
"*- 7",
|
"*- 7",
|
||||||
"*truncated (191 more lines)*use*-vv*",
|
"*truncated (193 more lines)*use*-vv*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
@ -626,3 +626,17 @@ def test_set_with_unsortable_elements():
|
||||||
+ repr(3)
|
+ repr(3)
|
||||||
""").strip()
|
""").strip()
|
||||||
assert '\n'.join(expl) == dedent
|
assert '\n'.join(expl) == dedent
|
||||||
|
|
||||||
|
def test_diff_newline_at_end(monkeypatch, testdir):
|
||||||
|
testdir.makepyfile(r"""
|
||||||
|
def test_diff():
|
||||||
|
assert 'asdf' == 'asdf\n'
|
||||||
|
""")
|
||||||
|
|
||||||
|
result = testdir.runpytest()
|
||||||
|
result.stdout.fnmatch_lines(r"""
|
||||||
|
*assert 'asdf' == 'asdf\n'
|
||||||
|
* - asdf
|
||||||
|
* + asdf
|
||||||
|
* ? +
|
||||||
|
""")
|
||||||
|
|
|
@ -694,6 +694,40 @@ class TestAssertionRewriteHookDetails(object):
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines('*1 passed*')
|
result.stdout.fnmatch_lines('*1 passed*')
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('initial_conftest', [True, False])
|
||||||
|
@pytest.mark.parametrize('mode', ['plain', 'rewrite', 'reinterp'])
|
||||||
|
def test_conftest_assertion_rewrite(self, testdir, initial_conftest, mode):
|
||||||
|
"""Test that conftest files are using assertion rewrite on import.
|
||||||
|
(#1619)
|
||||||
|
"""
|
||||||
|
testdir.tmpdir.join('foo/tests').ensure(dir=1)
|
||||||
|
conftest_path = 'conftest.py' if initial_conftest else 'foo/conftest.py'
|
||||||
|
contents = {
|
||||||
|
conftest_path: """
|
||||||
|
import pytest
|
||||||
|
@pytest.fixture
|
||||||
|
def check_first():
|
||||||
|
def check(values, value):
|
||||||
|
assert values.pop(0) == value
|
||||||
|
return check
|
||||||
|
""",
|
||||||
|
'foo/tests/test_foo.py': """
|
||||||
|
def test(check_first):
|
||||||
|
check_first([10, 30], 30)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
testdir.makepyfile(**contents)
|
||||||
|
result = testdir.runpytest_subprocess('--assert=%s' % mode)
|
||||||
|
if mode == 'plain':
|
||||||
|
expected = 'E AssertionError'
|
||||||
|
elif mode == 'rewrite':
|
||||||
|
expected = '*assert 10 == 30*'
|
||||||
|
elif mode == 'reinterp':
|
||||||
|
expected = '*AssertionError:*was re-run*'
|
||||||
|
else:
|
||||||
|
assert 0
|
||||||
|
result.stdout.fnmatch_lines([expected])
|
||||||
|
|
||||||
|
|
||||||
def test_issue731(testdir):
|
def test_issue731(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
|
|
@ -152,7 +152,9 @@ class TestCollectPluginHookRelay:
|
||||||
wascalled = []
|
wascalled = []
|
||||||
class Plugin:
|
class Plugin:
|
||||||
def pytest_collect_file(self, path, parent):
|
def pytest_collect_file(self, path, parent):
|
||||||
wascalled.append(path)
|
if not path.basename.startswith("."):
|
||||||
|
# Ignore hidden files, e.g. .testmondata.
|
||||||
|
wascalled.append(path)
|
||||||
testdir.makefile(".abc", "xyz")
|
testdir.makefile(".abc", "xyz")
|
||||||
pytest.main([testdir.tmpdir], plugins=[Plugin()])
|
pytest.main([testdir.tmpdir], plugins=[Plugin()])
|
||||||
assert len(wascalled) == 1
|
assert len(wascalled) == 1
|
||||||
|
@ -642,3 +644,114 @@ class TestNodekeywords:
|
||||||
""")
|
""")
|
||||||
reprec = testdir.inline_run("-k repr")
|
reprec = testdir.inline_run("-k repr")
|
||||||
reprec.assertoutcome(passed=1, failed=0)
|
reprec.assertoutcome(passed=1, failed=0)
|
||||||
|
|
||||||
|
|
||||||
|
COLLECTION_ERROR_PY_FILES = dict(
|
||||||
|
test_01_failure="""
|
||||||
|
def test_1():
|
||||||
|
assert False
|
||||||
|
""",
|
||||||
|
test_02_import_error="""
|
||||||
|
import asdfasdfasdf
|
||||||
|
def test_2():
|
||||||
|
assert True
|
||||||
|
""",
|
||||||
|
test_03_import_error="""
|
||||||
|
import asdfasdfasdf
|
||||||
|
def test_3():
|
||||||
|
assert True
|
||||||
|
""",
|
||||||
|
test_04_success="""
|
||||||
|
def test_4():
|
||||||
|
assert True
|
||||||
|
""",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_exit_on_collection_error(testdir):
|
||||||
|
"""Verify that all collection errors are collected and no tests executed"""
|
||||||
|
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||||
|
|
||||||
|
res = testdir.runpytest()
|
||||||
|
assert res.ret == 2
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"collected 2 items / 2 errors",
|
||||||
|
"*ERROR collecting test_02_import_error.py*",
|
||||||
|
"*No module named *asdfa*",
|
||||||
|
"*ERROR collecting test_03_import_error.py*",
|
||||||
|
"*No module named *asdfa*",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_exit_on_collection_with_maxfail_smaller_than_n_errors(testdir):
|
||||||
|
"""
|
||||||
|
Verify collection is aborted once maxfail errors are encountered ignoring
|
||||||
|
further modules which would cause more collection errors.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||||
|
|
||||||
|
res = testdir.runpytest("--maxfail=1")
|
||||||
|
assert res.ret == 2
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"*ERROR collecting test_02_import_error.py*",
|
||||||
|
"*No module named *asdfa*",
|
||||||
|
"*Interrupted: stopping after 1 failures*",
|
||||||
|
])
|
||||||
|
|
||||||
|
assert 'test_03' not in res.stdout.str()
|
||||||
|
|
||||||
|
|
||||||
|
def test_exit_on_collection_with_maxfail_bigger_than_n_errors(testdir):
|
||||||
|
"""
|
||||||
|
Verify the test run aborts due to collection errors even if maxfail count of
|
||||||
|
errors was not reached.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||||
|
|
||||||
|
res = testdir.runpytest("--maxfail=4")
|
||||||
|
assert res.ret == 2
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"collected 2 items / 2 errors",
|
||||||
|
"*ERROR collecting test_02_import_error.py*",
|
||||||
|
"*No module named *asdfa*",
|
||||||
|
"*ERROR collecting test_03_import_error.py*",
|
||||||
|
"*No module named *asdfa*",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_continue_on_collection_errors(testdir):
|
||||||
|
"""
|
||||||
|
Verify tests are executed even when collection errors occur when the
|
||||||
|
--continue-on-collection-errors flag is set
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||||
|
|
||||||
|
res = testdir.runpytest("--continue-on-collection-errors")
|
||||||
|
assert res.ret == 1
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"collected 2 items / 2 errors",
|
||||||
|
"*1 failed, 1 passed, 2 error*",
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def test_continue_on_collection_errors_maxfail(testdir):
|
||||||
|
"""
|
||||||
|
Verify tests are executed even when collection errors occur and that maxfail
|
||||||
|
is honoured (including the collection error count).
|
||||||
|
4 tests: 2 collection errors + 1 failure + 1 success
|
||||||
|
test_4 is never executed because the test run is with --maxfail=3 which
|
||||||
|
means it is interrupted after the 2 collection errors + 1 failure.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(**COLLECTION_ERROR_PY_FILES)
|
||||||
|
|
||||||
|
res = testdir.runpytest("--continue-on-collection-errors", "--maxfail=3")
|
||||||
|
assert res.ret == 2
|
||||||
|
|
||||||
|
res.stdout.fnmatch_lines([
|
||||||
|
"collected 2 items / 2 errors",
|
||||||
|
"*Interrupted: stopping after 3 failures*",
|
||||||
|
"*1 failed, 2 error*",
|
||||||
|
])
|
||||||
|
|
|
@ -18,7 +18,7 @@ class TestParseIni:
|
||||||
assert config.inicfg['name'] == 'value'
|
assert config.inicfg['name'] == 'value'
|
||||||
|
|
||||||
def test_getcfg_empty_path(self, tmpdir):
|
def test_getcfg_empty_path(self, tmpdir):
|
||||||
getcfg([''], ['setup.cfg']) #happens on py.test ""
|
getcfg([''], ['setup.cfg']) #happens on pytest ""
|
||||||
|
|
||||||
def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
|
def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
|
||||||
monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"')
|
monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"')
|
||||||
|
@ -485,9 +485,14 @@ def test_load_initial_conftest_last_ordering(testdir):
|
||||||
pm.register(m)
|
pm.register(m)
|
||||||
hc = pm.hook.pytest_load_initial_conftests
|
hc = pm.hook.pytest_load_initial_conftests
|
||||||
l = hc._nonwrappers + hc._wrappers
|
l = hc._nonwrappers + hc._wrappers
|
||||||
assert l[-1].function.__module__ == "_pytest.capture"
|
expected = [
|
||||||
assert l[-2].function == m.pytest_load_initial_conftests
|
"_pytest.config",
|
||||||
assert l[-3].function.__module__ == "_pytest.config"
|
'test_config',
|
||||||
|
'_pytest.assertion',
|
||||||
|
'_pytest.capture',
|
||||||
|
]
|
||||||
|
assert [x.function.__module__ for x in l] == expected
|
||||||
|
|
||||||
|
|
||||||
class TestWarning:
|
class TestWarning:
|
||||||
def test_warn_config(self, testdir):
|
def test_warn_config(self, testdir):
|
||||||
|
|
|
@ -14,13 +14,16 @@ class TestDoctests:
|
||||||
>>> i-1
|
>>> i-1
|
||||||
4
|
4
|
||||||
""")
|
""")
|
||||||
|
|
||||||
for x in (testdir.tmpdir, checkfile):
|
for x in (testdir.tmpdir, checkfile):
|
||||||
#print "checking that %s returns custom items" % (x,)
|
#print "checking that %s returns custom items" % (x,)
|
||||||
items, reprec = testdir.inline_genitems(x)
|
items, reprec = testdir.inline_genitems(x)
|
||||||
assert len(items) == 1
|
assert len(items) == 1
|
||||||
assert isinstance(items[0], DoctestTextfile)
|
assert isinstance(items[0], DoctestItem)
|
||||||
|
assert isinstance(items[0].parent, DoctestTextfile)
|
||||||
|
# Empty file has no items.
|
||||||
items, reprec = testdir.inline_genitems(w)
|
items, reprec = testdir.inline_genitems(w)
|
||||||
assert len(items) == 1
|
assert len(items) == 0
|
||||||
|
|
||||||
def test_collect_module_empty(self, testdir):
|
def test_collect_module_empty(self, testdir):
|
||||||
path = testdir.makepyfile(whatever="#")
|
path = testdir.makepyfile(whatever="#")
|
||||||
|
@ -199,8 +202,20 @@ class TestDoctests:
|
||||||
"*1 failed*",
|
"*1 failed*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_doctest_unex_importerror_only_txt(self, testdir):
|
||||||
|
testdir.maketxtfile("""
|
||||||
|
>>> import asdalsdkjaslkdjasd
|
||||||
|
>>>
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest()
|
||||||
|
# doctest is never executed because of error during hello.py collection
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*>>> import asdals*",
|
||||||
|
"*UNEXPECTED*ImportError*",
|
||||||
|
"ImportError: No module named *asdal*",
|
||||||
|
])
|
||||||
|
|
||||||
def test_doctest_unex_importerror(self, testdir):
|
def test_doctest_unex_importerror_with_module(self, testdir):
|
||||||
testdir.tmpdir.join("hello.py").write(_pytest._code.Source("""
|
testdir.tmpdir.join("hello.py").write(_pytest._code.Source("""
|
||||||
import asdalsdkjaslkdjasd
|
import asdalsdkjaslkdjasd
|
||||||
"""))
|
"""))
|
||||||
|
@ -209,10 +224,11 @@ class TestDoctests:
|
||||||
>>>
|
>>>
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--doctest-modules")
|
result = testdir.runpytest("--doctest-modules")
|
||||||
|
# doctest is never executed because of error during hello.py collection
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*>>> import hello",
|
"*ERROR collecting hello.py*",
|
||||||
"*UNEXPECTED*ImportError*",
|
"*ImportError: No module named *asdals*",
|
||||||
"*import asdals*",
|
"*Interrupted: 1 errors during collection*",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_doctestmodule(self, testdir):
|
def test_doctestmodule(self, testdir):
|
||||||
|
@ -595,6 +611,11 @@ class TestDoctestSkips:
|
||||||
reprec = testdir.inline_run("--doctest-modules")
|
reprec = testdir.inline_run("--doctest-modules")
|
||||||
reprec.assertoutcome(skipped=1)
|
reprec.assertoutcome(skipped=1)
|
||||||
|
|
||||||
|
def test_vacuous_all_skipped(self, testdir, makedoctest):
|
||||||
|
makedoctest('')
|
||||||
|
reprec = testdir.inline_run("--doctest-modules")
|
||||||
|
reprec.assertoutcome(passed=0, skipped=0)
|
||||||
|
|
||||||
|
|
||||||
class TestDoctestAutoUseFixtures:
|
class TestDoctestAutoUseFixtures:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import pkg_resources
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("entrypoint", ['py.test', 'pytest'])
|
||||||
|
def test_entry_point_exist(entrypoint):
|
||||||
|
assert entrypoint in pkg_resources.get_entry_map('pytest')['console_scripts']
|
||||||
|
|
||||||
|
|
||||||
|
def test_pytest_entry_points_are_identical():
|
||||||
|
entryMap = pkg_resources.get_entry_map('pytest')['console_scripts']
|
||||||
|
assert entryMap['pytest'].module_name == entryMap['py.test'].module_name
|
|
@ -21,8 +21,8 @@ def test_help(testdir):
|
||||||
*-v*verbose*
|
*-v*verbose*
|
||||||
*setup.cfg*
|
*setup.cfg*
|
||||||
*minversion*
|
*minversion*
|
||||||
*to see*markers*py.test --markers*
|
*to see*markers*pytest --markers*
|
||||||
*to see*fixtures*py.test --fixtures*
|
*to see*fixtures*pytest --fixtures*
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def test_hookvalidation_unknown(testdir):
|
def test_hookvalidation_unknown(testdir):
|
||||||
|
|
|
@ -362,7 +362,7 @@ class TestPython:
|
||||||
file="test_collect_skipped.py",
|
file="test_collect_skipped.py",
|
||||||
name="test_collect_skipped")
|
name="test_collect_skipped")
|
||||||
|
|
||||||
# py.test doesn't give us a line here.
|
# pytest doesn't give us a line here.
|
||||||
assert tnode["line"] is None
|
assert tnode["line"] is None
|
||||||
|
|
||||||
fnode = tnode.find_first_by_tag("skipped")
|
fnode = tnode.find_first_by_tag("skipped")
|
||||||
|
|
|
@ -246,8 +246,8 @@ def test_argcomplete(testdir, monkeypatch):
|
||||||
pytest.skip("bash not available")
|
pytest.skip("bash not available")
|
||||||
script = str(testdir.tmpdir.join("test_argcomplete"))
|
script = str(testdir.tmpdir.join("test_argcomplete"))
|
||||||
pytest_bin = sys.argv[0]
|
pytest_bin = sys.argv[0]
|
||||||
if "py.test" not in os.path.basename(pytest_bin):
|
if "pytest" not in os.path.basename(pytest_bin):
|
||||||
pytest.skip("need to be run with py.test executable, not %s" %(pytest_bin,))
|
pytest.skip("need to be run with pytest executable, not %s" %(pytest_bin,))
|
||||||
|
|
||||||
with open(str(script), 'w') as fp:
|
with open(str(script), 'w') as fp:
|
||||||
# redirect output from argcomplete to stdin and stderr is not trivial
|
# redirect output from argcomplete to stdin and stderr is not trivial
|
||||||
|
@ -262,8 +262,8 @@ def test_argcomplete(testdir, monkeypatch):
|
||||||
monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
|
monkeypatch.setenv('COMP_WORDBREAKS', ' \\t\\n"\\\'><=;|&(:')
|
||||||
|
|
||||||
arg = '--fu'
|
arg = '--fu'
|
||||||
monkeypatch.setenv('COMP_LINE', "py.test " + arg)
|
monkeypatch.setenv('COMP_LINE', "pytest " + arg)
|
||||||
monkeypatch.setenv('COMP_POINT', str(len("py.test " + arg)))
|
monkeypatch.setenv('COMP_POINT', str(len("pytest " + arg)))
|
||||||
result = testdir.run('bash', str(script), arg)
|
result = testdir.run('bash', str(script), arg)
|
||||||
if result.ret == 255:
|
if result.ret == 255:
|
||||||
# argcomplete not found
|
# argcomplete not found
|
||||||
|
@ -280,8 +280,7 @@ def test_argcomplete(testdir, monkeypatch):
|
||||||
return
|
return
|
||||||
os.mkdir('test_argcomplete.d')
|
os.mkdir('test_argcomplete.d')
|
||||||
arg = 'test_argc'
|
arg = 'test_argc'
|
||||||
monkeypatch.setenv('COMP_LINE', "py.test " + arg)
|
monkeypatch.setenv('COMP_LINE', "pytest " + arg)
|
||||||
monkeypatch.setenv('COMP_POINT', str(len('py.test ' + arg)))
|
monkeypatch.setenv('COMP_POINT', str(len('pytest ' + arg)))
|
||||||
result = testdir.run('bash', str(script), arg)
|
result = testdir.run('bash', str(script), arg)
|
||||||
result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
|
result.stdout.fnmatch_lines(["test_argcomplete", "test_argcomplete.d/"])
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,6 @@ def test_failure_issue380(testdir):
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest("--resultlog=log")
|
result = testdir.runpytest("--resultlog=log")
|
||||||
assert result.ret == 1
|
assert result.ret == 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -228,6 +228,39 @@ class BaseFunctionalTests:
|
||||||
assert reps[5].nodeid.endswith("test_func")
|
assert reps[5].nodeid.endswith("test_func")
|
||||||
assert reps[5].failed
|
assert reps[5].failed
|
||||||
|
|
||||||
|
def test_exact_teardown_issue1206(self, testdir):
|
||||||
|
rec = testdir.inline_runsource("""
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
def teardown_method(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_method(self):
|
||||||
|
assert True
|
||||||
|
""")
|
||||||
|
reps = rec.getreports("pytest_runtest_logreport")
|
||||||
|
print (reps)
|
||||||
|
assert len(reps) == 3
|
||||||
|
#
|
||||||
|
assert reps[0].nodeid.endswith("test_method")
|
||||||
|
assert reps[0].passed
|
||||||
|
assert reps[0].when == 'setup'
|
||||||
|
#
|
||||||
|
assert reps[1].nodeid.endswith("test_method")
|
||||||
|
assert reps[1].passed
|
||||||
|
assert reps[1].when == 'call'
|
||||||
|
#
|
||||||
|
assert reps[2].nodeid.endswith("test_method")
|
||||||
|
assert reps[2].failed
|
||||||
|
assert reps[2].when == "teardown"
|
||||||
|
assert reps[2].longrepr.reprcrash.message in (
|
||||||
|
# python3 error
|
||||||
|
'TypeError: teardown_method() takes 1 positional argument but 2 were given',
|
||||||
|
# python2 error
|
||||||
|
'TypeError: teardown_method() takes exactly 1 argument (2 given)'
|
||||||
|
)
|
||||||
|
|
||||||
def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
|
def test_failure_in_setup_function_ignores_custom_repr(self, testdir):
|
||||||
testdir.makepyfile(conftest="""
|
testdir.makepyfile(conftest="""
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -8,16 +8,11 @@ import _pytest._pluggy as pluggy
|
||||||
import _pytest._code
|
import _pytest._code
|
||||||
import py
|
import py
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest import runner
|
|
||||||
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
from _pytest.main import EXIT_NOTESTSCOLLECTED
|
||||||
from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt
|
from _pytest.terminal import TerminalReporter, repr_pythonversion, getreportopt
|
||||||
from _pytest.terminal import build_summary_stats_line, _plugin_nameversions
|
from _pytest.terminal import build_summary_stats_line, _plugin_nameversions
|
||||||
|
|
||||||
|
|
||||||
def basic_run_report(item):
|
|
||||||
runner.call_and_report(item, "setup", log=False)
|
|
||||||
return runner.call_and_report(item, "call", log=False)
|
|
||||||
|
|
||||||
DistInfo = collections.namedtuple('DistInfo', ['project_name', 'version'])
|
DistInfo = collections.namedtuple('DistInfo', ['project_name', 'version'])
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,7 +268,7 @@ class TestCollectonly:
|
||||||
def test_collectonly_error(self, testdir):
|
def test_collectonly_error(self, testdir):
|
||||||
p = testdir.makepyfile("import Errlkjqweqwe")
|
p = testdir.makepyfile("import Errlkjqweqwe")
|
||||||
result = testdir.runpytest("--collect-only", p)
|
result = testdir.runpytest("--collect-only", p)
|
||||||
assert result.ret == 1
|
assert result.ret == 2
|
||||||
result.stdout.fnmatch_lines(_pytest._code.Source("""
|
result.stdout.fnmatch_lines(_pytest._code.Source("""
|
||||||
*ERROR*
|
*ERROR*
|
||||||
*ImportError*
|
*ImportError*
|
||||||
|
|
26
tox.ini
26
tox.ini
|
@ -7,7 +7,7 @@ envlist=
|
||||||
py27-nobyte,doctesting,py27-cxfreeze
|
py27-nobyte,doctesting,py27-cxfreeze
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands= py.test --lsof -rfsxX {posargs:testing}
|
commands= pytest --lsof -rfsxX {posargs:testing}
|
||||||
passenv = USER USERNAME
|
passenv = USER USERNAME
|
||||||
deps=
|
deps=
|
||||||
hypothesis
|
hypothesis
|
||||||
|
@ -16,7 +16,7 @@ deps=
|
||||||
requests
|
requests
|
||||||
|
|
||||||
[testenv:py26]
|
[testenv:py26]
|
||||||
commands= py.test --lsof -rfsxX {posargs:testing}
|
commands= pytest --lsof -rfsxX {posargs:testing}
|
||||||
# pinning mock to last supported version for python 2.6
|
# pinning mock to last supported version for python 2.6
|
||||||
deps=
|
deps=
|
||||||
hypothesis<3.0
|
hypothesis<3.0
|
||||||
|
@ -30,10 +30,10 @@ deps=pytest-xdist>=1.13
|
||||||
mock
|
mock
|
||||||
nose
|
nose
|
||||||
commands=
|
commands=
|
||||||
py.test -n3 -rfsxX --runpytest=subprocess {posargs:testing}
|
pytest -n3 -rfsxX --runpytest=subprocess {posargs:testing}
|
||||||
|
|
||||||
[testenv:genscript]
|
[testenv:genscript]
|
||||||
commands= py.test --genscript=pytest1
|
commands= pytest --genscript=pytest1
|
||||||
|
|
||||||
[testenv:linting]
|
[testenv:linting]
|
||||||
basepython = python2.7
|
basepython = python2.7
|
||||||
|
@ -48,26 +48,26 @@ deps=pytest-xdist>=1.13
|
||||||
nose
|
nose
|
||||||
hypothesis
|
hypothesis
|
||||||
commands=
|
commands=
|
||||||
py.test -n1 -rfsxX {posargs:testing}
|
pytest -n1 -rfsxX {posargs:testing}
|
||||||
|
|
||||||
[testenv:py35-xdist]
|
[testenv:py35-xdist]
|
||||||
deps={[testenv:py27-xdist]deps}
|
deps={[testenv:py27-xdist]deps}
|
||||||
commands=
|
commands=
|
||||||
py.test -n3 -rfsxX {posargs:testing}
|
pytest -n3 -rfsxX {posargs:testing}
|
||||||
|
|
||||||
[testenv:py27-pexpect]
|
[testenv:py27-pexpect]
|
||||||
changedir=testing
|
changedir=testing
|
||||||
platform=linux|darwin
|
platform=linux|darwin
|
||||||
deps=pexpect
|
deps=pexpect
|
||||||
commands=
|
commands=
|
||||||
py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||||
|
|
||||||
[testenv:py35-pexpect]
|
[testenv:py35-pexpect]
|
||||||
changedir=testing
|
changedir=testing
|
||||||
platform=linux|darwin
|
platform=linux|darwin
|
||||||
deps={[testenv:py27-pexpect]deps}
|
deps={[testenv:py27-pexpect]deps}
|
||||||
commands=
|
commands=
|
||||||
py.test -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
pytest -rfsxX test_pdb.py test_terminal.py test_unittest.py
|
||||||
|
|
||||||
[testenv:py27-nobyte]
|
[testenv:py27-nobyte]
|
||||||
deps=pytest-xdist>=1.13
|
deps=pytest-xdist>=1.13
|
||||||
|
@ -76,21 +76,21 @@ distribute=true
|
||||||
setenv=
|
setenv=
|
||||||
PYTHONDONTWRITEBYTECODE=1
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
commands=
|
commands=
|
||||||
py.test -n3 -rfsxX {posargs:testing}
|
pytest -n3 -rfsxX {posargs:testing}
|
||||||
|
|
||||||
[testenv:py27-trial]
|
[testenv:py27-trial]
|
||||||
deps=twisted
|
deps=twisted
|
||||||
commands=
|
commands=
|
||||||
py.test -rsxf {posargs:testing/test_unittest.py}
|
pytest -rsxf {posargs:testing/test_unittest.py}
|
||||||
|
|
||||||
[testenv:py35-trial]
|
[testenv:py35-trial]
|
||||||
platform=linux|darwin
|
platform=linux|darwin
|
||||||
deps={[testenv:py27-trial]deps}
|
deps={[testenv:py27-trial]deps}
|
||||||
commands=
|
commands=
|
||||||
py.test -rsxf {posargs:testing/test_unittest.py}
|
pytest -rsxf {posargs:testing/test_unittest.py}
|
||||||
|
|
||||||
[testenv:doctest]
|
[testenv:doctest]
|
||||||
commands=py.test --doctest-modules _pytest
|
commands=pytest --doctest-modules _pytest
|
||||||
deps=
|
deps=
|
||||||
|
|
||||||
[testenv:doc]
|
[testenv:doc]
|
||||||
|
@ -107,7 +107,7 @@ commands=
|
||||||
basepython = python
|
basepython = python
|
||||||
changedir=doc/en
|
changedir=doc/en
|
||||||
deps=PyYAML
|
deps=PyYAML
|
||||||
commands= py.test -rfsxX {posargs}
|
commands= pytest -rfsxX {posargs}
|
||||||
|
|
||||||
[testenv:regen]
|
[testenv:regen]
|
||||||
changedir=doc/en
|
changedir=doc/en
|
||||||
|
|
Loading…
Reference in New Issue