Merge remote-tracking branch 'upstream/features' into davidszotten/stepwise
This commit is contained in:
commit
f947cb2613
|
@ -3,7 +3,7 @@ Thanks for submitting a PR, your contribution is really appreciated!
|
|||
Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is
|
||||
just a guideline):
|
||||
|
||||
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](/changelog/README.rst) for details.
|
||||
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
|
||||
- [ ] Target the `master` branch for bug fixes, documentation updates and trivial changes.
|
||||
- [ ] Target the `features` branch for new features and removals/deprecations.
|
||||
- [ ] Include documentation when adding new features.
|
||||
|
|
26
.travis.yml
26
.travis.yml
|
@ -12,19 +12,15 @@ install:
|
|||
- pip install --upgrade --pre tox
|
||||
env:
|
||||
matrix:
|
||||
# note: please use "tox --listenvs" to populate the build matrix below
|
||||
# please remove the linting env in all cases
|
||||
- TOXENV=py27-pexpect
|
||||
- TOXENV=py27-xdist
|
||||
- TOXENV=py27-trial
|
||||
- TOXENV=py27-numpy
|
||||
- TOXENV=py27-pluggymaster PYTEST_NO_COVERAGE=1
|
||||
- TOXENV=py36-pexpect
|
||||
- TOXENV=py36-xdist
|
||||
- TOXENV=py36-trial
|
||||
- TOXENV=py36-numpy
|
||||
- TOXENV=py36-pluggymaster PYTEST_NO_COVERAGE=1
|
||||
# Specialized factors for py27.
|
||||
- TOXENV=py27-pexpect,py27-trial,py27-numpy
|
||||
- TOXENV=py27-nobyte
|
||||
- TOXENV=py27-xdist
|
||||
- TOXENV=py27-pluggymaster PYTEST_NO_COVERAGE=1
|
||||
# Specialized factors for py36.
|
||||
- TOXENV=py36-pexpect,py36-trial,py36-numpy
|
||||
- TOXENV=py36-xdist
|
||||
- TOXENV=py36-pluggymaster PYTEST_NO_COVERAGE=1
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
@ -97,12 +93,6 @@ after_success:
|
|||
coverage xml --ignore-errors
|
||||
coverage report -m --ignore-errors
|
||||
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -F "${TOXENV//-/,},linux"
|
||||
|
||||
# Coveralls does not support merged reports.
|
||||
if [[ "$TOXENV" = py37 ]]; then
|
||||
pip install coveralls
|
||||
coveralls
|
||||
fi
|
||||
fi
|
||||
|
||||
notifications:
|
||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -204,6 +204,7 @@ Stefan Zimmermann
|
|||
Stefano Taschini
|
||||
Steffen Allner
|
||||
Stephan Obermann
|
||||
Sven-Hendrik Haase
|
||||
Tadek Teleżyński
|
||||
Tarcisio Fischer
|
||||
Tareq Alayan
|
||||
|
@ -213,6 +214,7 @@ Thomas Hisch
|
|||
Tim Strazny
|
||||
Tom Dalton
|
||||
Tom Viner
|
||||
Tomer Keren
|
||||
Trevor Bekolay
|
||||
Tyler Goodlet
|
||||
Tzu-ping Chung
|
||||
|
|
157
CHANGELOG.rst
157
CHANGELOG.rst
|
@ -18,6 +18,163 @@ with advance notice in the **Deprecations** section of releases.
|
|||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 3.9.1 (2018-10-16)
|
||||
=========================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#4159 <https://github.com/pytest-dev/pytest/issues/4159>`_: For test-suites containing test classes, the information about the subclassed
|
||||
module is now output only if a higher verbosity level is specified (at least
|
||||
"-vv").
|
||||
|
||||
|
||||
pytest 3.9.0 (2018-10-15 - not published due to a release automation bug)
|
||||
=========================================================================
|
||||
|
||||
Deprecations
|
||||
------------
|
||||
|
||||
- `#3616 <https://github.com/pytest-dev/pytest/issues/3616>`_: The following accesses have been documented as deprecated for years, but are now actually emitting deprecation warnings.
|
||||
|
||||
* Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances. Now
|
||||
users will this warning::
|
||||
|
||||
usage of Function.Module is deprecated, please use pytest.Module instead
|
||||
|
||||
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
||||
|
||||
* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can
|
||||
consult `funcarg comparison section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_.
|
||||
|
||||
* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
||||
collection.
|
||||
|
||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
||||
message please contact the authors so they can change the code.
|
||||
|
||||
* The warning that produces the message below has changed to ``RemovedInPytest4Warning``::
|
||||
|
||||
getfuncargvalue is deprecated, use getfixturevalue
|
||||
|
||||
|
||||
- `#3988 <https://github.com/pytest-dev/pytest/issues/3988>`_: Add a Deprecation warning for pytest.ensuretemp as it was deprecated since a while.
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#2293 <https://github.com/pytest-dev/pytest/issues/2293>`_: Improve usage errors messages by hiding internal details which can be distracting and noisy.
|
||||
|
||||
This has the side effect that some error conditions that previously raised generic errors (such as
|
||||
``ValueError`` for unregistered marks) are now raising ``Failed`` exceptions.
|
||||
|
||||
|
||||
- `#3332 <https://github.com/pytest-dev/pytest/issues/3332>`_: Improve the error displayed when a ``conftest.py`` file could not be imported.
|
||||
|
||||
In order to implement this, a new ``chain`` parameter was added to ``ExceptionInfo.getrepr``
|
||||
to show or hide chained tracebacks in Python 3 (defaults to ``True``).
|
||||
|
||||
|
||||
- `#3849 <https://github.com/pytest-dev/pytest/issues/3849>`_: Add ``empty_parameter_set_mark=fail_at_collect`` ini option for raising an exception when parametrize collects an empty set.
|
||||
|
||||
|
||||
- `#3964 <https://github.com/pytest-dev/pytest/issues/3964>`_: Log messages generated in the collection phase are shown when
|
||||
live-logging is enabled and/or when they are logged to a file.
|
||||
|
||||
|
||||
- `#3985 <https://github.com/pytest-dev/pytest/issues/3985>`_: Introduce ``tmp_path`` as a fixture providing a Path object.
|
||||
|
||||
|
||||
- `#4013 <https://github.com/pytest-dev/pytest/issues/4013>`_: Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version
|
||||
any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default.
|
||||
|
||||
|
||||
- `#4073 <https://github.com/pytest-dev/pytest/issues/4073>`_: Allow specification of timeout for ``Testdir.runpytest_subprocess()`` and ``Testdir.run()``.
|
||||
|
||||
|
||||
- `#4098 <https://github.com/pytest-dev/pytest/issues/4098>`_: Add returncode argument to pytest.exit() to exit pytest with a specific return code.
|
||||
|
||||
|
||||
- `#4102 <https://github.com/pytest-dev/pytest/issues/4102>`_: Reimplement ``pytest.deprecated_call`` using ``pytest.warns`` so it supports the ``match='...'`` keyword argument.
|
||||
|
||||
This has the side effect that ``pytest.deprecated_call`` now raises ``pytest.fail.Exception`` instead
|
||||
of ``AssertionError``.
|
||||
|
||||
|
||||
- `#4149 <https://github.com/pytest-dev/pytest/issues/4149>`_: Require setuptools>=30.3 and move most of the metadata to ``setup.cfg``.
|
||||
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#2535 <https://github.com/pytest-dev/pytest/issues/2535>`_: Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture.
|
||||
|
||||
|
||||
- `#3057 <https://github.com/pytest-dev/pytest/issues/3057>`_: ``request.fixturenames`` now correctly returns the name of fixtures created by ``request.getfixturevalue()``.
|
||||
|
||||
|
||||
- `#3946 <https://github.com/pytest-dev/pytest/issues/3946>`_: Warning filters passed as command line options using ``-W`` now take precedence over filters defined in ``ini``
|
||||
configuration files.
|
||||
|
||||
|
||||
- `#4066 <https://github.com/pytest-dev/pytest/issues/4066>`_: Fix source reindenting by using ``textwrap.dedent`` directly.
|
||||
|
||||
|
||||
- `#4102 <https://github.com/pytest-dev/pytest/issues/4102>`_: ``pytest.warn`` will capture previously-warned warnings in Python 2. Previously they were never raised.
|
||||
|
||||
|
||||
- `#4108 <https://github.com/pytest-dev/pytest/issues/4108>`_: Resolve symbolic links for args.
|
||||
|
||||
This fixes running ``pytest tests/test_foo.py::test_bar``, where ``tests``
|
||||
is a symlink to ``project/app/tests``:
|
||||
previously ``project/app/conftest.py`` would be ignored for fixtures then.
|
||||
|
||||
|
||||
- `#4132 <https://github.com/pytest-dev/pytest/issues/4132>`_: Fix duplicate printing of internal errors when using ``--pdb``.
|
||||
|
||||
|
||||
- `#4135 <https://github.com/pytest-dev/pytest/issues/4135>`_: pathlib based tmpdir cleanup now correctly handles symlinks in the folder.
|
||||
|
||||
|
||||
- `#4152 <https://github.com/pytest-dev/pytest/issues/4152>`_: Display the filename when encountering ``SyntaxWarning``.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#3713 <https://github.com/pytest-dev/pytest/issues/3713>`_: Update usefixtures documentation to clarify that it can't be used with fixture functions.
|
||||
|
||||
|
||||
- `#4058 <https://github.com/pytest-dev/pytest/issues/4058>`_: Update fixture documentation to specify that a fixture can be invoked twice in the scope it's defined for.
|
||||
|
||||
|
||||
- `#4064 <https://github.com/pytest-dev/pytest/issues/4064>`_: According to unittest.rst, setUpModule and tearDownModule were not implemented, but it turns out they are. So updated the documentation for unittest.
|
||||
|
||||
|
||||
- `#4151 <https://github.com/pytest-dev/pytest/issues/4151>`_: Add tempir testing example to CONTRIBUTING.rst guide
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#2293 <https://github.com/pytest-dev/pytest/issues/2293>`_: The internal ``MarkerError`` exception has been removed.
|
||||
|
||||
|
||||
- `#3988 <https://github.com/pytest-dev/pytest/issues/3988>`_: Port the implementation of tmpdir to pathlib.
|
||||
|
||||
|
||||
- `#4063 <https://github.com/pytest-dev/pytest/issues/4063>`_: Exclude 0.00 second entries from ``--duration`` output unless ``-vv`` is passed on the command-line.
|
||||
|
||||
|
||||
- `#4093 <https://github.com/pytest-dev/pytest/issues/4093>`_: Fixed formatting of string literals in internal tests.
|
||||
|
||||
|
||||
pytest 3.8.2 (2018-10-02)
|
||||
=========================
|
||||
|
||||
|
|
|
@ -280,6 +280,47 @@ Here is a simple overview, with pytest-specific bits:
|
|||
base: features # if it's a feature
|
||||
|
||||
|
||||
Writing Tests
|
||||
----------------------------
|
||||
|
||||
Writing tests for plugins or for pytest itself is often done using the `testdir fixture <https://docs.pytest.org/en/latest/reference.html#testdir>`_, as a "black-box" test.
|
||||
|
||||
For example, to ensure a simple test passes you can write:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.assert_outcomes(failed=0, passed=1)
|
||||
|
||||
|
||||
Alternatively, it is possible to make checks based on the actual output of the termal using
|
||||
*glob-like* expressions:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"])
|
||||
|
||||
When choosing a file where to write a new test, take a look at the existing files and see if there's
|
||||
one file which looks like a good fit. For example, a regression test about a bug in the ``--lf`` option
|
||||
should go into ``test_cacheprovider.py``, given that this option is implemented in ``cacheprovider.py``.
|
||||
If in doubt, go ahead and open a PR with your best guess and we can discuss this over the code.
|
||||
|
||||
|
||||
Joining the Development Team
|
||||
----------------------------
|
||||
|
||||
|
|
26
appveyor.yml
26
appveyor.yml
|
@ -1,27 +1,29 @@
|
|||
environment:
|
||||
matrix:
|
||||
- TOXENV: "linting,docs,doctesting"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "py27"
|
||||
- TOXENV: "py34"
|
||||
- TOXENV: "py35"
|
||||
- TOXENV: "py36"
|
||||
- TOXENV: "py37"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "linting,docs,doctesting"
|
||||
- TOXENV: "py36"
|
||||
- TOXENV: "py35"
|
||||
- TOXENV: "py34"
|
||||
- TOXENV: "pypy"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "py27-xdist"
|
||||
- TOXENV: "py27-trial"
|
||||
- TOXENV: "py27-numpy"
|
||||
# Specialized factors for py27.
|
||||
- TOXENV: "py27-trial,py27-numpy,py27-nobyte"
|
||||
- TOXENV: "py27-pluggymaster"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "py36-xdist"
|
||||
- TOXENV: "py36-trial"
|
||||
- TOXENV: "py36-numpy"
|
||||
- TOXENV: "py27-xdist"
|
||||
# Specialized factors for py36.
|
||||
- TOXENV: "py36-trial,py36-numpy"
|
||||
- TOXENV: "py36-pluggymaster"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "py27-nobyte"
|
||||
- TOXENV: "py36-freeze"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
- TOXENV: "py36-xdist"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- echo Installed Pythons
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
Improve usage errors messages by hiding internal details which can be distracting and noisy.
|
||||
|
||||
This has the side effect that some error conditions that previously raised generic errors (such as
|
||||
``ValueError`` for unregistered marks) are now raising ``Failed`` exceptions.
|
|
@ -1 +0,0 @@
|
|||
The internal ``MarkerError`` exception has been removed.
|
|
@ -1 +0,0 @@
|
|||
Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture.
|
|
@ -1 +0,0 @@
|
|||
``request.fixturenames`` now correctly returns the name of fixtures created by ``request.getfixturevalue()``.
|
|
@ -1,4 +0,0 @@
|
|||
Improve the error displayed when a ``conftest.py`` file could not be imported.
|
||||
|
||||
In order to implement this, a new ``chain`` parameter was added to ``ExceptionInfo.getrepr``
|
||||
to show or hide chained tracebacks in Python 3 (defaults to ``True``).
|
|
@ -0,0 +1 @@
|
|||
Fix unescaped XML raw objects in JUnit report for skipped tests
|
|
@ -1,22 +0,0 @@
|
|||
The following accesses have been documented as deprecated for years, but are now actually emitting deprecation warnings.
|
||||
|
||||
* Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances. Now
|
||||
users will this warning::
|
||||
|
||||
usage of Function.Module is deprecated, please use pytest.Module instead
|
||||
|
||||
Users should just ``import pytest`` and access those objects using the ``pytest`` module.
|
||||
|
||||
* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can
|
||||
consult `funcarg comparision section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_.
|
||||
|
||||
* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
||||
collection.
|
||||
|
||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
||||
message please contact the authors so they can change the code.
|
||||
|
||||
* The warning that produces the message below has changed to ``RemovedInPytest4Warning``::
|
||||
|
||||
getfuncargvalue is deprecated, use getfixturevalue
|
|
@ -1 +0,0 @@
|
|||
Update usefixtures documentation to clarify that it can't be used with fixture functions.
|
|
@ -1 +0,0 @@
|
|||
Add ``empty_parameter_set_mark=fail_at_collect`` ini option for raising an exception when parametrize collects an empty set.
|
|
@ -1,2 +0,0 @@
|
|||
Warning filters passed as command line options using ``-W`` now take precedence over filters defined in ``ini``
|
||||
configuration files.
|
|
@ -1,2 +0,0 @@
|
|||
Log messages generated in the collection phase are shown when
|
||||
live-logging is enabled and/or when they are logged to a file.
|
|
@ -1 +0,0 @@
|
|||
Introduce ``tmp_path`` as a fixture providing a Path object.
|
|
@ -1 +0,0 @@
|
|||
Add a Deprecation warning for pytest.ensuretemp as it was deprecated since a while.
|
|
@ -1 +0,0 @@
|
|||
Port the implementation of tmpdir to pathlib.
|
|
@ -1,2 +0,0 @@
|
|||
Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version
|
||||
any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default.
|
|
@ -1 +0,0 @@
|
|||
Update fixture documentation to specify that a fixture can be invoked twice in the scope it's defined for.
|
|
@ -1 +0,0 @@
|
|||
According to unittest.rst, setUpModule and tearDownModule were not implemented, but it turns out they are. So updated the documentation for unittest.
|
|
@ -1 +0,0 @@
|
|||
Fix source reindenting by using ``textwrap.dedent`` directly.
|
|
@ -1 +0,0 @@
|
|||
Allow specification of timeout for ``Testdir.runpytest_subprocess()`` and ``Testdir.run()``.
|
|
@ -1 +0,0 @@
|
|||
Fixed formatting of string literals in internal tests.
|
|
@ -1 +0,0 @@
|
|||
Add returncode argument to pytest.exit() to exit pytest with a specific return code.
|
|
@ -1 +0,0 @@
|
|||
``pytest.warn`` will capture previously-warned warnings in Python 2. Previously they were never raised.
|
|
@ -1,4 +0,0 @@
|
|||
Reimplement ``pytest.deprecated_call`` using ``pytest.warns`` so it supports the ``match='...'`` keyword argument.
|
||||
|
||||
This has the side effect that ``pytest.deprecated_call`` now raises ``pytest.fail.Exception`` instead
|
||||
of ``AssertionError``.
|
|
@ -1,5 +0,0 @@
|
|||
Resolve symbolic links for args.
|
||||
|
||||
This fixes running ``pytest tests/test_foo.py::test_bar``, where ``tests``
|
||||
is a symlink to ``project/app/tests``:
|
||||
previously ``project/app/conftest.py`` would be ignored for fixtures then.
|
|
@ -1 +0,0 @@
|
|||
pathlib based tmpdir cleanup now correctly handles symlinks in the folder.
|
|
@ -1 +0,0 @@
|
|||
Require setuptools>=30.3 and move most of the metadata to ``setup.cfg``.
|
|
@ -0,0 +1 @@
|
|||
Pin ``setuptools>=40.0`` to support ``py_modules`` in ``setup.cfg``
|
|
@ -0,0 +1 @@
|
|||
Restore the tmpdir behaviour of symlinking the current test run.
|
|
@ -0,0 +1 @@
|
|||
Make ``--color`` emit colorful dots when not running in verbose mode. Earlier, it would only colorize the test-by-test output if ``--verbose`` was also passed.
|
|
@ -6,6 +6,8 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-3.9.1
|
||||
release-3.9.0
|
||||
release-3.8.2
|
||||
release-3.8.1
|
||||
release-3.8.0
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
pytest-3.9.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 3.9.0 release!
|
||||
|
||||
pytest is a mature Python testing tool with more than a 2000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a number of bugs fixes and improvements, so users are encouraged
|
||||
to take a look at the CHANGELOG:
|
||||
|
||||
https://docs.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
https://docs.pytest.org/en/latest/
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Andrea Cimatoribus
|
||||
* Ankit Goel
|
||||
* Anthony Sottile
|
||||
* Ben Eyal
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Jeffrey Rackauckas
|
||||
* Jose Carlos Menezes
|
||||
* Kyle Altendorf
|
||||
* Niklas JQ
|
||||
* Palash Chatterjee
|
||||
* Ronny Pfannschmidt
|
||||
* Thomas Hess
|
||||
* Thomas Hisch
|
||||
* Tomer Keren
|
||||
* Victor Maryama
|
||||
|
||||
|
||||
Happy testing,
|
||||
The Pytest Development Team
|
|
@ -0,0 +1,20 @@
|
|||
pytest-3.9.1
|
||||
=======================================
|
||||
|
||||
pytest 3.9.1 has just been released to PyPI.
|
||||
|
||||
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The full changelog is available at https://docs.pytest.org/en/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Bruno Oliveira
|
||||
* Ronny Pfannschmidt
|
||||
* Thomas Hisch
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -104,7 +104,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
|||
See http://docs.python.org/library/warnings.html for information
|
||||
on warning categories.
|
||||
tmpdir_factory
|
||||
Return a TempdirFactory instance for the test session.
|
||||
Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.
|
||||
tmp_path_factory
|
||||
Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
|
||||
tmpdir
|
||||
Return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
|
@ -113,6 +115,16 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
|||
path object.
|
||||
|
||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
||||
tmp_path
|
||||
Return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
created as a sub directory of the base temporary
|
||||
directory. The returned object is a :class:`pathlib.Path`
|
||||
object.
|
||||
|
||||
.. note::
|
||||
|
||||
in python < 3.6 this is a pathlib2.Path
|
||||
|
||||
no tests ran in 0.12 seconds
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ This should be updated to make use of standard fixture mechanisms:
|
|||
session.close()
|
||||
|
||||
|
||||
You can consult `funcarg comparision section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_ for
|
||||
You can consult `funcarg comparison section in the docs <https://docs.pytest.org/en/latest/funcarg_compare.html>`_ for
|
||||
more information.
|
||||
|
||||
This has been documented as deprecated for years, but only now we are actually emitting deprecation warnings.
|
||||
|
@ -68,7 +68,7 @@ Using ``Class`` in custom Collectors
|
|||
.. deprecated:: 3.9
|
||||
|
||||
Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
||||
subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during
|
||||
subclasses has been deprecated. Users instead should use ``pytest_pycollect_makeitem`` to customize node types during
|
||||
collection.
|
||||
|
||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
||||
|
@ -304,7 +304,7 @@ This form of test function doesn't support fixtures properly, and users should s
|
|||
.. code-block:: python
|
||||
|
||||
@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
|
||||
def test_squared():
|
||||
def test_squared(x, y):
|
||||
assert x ** x == y
|
||||
|
||||
|
||||
|
|
|
@ -574,7 +574,7 @@ We can run this::
|
|||
file $REGENDOC_TMPDIR/b/test_error.py, line 1
|
||||
def test_root(db): # no db here, will error out
|
||||
E fixture 'db' not found
|
||||
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmpdir, tmpdir_factory
|
||||
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
|
||||
> use 'pytest --fixtures [testpath]' for help on them.
|
||||
|
||||
$REGENDOC_TMPDIR/b/test_error.py:1
|
||||
|
|
|
@ -31,16 +31,37 @@ created in the `base temporary directory`_.
|
|||
p = d / "hello.txt"
|
||||
p.write_text(CONTENT)
|
||||
assert p.read_text() == CONTENT
|
||||
assert len(tmpdir.listdir()) == 1
|
||||
assert len(list(tmp_path.iterdir())) == 1
|
||||
assert 0
|
||||
|
||||
Running this would result in a passed test except for the last
|
||||
``assert 0`` line which we use to look at values::
|
||||
|
||||
$ pytest test_tmp_path.py
|
||||
... #fill fom regendoc
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collected 1 item
|
||||
|
||||
test_tmp_path.py F [100%]
|
||||
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_create_file _____________________________
|
||||
|
||||
tmp_path = PosixPath('PYTEST_TMPDIR/test_create_file0')
|
||||
|
||||
def test_create_file(tmp_path):
|
||||
d = tmp_path / "sub"
|
||||
d.mkdir()
|
||||
p = d / "hello.txt"
|
||||
p.write_text(CONTENT)
|
||||
assert p.read_text() == CONTENT
|
||||
assert len(list(tmp_path.iterdir())) == 1
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_tmp_path.py:13: AssertionError
|
||||
========================= 1 failed in 0.12 seconds =========================
|
||||
|
||||
The ``tmp_path_factory`` fixture
|
||||
--------------------------------
|
||||
|
|
|
@ -269,6 +269,7 @@ To get a list of the slowest 10 test durations::
|
|||
|
||||
pytest --durations=10
|
||||
|
||||
By default, pytest will not show test durations that are too small (<0.01s) unless ``-vv`` is passed on the command-line.
|
||||
|
||||
Creating JUnitXML format files
|
||||
----------------------------------------------------
|
||||
|
|
|
@ -75,60 +75,6 @@ Both ``-W`` command-line option and ``filterwarnings`` ini option are based on P
|
|||
`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
|
||||
documentation for other examples and advanced usage.
|
||||
|
||||
Disabling warning summary
|
||||
-------------------------
|
||||
|
||||
Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the
|
||||
warning summary entirely from the test run output.
|
||||
|
||||
Disabling warning capture entirely
|
||||
----------------------------------
|
||||
|
||||
This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
addopts = -p no:warnings
|
||||
|
||||
Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings
|
||||
using an external system.
|
||||
|
||||
|
||||
.. _`deprecation-warnings`:
|
||||
|
||||
DeprecationWarning and PendingDeprecationWarning
|
||||
------------------------------------------------
|
||||
|
||||
.. versionadded:: 3.8
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning``.
|
||||
|
||||
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
|
||||
(such as third-party libraries), in which case you might use the standard warning filters options (ini or marks).
|
||||
For example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
filterwarnings =
|
||||
ignore:.*U.*mode is deprecated:DeprecationWarning
|
||||
|
||||
|
||||
.. note::
|
||||
If warnings are configured at the interpreter level, using
|
||||
the `PYTHONWARNINGS <https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS>`_ environment variable or the
|
||||
``-W`` command-line option, pytest will not configure any filters by default.
|
||||
|
||||
.. note::
|
||||
This feature makes pytest more compliant with `PEP-0506 <https://www.python.org/dev/peps/pep-0565/#recommended-filter-settings-for-test-runners>`_ which suggests that those warnings should
|
||||
be shown by default by test runners, but pytest doesn't follow ``PEP-0506`` completely because resetting all
|
||||
warning filters like suggested in the PEP will break existing test suites that configure warning filters themselves
|
||||
by calling ``warnings.simplefilter`` (see issue `#2430 <https://github.com/pytest-dev/pytest/issues/2430>`_
|
||||
for an example of that).
|
||||
|
||||
|
||||
.. _`filterwarnings`:
|
||||
|
||||
``@pytest.mark.filterwarnings``
|
||||
|
@ -167,24 +113,6 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
|||
pytestmark = pytest.mark.filterwarnings("error")
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Except for these features, pytest does not change the python warning filter; it only captures
|
||||
and displays the warnings which are issued with respect to the currently configured filter,
|
||||
including changes to the filter made by test functions or by the system under test.
|
||||
|
||||
.. note::
|
||||
|
||||
``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library
|
||||
by default so you have to explicitly configure them to be displayed in your ``pytest.ini``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
filterwarnings =
|
||||
once::DeprecationWarning
|
||||
once::PendingDeprecationWarning
|
||||
|
||||
|
||||
*Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_
|
||||
*plugin.*
|
||||
|
@ -193,6 +121,102 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable:
|
|||
.. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter
|
||||
.. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings
|
||||
|
||||
Disabling warnings summary
|
||||
--------------------------
|
||||
|
||||
Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the
|
||||
warning summary entirely from the test run output.
|
||||
|
||||
Disabling warning capture entirely
|
||||
----------------------------------
|
||||
|
||||
This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
addopts = -p no:warnings
|
||||
|
||||
Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings
|
||||
using an external system.
|
||||
|
||||
|
||||
.. _`deprecation-warnings`:
|
||||
|
||||
DeprecationWarning and PendingDeprecationWarning
|
||||
------------------------------------------------
|
||||
|
||||
.. versionadded:: 3.8
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
|
||||
user code and third-party libraries, as recommended by `PEP-0506 <https://www.python.org/dev/peps/pep-0565>`_.
|
||||
This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.
|
||||
|
||||
Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over
|
||||
(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore
|
||||
those warnings.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
filterwarnings =
|
||||
ignore:.*U.*mode is deprecated:DeprecationWarning
|
||||
|
||||
|
||||
This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches
|
||||
the regular expression ``".*U.*mode is deprecated"``.
|
||||
|
||||
.. note::
|
||||
If warnings are configured at the interpreter level, using
|
||||
the `PYTHONWARNINGS <https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS>`_ environment variable or the
|
||||
``-W`` command-line option, pytest will not configure any filters by default.
|
||||
|
||||
Also pytest doesn't follow ``PEP-0506`` suggestion of resetting all warning filters because
|
||||
it might break test suites that configure warning filters themselves
|
||||
by calling ``warnings.simplefilter`` (see issue `#2430 <https://github.com/pytest-dev/pytest/issues/2430>`_
|
||||
for an example of that).
|
||||
|
||||
|
||||
.. _`ensuring a function triggers a deprecation warning`:
|
||||
|
||||
.. _ensuring_function_triggers:
|
||||
|
||||
Ensuring code triggers a deprecation warning
|
||||
--------------------------------------------
|
||||
|
||||
You can also call a global helper for checking
|
||||
that a certain function call triggers a ``DeprecationWarning`` or
|
||||
``PendingDeprecationWarning``::
|
||||
|
||||
import pytest
|
||||
|
||||
def test_global():
|
||||
pytest.deprecated_call(myfunction, 17)
|
||||
|
||||
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
||||
caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
|
||||
them. If you wish to record them in your own code, use the
|
||||
command ``warnings.simplefilter('always')``::
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
def test_deprecation(recwarn):
|
||||
warnings.simplefilter('always')
|
||||
warnings.warn("deprecated", DeprecationWarning)
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
You can also use it as a contextmanager::
|
||||
|
||||
def test_global():
|
||||
with pytest.deprecated_call():
|
||||
myobject.deprecated_method()
|
||||
|
||||
|
||||
|
||||
.. _`asserting warnings`:
|
||||
|
||||
|
@ -299,43 +323,6 @@ warnings, or index into it to get a particular recorded warning.
|
|||
|
||||
Full API: :class:`WarningsRecorder`.
|
||||
|
||||
.. _`ensuring a function triggers a deprecation warning`:
|
||||
|
||||
.. _ensuring_function_triggers:
|
||||
|
||||
Ensuring a function triggers a deprecation warning
|
||||
-------------------------------------------------------
|
||||
|
||||
You can also call a global helper for checking
|
||||
that a certain function call triggers a ``DeprecationWarning`` or
|
||||
``PendingDeprecationWarning``::
|
||||
|
||||
import pytest
|
||||
|
||||
def test_global():
|
||||
pytest.deprecated_call(myfunction, 17)
|
||||
|
||||
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
||||
caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
|
||||
them. If you wish to record them in your own code, use the
|
||||
command ``warnings.simplefilter('always')``::
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
def test_deprecation(recwarn):
|
||||
warnings.simplefilter('always')
|
||||
warnings.warn("deprecated", DeprecationWarning)
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
You can also use it as a contextmanager::
|
||||
|
||||
def test_global():
|
||||
with pytest.deprecated_call():
|
||||
myobject.deprecated_method()
|
||||
|
||||
|
||||
|
||||
.. _internal-warnings:
|
||||
|
||||
|
|
|
@ -420,9 +420,21 @@ additionally it is possible to copy examples for a example folder before running
|
|||
============================= warnings summary =============================
|
||||
$REGENDOC_TMPDIR/test_example.py:4: PytestExperimentalApiWarning: testdir.copy_example is an experimental api that may change over time
|
||||
testdir.copy_example("test_example.py")
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead
|
||||
return getattr(object, name, default)
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.File is deprecated, please use pytest.File instead
|
||||
return getattr(object, name, default)
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Function is deprecated, please use pytest.Function instead
|
||||
return getattr(object, name, default)
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Instance is deprecated, please use pytest.Instance instead
|
||||
return getattr(object, name, default)
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Item is deprecated, please use pytest.Item instead
|
||||
return getattr(object, name, default)
|
||||
$PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Module is deprecated, please use pytest.Module instead
|
||||
return getattr(object, name, default)
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
=================== 2 passed, 1 warnings in 0.12 seconds ===================
|
||||
=================== 2 passed, 7 warnings in 0.12 seconds ===================
|
||||
|
||||
For more information about the result object that ``runpytest()`` returns, and
|
||||
the methods that it provides please check out the :py:class:`RunResult
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[build-system]
|
||||
requires = [
|
||||
# sync with setup.py until we discard non-pep-517/518
|
||||
"setuptools>=30.3",
|
||||
"setuptools>=40.0",
|
||||
"setuptools-scm",
|
||||
"wheel",
|
||||
]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
name = pytest
|
||||
description = pytest: simple powerful testing with Python
|
||||
long_description = file: README.rst
|
||||
url = "https://docs.pytest.org/en/latest/"
|
||||
url = https://docs.pytest.org/en/latest/
|
||||
project_urls =
|
||||
Source=https://github.com/pytest-dev/pytest
|
||||
Tracker=https://github.com/pytest-dev/pytest/issues
|
||||
|
|
2
setup.py
2
setup.py
|
@ -26,7 +26,7 @@ if "_PYTEST_SETUP_SKIP_PLUGGY_DEP" not in os.environ:
|
|||
def main():
|
||||
setup(
|
||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
||||
setup_requires=["setuptools-scm", "setuptools>=30.3"],
|
||||
setup_requires=["setuptools-scm", "setuptools>=40.0"],
|
||||
package_dir={"": "src"},
|
||||
install_requires=INSTALL_REQUIRES,
|
||||
)
|
||||
|
|
|
@ -399,7 +399,7 @@ def _rewrite_test(config, fn):
|
|||
finally:
|
||||
del state._indecode
|
||||
try:
|
||||
tree = ast.parse(source)
|
||||
tree = ast.parse(source, filename=fn.strpath)
|
||||
except SyntaxError:
|
||||
# Let this pop up again in the real import.
|
||||
state.trace("failed to parse: %r" % (fn,))
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
""" interactive debugging with PDB, the Python Debugger. """
|
||||
from __future__ import absolute_import, division, print_function
|
||||
|
||||
import os
|
||||
import pdb
|
||||
import sys
|
||||
import os
|
||||
from doctest import UnexpectedException
|
||||
|
||||
from _pytest import outcomes
|
||||
from _pytest.config import hookimpl
|
||||
|
||||
try:
|
||||
|
@ -109,9 +111,6 @@ class PdbInvoke(object):
|
|||
_enter_pdb(node, call.excinfo, report)
|
||||
|
||||
def pytest_internalerror(self, excrepr, excinfo):
|
||||
for line in str(excrepr).split("\n"):
|
||||
sys.stderr.write("INTERNALERROR> %s\n" % line)
|
||||
sys.stderr.flush()
|
||||
tb = _postmortem_traceback(excinfo)
|
||||
post_mortem(tb)
|
||||
|
||||
|
@ -164,8 +163,9 @@ def _enter_pdb(node, excinfo, rep):
|
|||
rep.toterminal(tw)
|
||||
tw.sep(">", "entering PDB")
|
||||
tb = _postmortem_traceback(excinfo)
|
||||
post_mortem(tb)
|
||||
rep._pdbshown = True
|
||||
if post_mortem(tb):
|
||||
outcomes.exit("Quitting debugger")
|
||||
return rep
|
||||
|
||||
|
||||
|
@ -196,3 +196,4 @@ def post_mortem(t):
|
|||
p = Pdb()
|
||||
p.reset()
|
||||
p.interaction(None, t)
|
||||
return p.quitting
|
||||
|
|
|
@ -1020,7 +1020,7 @@ class FixtureFunctionMarker(object):
|
|||
|
||||
def __call__(self, function):
|
||||
if isclass(function):
|
||||
raise ValueError("class fixtures not supported (may be in the future)")
|
||||
raise ValueError("class fixtures not supported (maybe in the future)")
|
||||
|
||||
if getattr(function, "_pytestfixturefunction", False):
|
||||
raise ValueError(
|
||||
|
@ -1371,8 +1371,7 @@ class FixtureManager(object):
|
|||
fixturedefs = self._arg2fixturedefs[argname]
|
||||
except KeyError:
|
||||
return None
|
||||
else:
|
||||
return tuple(self._matchfactories(fixturedefs, nodeid))
|
||||
return tuple(self._matchfactories(fixturedefs, nodeid))
|
||||
|
||||
def _matchfactories(self, fixturedefs, nodeid):
|
||||
for fixturedef in fixturedefs:
|
||||
|
|
|
@ -221,12 +221,14 @@ class _NodeReporter(object):
|
|||
else:
|
||||
filename, lineno, skipreason = report.longrepr
|
||||
if skipreason.startswith("Skipped: "):
|
||||
skipreason = bin_xml_escape(skipreason[9:])
|
||||
skipreason = skipreason[9:]
|
||||
details = "%s:%s: %s" % (filename, lineno, skipreason)
|
||||
|
||||
self.append(
|
||||
Junit.skipped(
|
||||
"%s:%s: %s" % (filename, lineno, skipreason),
|
||||
bin_xml_escape(details),
|
||||
type="pytest.skip",
|
||||
message=skipreason,
|
||||
message=bin_xml_escape(skipreason),
|
||||
)
|
||||
)
|
||||
self.write_captured_output(report)
|
||||
|
|
|
@ -279,7 +279,7 @@ class LogCaptureFixture(object):
|
|||
Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list
|
||||
are all interpolated.
|
||||
Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with
|
||||
levels, timestamps, etc, making exact comparisions more reliable.
|
||||
levels, timestamps, etc, making exact comparisons more reliable.
|
||||
|
||||
Note that traceback or stack info (from :func:`logging.exception` or the `exc_info` or `stack_info` arguments
|
||||
to the logging functions) is not included, as this is added by the formatter in the handler.
|
||||
|
|
|
@ -570,9 +570,7 @@ class Session(nodes.FSCollector):
|
|||
return True
|
||||
|
||||
def _tryconvertpyarg(self, x):
|
||||
"""Convert a dotted module name to path.
|
||||
|
||||
"""
|
||||
"""Convert a dotted module name to path."""
|
||||
try:
|
||||
with _patched_find_module():
|
||||
loader = pkgutil.find_loader(x)
|
||||
|
@ -604,8 +602,7 @@ class Session(nodes.FSCollector):
|
|||
raise UsageError(
|
||||
"file or package not found: " + arg + " (missing __init__.py?)"
|
||||
)
|
||||
else:
|
||||
raise UsageError("file not found: " + arg)
|
||||
raise UsageError("file not found: " + arg)
|
||||
parts[0] = path
|
||||
return parts
|
||||
|
||||
|
|
|
@ -100,6 +100,26 @@ else:
|
|||
_max = max
|
||||
|
||||
|
||||
def _force_symlink(root, target, link_to):
|
||||
"""helper to create the current symlink
|
||||
|
||||
its full of race conditions that are reasonably ok to ignore
|
||||
for the contex of best effort linking to the latest testrun
|
||||
|
||||
the presumption being thatin case of much parallelism
|
||||
the inaccuracy is going to be acceptable
|
||||
"""
|
||||
current_symlink = root.joinpath(target)
|
||||
try:
|
||||
current_symlink.unlink()
|
||||
except OSError:
|
||||
pass
|
||||
try:
|
||||
current_symlink.symlink_to(link_to)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def make_numbered_dir(root, prefix):
|
||||
"""create a directory with a increased number as suffix for the given prefix"""
|
||||
for i in range(10):
|
||||
|
@ -112,6 +132,7 @@ def make_numbered_dir(root, prefix):
|
|||
except Exception:
|
||||
pass
|
||||
else:
|
||||
_force_symlink(root, prefix + "current", new_path)
|
||||
return new_path
|
||||
else:
|
||||
raise EnvironmentError(
|
||||
|
|
|
@ -17,7 +17,7 @@ from weakref import WeakKeyDictionary
|
|||
|
||||
from _pytest.capture import MultiCapture, SysCapture
|
||||
from _pytest._code import Source
|
||||
from _pytest.main import Session, EXIT_OK
|
||||
from _pytest.main import Session, EXIT_INTERRUPTED, EXIT_OK
|
||||
from _pytest.assertion.rewrite import AssertionRewritingHook
|
||||
from _pytest.pathlib import Path
|
||||
from _pytest.compat import safe_str
|
||||
|
@ -857,7 +857,7 @@ class Testdir(object):
|
|||
|
||||
# typically we reraise keyboard interrupts from the child run
|
||||
# because it's our user requesting interruption of the testing
|
||||
if ret == 2 and not kwargs.get("no_reraise_ctrlc"):
|
||||
if ret == EXIT_INTERRUPTED and not kwargs.get("no_reraise_ctrlc"):
|
||||
calls = reprec.getcalls("pytest_keyboard_interrupt")
|
||||
if calls and calls[-1].excinfo.type == KeyboardInterrupt:
|
||||
raise KeyboardInterrupt()
|
||||
|
|
|
@ -30,6 +30,7 @@ def pytest_addoption(parser):
|
|||
|
||||
def pytest_terminal_summary(terminalreporter):
|
||||
durations = terminalreporter.config.option.durations
|
||||
verbose = terminalreporter.config.getvalue("verbose")
|
||||
if durations is None:
|
||||
return
|
||||
tr = terminalreporter
|
||||
|
@ -49,6 +50,10 @@ def pytest_terminal_summary(terminalreporter):
|
|||
dlist = dlist[:durations]
|
||||
|
||||
for rep in dlist:
|
||||
if verbose < 2 and rep.duration < 0.005:
|
||||
tr.write_line("")
|
||||
tr.write_line("(0.00 durations hidden. Use -vv to show these durations.)")
|
||||
break
|
||||
nodeid = rep.nodeid.replace("::()::", "::")
|
||||
tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid))
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ class TerminalReporter(object):
|
|||
char = {"xfailed": "x", "skipped": "s"}.get(char, char)
|
||||
return char in self.reportchars
|
||||
|
||||
def write_fspath_result(self, nodeid, res):
|
||||
def write_fspath_result(self, nodeid, res, **markup):
|
||||
fspath = self.config.rootdir.join(nodeid.split("::")[0])
|
||||
if fspath != self.currentfspath:
|
||||
if self.currentfspath is not None and self._show_progress_info:
|
||||
|
@ -272,7 +272,7 @@ class TerminalReporter(object):
|
|||
fspath = self.startdir.bestrelpath(fspath)
|
||||
self._tw.line()
|
||||
self._tw.write(fspath + " ")
|
||||
self._tw.write(res)
|
||||
self._tw.write(res, **markup)
|
||||
|
||||
def write_ensure_prefix(self, prefix, extra="", **kwargs):
|
||||
if self.currentfspath != prefix:
|
||||
|
@ -386,22 +386,22 @@ class TerminalReporter(object):
|
|||
# probably passed setup/teardown
|
||||
return
|
||||
running_xdist = hasattr(rep, "node")
|
||||
if markup is None:
|
||||
if rep.passed:
|
||||
markup = {"green": True}
|
||||
elif rep.failed:
|
||||
markup = {"red": True}
|
||||
elif rep.skipped:
|
||||
markup = {"yellow": True}
|
||||
else:
|
||||
markup = {}
|
||||
if self.verbosity <= 0:
|
||||
if not running_xdist and self.showfspath:
|
||||
self.write_fspath_result(rep.nodeid, letter)
|
||||
self.write_fspath_result(rep.nodeid, letter, **markup)
|
||||
else:
|
||||
self._tw.write(letter)
|
||||
self._tw.write(letter, **markup)
|
||||
else:
|
||||
self._progress_nodeids_reported.add(rep.nodeid)
|
||||
if markup is None:
|
||||
if rep.passed:
|
||||
markup = {"green": True}
|
||||
elif rep.failed:
|
||||
markup = {"red": True}
|
||||
elif rep.skipped:
|
||||
markup = {"yellow": True}
|
||||
else:
|
||||
markup = {}
|
||||
line = self._locationline(rep.nodeid, *rep.location)
|
||||
if not running_xdist:
|
||||
self.write_ensure_prefix(line, word, **markup)
|
||||
|
@ -676,7 +676,9 @@ class TerminalReporter(object):
|
|||
|
||||
if fspath:
|
||||
res = mkrel(nodeid).replace("::()", "") # parens-normalization
|
||||
if nodeid.split("::")[0] != fspath.replace("\\", nodes.SEP):
|
||||
if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace(
|
||||
"\\", nodes.SEP
|
||||
):
|
||||
res += " <- " + self.startdir.bestrelpath(fspath)
|
||||
else:
|
||||
res = "[location]"
|
||||
|
|
|
@ -12,6 +12,13 @@ import pytest
|
|||
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
|
||||
|
||||
|
||||
def prepend_pythonpath(*dirs):
|
||||
cur = os.getenv("PYTHONPATH")
|
||||
if cur:
|
||||
dirs += (cur,)
|
||||
return os.pathsep.join(str(p) for p in dirs)
|
||||
|
||||
|
||||
class TestGeneralUsage(object):
|
||||
def test_config_error(self, testdir):
|
||||
testdir.copy_example("conftest_usageerror/conftest.py")
|
||||
|
@ -590,14 +597,8 @@ class TestInvocationVariants(object):
|
|||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
||||
|
||||
def join_pythonpath(what):
|
||||
cur = os.environ.get("PYTHONPATH")
|
||||
if cur:
|
||||
return str(what) + os.pathsep + cur
|
||||
return what
|
||||
|
||||
empty_package = testdir.mkpydir("empty_package")
|
||||
monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(empty_package)))
|
||||
monkeypatch.setenv("PYTHONPATH", str(empty_package), prepend=os.pathsep)
|
||||
# the path which is not a package raises a warning on pypy;
|
||||
# no idea why only pypy and not normal python warn about it here
|
||||
with warnings.catch_warnings():
|
||||
|
@ -606,7 +607,7 @@ class TestInvocationVariants(object):
|
|||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
||||
|
||||
monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(testdir)))
|
||||
monkeypatch.setenv("PYTHONPATH", str(testdir), prepend=os.pathsep)
|
||||
result = testdir.runpytest("--pyargs", "tpkg.test_missing", syspathinsert=True)
|
||||
assert result.ret != 0
|
||||
result.stderr.fnmatch_lines(["*not*found*test_missing*"])
|
||||
|
@ -646,18 +647,13 @@ class TestInvocationVariants(object):
|
|||
# ├── __init__.py
|
||||
# └── test_world.py
|
||||
|
||||
def join_pythonpath(*dirs):
|
||||
cur = 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))
|
||||
# NOTE: the different/reversed ordering is intentional here.
|
||||
monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path))
|
||||
for p in search_path:
|
||||
monkeypatch.syspath_prepend(p)
|
||||
|
||||
# mixed module and filenames:
|
||||
os.chdir("world")
|
||||
monkeypatch.chdir("world")
|
||||
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(
|
||||
|
@ -708,8 +704,6 @@ class TestInvocationVariants(object):
|
|||
pytest.skip(six.text_type(e.args[0]))
|
||||
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
||||
|
||||
search_path = ["lib", os.path.join("local", "lib")]
|
||||
|
||||
dirname = "lib"
|
||||
d = testdir.mkdir(dirname)
|
||||
foo = d.mkdir("foo")
|
||||
|
@ -742,13 +736,9 @@ class TestInvocationVariants(object):
|
|||
# ├── conftest.py
|
||||
# └── test_bar.py
|
||||
|
||||
def join_pythonpath(*dirs):
|
||||
cur = os.getenv("PYTHONPATH")
|
||||
if cur:
|
||||
dirs += (cur,)
|
||||
return os.pathsep.join(str(p) for p in dirs)
|
||||
|
||||
monkeypatch.setenv("PYTHONPATH", join_pythonpath(*search_path))
|
||||
# NOTE: the different/reversed ordering is intentional here.
|
||||
search_path = ["lib", os.path.join("local", "lib")]
|
||||
monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path))
|
||||
for p in search_path:
|
||||
monkeypatch.syspath_prepend(p)
|
||||
|
||||
|
@ -760,16 +750,16 @@ class TestInvocationVariants(object):
|
|||
if hasattr(py.path.local, "mksymlinkto"):
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"lib/foo/bar/test_bar.py::test_bar <- local/lib/foo/bar/test_bar.py PASSED*",
|
||||
"lib/foo/bar/test_bar.py::test_other <- local/lib/foo/bar/test_bar.py PASSED*",
|
||||
"lib/foo/bar/test_bar.py::test_bar PASSED*",
|
||||
"lib/foo/bar/test_bar.py::test_other PASSED*",
|
||||
"*2 passed*",
|
||||
]
|
||||
)
|
||||
else:
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"local/lib/foo/bar/test_bar.py::test_bar PASSED*",
|
||||
"local/lib/foo/bar/test_bar.py::test_other PASSED*",
|
||||
"*lib/foo/bar/test_bar.py::test_bar PASSED*",
|
||||
"*lib/foo/bar/test_bar.py::test_other PASSED*",
|
||||
"*2 passed*",
|
||||
]
|
||||
)
|
||||
|
@ -846,7 +836,10 @@ class TestDurations(object):
|
|||
result = testdir.runpytest("--durations=10")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines_random(
|
||||
["*durations*", "*call*test_3*", "*call*test_2*", "*call*test_1*"]
|
||||
["*durations*", "*call*test_3*", "*call*test_2*"]
|
||||
)
|
||||
result.stdout.fnmatch_lines(
|
||||
["(0.00 durations hidden. Use -vv to show these durations.)"]
|
||||
)
|
||||
|
||||
def test_calls_show_2(self, testdir):
|
||||
|
@ -860,6 +853,18 @@ class TestDurations(object):
|
|||
testdir.makepyfile(self.source)
|
||||
result = testdir.runpytest("--durations=0")
|
||||
assert result.ret == 0
|
||||
for x in "23":
|
||||
for y in ("call",): # 'setup', 'call', 'teardown':
|
||||
for line in result.stdout.lines:
|
||||
if ("test_%s" % x) in line and y in line:
|
||||
break
|
||||
else:
|
||||
raise AssertionError("not found {} {}".format(x, y))
|
||||
|
||||
def test_calls_showall_verbose(self, testdir):
|
||||
testdir.makepyfile(self.source)
|
||||
result = testdir.runpytest("--durations=0", "-vv")
|
||||
assert result.ret == 0
|
||||
for x in "123":
|
||||
for y in ("call",): # 'setup', 'call', 'teardown':
|
||||
for line in result.stdout.lines:
|
||||
|
@ -870,9 +875,9 @@ class TestDurations(object):
|
|||
|
||||
def test_with_deselected(self, testdir):
|
||||
testdir.makepyfile(self.source)
|
||||
result = testdir.runpytest("--durations=2", "-k test_1")
|
||||
result = testdir.runpytest("--durations=2", "-k test_2")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*durations*", "*call*test_1*"])
|
||||
result.stdout.fnmatch_lines(["*durations*", "*call*test_2*"])
|
||||
|
||||
def test_with_failing_collection(self, testdir):
|
||||
testdir.makepyfile(self.source)
|
||||
|
@ -892,13 +897,15 @@ class TestDurations(object):
|
|||
|
||||
class TestDurationWithFixture(object):
|
||||
source = """
|
||||
import pytest
|
||||
import time
|
||||
frag = 0.001
|
||||
def setup_function(func):
|
||||
time.sleep(frag * 3)
|
||||
def test_1():
|
||||
time.sleep(frag*2)
|
||||
def test_2():
|
||||
frag = 0.01
|
||||
|
||||
@pytest.fixture
|
||||
def setup_fixt():
|
||||
time.sleep(frag)
|
||||
|
||||
def test_1(setup_fixt):
|
||||
time.sleep(frag)
|
||||
"""
|
||||
|
||||
|
|
|
@ -494,6 +494,12 @@ class TestRequestBasic(object):
|
|||
reason="this method of test doesn't work on pypy",
|
||||
)
|
||||
def test_request_garbage(self, testdir):
|
||||
try:
|
||||
import xdist # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
pytest.xfail("this test is flaky when executed with xdist")
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import sys
|
||||
|
|
|
@ -1222,3 +1222,19 @@ def test_set_suite_name(testdir, suite_name):
|
|||
assert result.ret == 0
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
node.assert_attr(name=expected)
|
||||
|
||||
|
||||
def test_escaped_skipreason_issue3533(testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import pytest
|
||||
@pytest.mark.skip(reason='1 <> 2')
|
||||
def test_skip():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
_, dom = runandparse(testdir)
|
||||
node = dom.find_first_by_tag("testcase")
|
||||
snode = node.find_first_by_tag("skipped")
|
||||
assert "1 <> 2" in snode.text
|
||||
snode.assert_attr(message="1 <> 2")
|
||||
|
|
|
@ -25,6 +25,8 @@ def custom_pdb_calls():
|
|||
|
||||
# install dummy debugger class and track which methods were called on it
|
||||
class _CustomPdb(object):
|
||||
quitting = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
called.append("init")
|
||||
|
||||
|
@ -142,6 +144,9 @@ class TestPDB(object):
|
|||
def test_1():
|
||||
i = 0
|
||||
assert i == 1
|
||||
|
||||
def test_not_called_due_to_quit():
|
||||
pass
|
||||
"""
|
||||
)
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
|
@ -150,8 +155,9 @@ class TestPDB(object):
|
|||
child.expect("Pdb")
|
||||
child.sendeof()
|
||||
rest = child.read().decode("utf8")
|
||||
assert "1 failed" in rest
|
||||
assert "= 1 failed in" in rest
|
||||
assert "def test_1" not in rest
|
||||
assert "Exit: Quitting debugger" in rest
|
||||
self.flush(child)
|
||||
|
||||
@staticmethod
|
||||
|
@ -321,7 +327,7 @@ class TestPDB(object):
|
|||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
# child.expect(".*import pytest.*")
|
||||
child.expect("Pdb")
|
||||
child.sendeof()
|
||||
child.sendline("c")
|
||||
child.expect("1 error")
|
||||
self.flush(child)
|
||||
|
||||
|
@ -334,8 +340,20 @@ class TestPDB(object):
|
|||
)
|
||||
p1 = testdir.makepyfile("def test_func(): pass")
|
||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||
# child.expect(".*import pytest.*")
|
||||
child.expect("Pdb")
|
||||
|
||||
# INTERNALERROR is only displayed once via terminal reporter.
|
||||
assert (
|
||||
len(
|
||||
[
|
||||
x
|
||||
for x in child.before.decode().splitlines()
|
||||
if x.startswith("INTERNALERROR> Traceback")
|
||||
]
|
||||
)
|
||||
== 1
|
||||
)
|
||||
|
||||
child.sendeof()
|
||||
self.flush(child)
|
||||
|
||||
|
@ -345,7 +363,7 @@ class TestPDB(object):
|
|||
import pytest
|
||||
def test_1():
|
||||
i = 0
|
||||
print ("hello17")
|
||||
print("hello17")
|
||||
pytest.set_trace()
|
||||
x = 3
|
||||
"""
|
||||
|
@ -376,6 +394,7 @@ class TestPDB(object):
|
|||
rest = child.read().decode("utf8")
|
||||
assert "1 failed" in rest
|
||||
assert "reading from stdin while output" not in rest
|
||||
assert "BdbQuit" in rest
|
||||
self.flush(child)
|
||||
|
||||
def test_pdb_and_capsys(self, testdir):
|
||||
|
@ -383,7 +402,7 @@ class TestPDB(object):
|
|||
"""
|
||||
import pytest
|
||||
def test_1(capsys):
|
||||
print ("hello1")
|
||||
print("hello1")
|
||||
pytest.set_trace()
|
||||
"""
|
||||
)
|
||||
|
@ -420,7 +439,7 @@ class TestPDB(object):
|
|||
def test_1():
|
||||
pdb.set_trace()
|
||||
def test_2():
|
||||
print ("hello")
|
||||
print("hello")
|
||||
assert 0
|
||||
"""
|
||||
)
|
||||
|
@ -461,10 +480,10 @@ class TestPDB(object):
|
|||
import pytest
|
||||
def test_1():
|
||||
i = 0
|
||||
print ("hello17")
|
||||
print("hello17")
|
||||
pytest.set_trace()
|
||||
x = 3
|
||||
print ("hello18")
|
||||
print("hello18")
|
||||
pytest.set_trace()
|
||||
x = 4
|
||||
"""
|
||||
|
@ -518,14 +537,16 @@ class TestPDB(object):
|
|||
def test_pdb_collection_failure_is_shown(self, testdir):
|
||||
p1 = testdir.makepyfile("xxx")
|
||||
result = testdir.runpytest_subprocess("--pdb", p1)
|
||||
result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"])
|
||||
result.stdout.fnmatch_lines(
|
||||
["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF
|
||||
)
|
||||
|
||||
def test_enter_pdb_hook_is_called(self, testdir):
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
def pytest_enter_pdb(config):
|
||||
assert config.testing_verification == 'configured'
|
||||
print 'enter_pdb_hook'
|
||||
print('enter_pdb_hook')
|
||||
|
||||
def pytest_configure(config):
|
||||
config.testing_verification = 'configured'
|
||||
|
@ -562,7 +583,7 @@ class TestPDB(object):
|
|||
custom_pdb="""
|
||||
class CustomPdb(object):
|
||||
def set_trace(*args, **kwargs):
|
||||
print 'custom set_trace>'
|
||||
print('custom set_trace>')
|
||||
"""
|
||||
)
|
||||
p1 = testdir.makepyfile(
|
||||
|
|
|
@ -154,7 +154,7 @@ class TestTerminal(object):
|
|||
)
|
||||
result = testdir.runpytest(p2)
|
||||
result.stdout.fnmatch_lines(["*test_p2.py .*", "*1 passed*"])
|
||||
result = testdir.runpytest("-v", p2)
|
||||
result = testdir.runpytest("-vv", p2)
|
||||
result.stdout.fnmatch_lines(
|
||||
["*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED*"]
|
||||
)
|
||||
|
@ -170,7 +170,7 @@ class TestTerminal(object):
|
|||
"""
|
||||
)
|
||||
)
|
||||
result = testdir.runpytest("-v")
|
||||
result = testdir.runpytest("-vv")
|
||||
assert result.ret == 0
|
||||
result.stdout.fnmatch_lines(["*a123/test_hello123.py*PASS*"])
|
||||
assert " <- " not in result.stdout.str()
|
||||
|
|
|
@ -196,6 +196,12 @@ class TestNumberedDir(object):
|
|||
assert d.name.startswith(self.PREFIX)
|
||||
assert d.name.endswith(str(i))
|
||||
|
||||
symlink = tmp_path.joinpath(self.PREFIX + "current")
|
||||
if symlink.exists():
|
||||
# unix
|
||||
assert symlink.is_symlink()
|
||||
assert symlink.resolve() == d.resolve()
|
||||
|
||||
def test_cleanup_lock_create(self, tmp_path):
|
||||
d = tmp_path.joinpath("test")
|
||||
d.mkdir()
|
||||
|
@ -244,7 +250,7 @@ class TestNumberedDir(object):
|
|||
|
||||
def test_cleanup_keep(self, tmp_path):
|
||||
self._do_cleanup(tmp_path)
|
||||
a, b = tmp_path.iterdir()
|
||||
a, b = (x for x in tmp_path.iterdir() if not x.is_symlink())
|
||||
print(a, b)
|
||||
|
||||
def test_cleanup_locked(self, tmp_path):
|
||||
|
|
27
tox.ini
27
tox.ini
|
@ -18,10 +18,10 @@ envlist =
|
|||
|
||||
[testenv]
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof -ra {posargs:testing}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof
|
||||
coverage: coverage combine
|
||||
coverage: coverage report
|
||||
passenv = USER USERNAME
|
||||
passenv = USER USERNAME COVERAGE_* TRAVIS
|
||||
setenv =
|
||||
# configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage"
|
||||
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
||||
|
@ -36,14 +36,12 @@ deps =
|
|||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
|
||||
[testenv:py27-subprocess]
|
||||
changedir = .
|
||||
deps =
|
||||
pytest-xdist>=1.13
|
||||
py27: mock
|
||||
nose
|
||||
passenv = USER USERNAME TRAVIS
|
||||
commands =
|
||||
pytest -n auto -ra --runpytest=subprocess {posargs:testing}
|
||||
pytest -n auto --runpytest=subprocess
|
||||
|
||||
|
||||
[testenv:linting]
|
||||
|
@ -59,9 +57,8 @@ deps =
|
|||
nose
|
||||
hypothesis>=3.56
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
passenv = USER USERNAME TRAVIS
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:testing}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto
|
||||
|
||||
[testenv:py36-xdist]
|
||||
# NOTE: copied from above due to https://github.com/tox-dev/tox/issues/706.
|
||||
|
@ -74,16 +71,14 @@ deps =
|
|||
commands = {[testenv:py27-xdist]commands}
|
||||
|
||||
[testenv:py27-pexpect]
|
||||
changedir = testing
|
||||
platform = linux|darwin
|
||||
deps =
|
||||
pexpect
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest testing/test_pdb.py testing/test_terminal.py testing/test_unittest.py {posargs}
|
||||
|
||||
[testenv:py36-pexpect]
|
||||
changedir = {[testenv:py27-pexpect]changedir}
|
||||
platform = {[testenv:py27-pexpect]platform}
|
||||
deps = {[testenv:py27-pexpect]deps}
|
||||
commands = {[testenv:py27-pexpect]commands}
|
||||
|
@ -95,20 +90,18 @@ deps =
|
|||
py27: mock
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
distribute = true
|
||||
changedir=testing
|
||||
setenv =
|
||||
{[testenv]setenv}
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
passenv = USER USERNAME TRAVIS
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:.}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs}
|
||||
|
||||
[testenv:py27-trial]
|
||||
deps =
|
||||
twisted
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/test_unittest.py}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:testing/test_unittest.py}
|
||||
|
||||
[testenv:py36-trial]
|
||||
deps = {[testenv:py27-trial]deps}
|
||||
|
@ -119,7 +112,7 @@ deps =
|
|||
numpy
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands=
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/python/approx.py}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:testing/python/approx.py}
|
||||
|
||||
[testenv:py36-numpy]
|
||||
deps = {[testenv:py27-numpy]deps}
|
||||
|
@ -154,7 +147,7 @@ deps =
|
|||
PyYAML
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra doc/en
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest doc/en
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest
|
||||
|
||||
[testenv:regen]
|
||||
|
@ -175,7 +168,7 @@ commands =
|
|||
[testenv:jython]
|
||||
changedir = testing
|
||||
commands =
|
||||
{envpython} {envbindir}/py.test-jython -ra {posargs}
|
||||
{envpython} {envbindir}/py.test-jython {posargs}
|
||||
|
||||
[testenv:py36-freeze]
|
||||
changedir = testing/freeze
|
||||
|
|
Loading…
Reference in New Issue