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
|
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):
|
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 `master` branch for bug fixes, documentation updates and trivial changes.
|
||||||
- [ ] Target the `features` branch for new features and removals/deprecations.
|
- [ ] Target the `features` branch for new features and removals/deprecations.
|
||||||
- [ ] Include documentation when adding new features.
|
- [ ] Include documentation when adding new features.
|
||||||
|
|
26
.travis.yml
26
.travis.yml
|
@ -12,19 +12,15 @@ install:
|
||||||
- pip install --upgrade --pre tox
|
- pip install --upgrade --pre tox
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
# note: please use "tox --listenvs" to populate the build matrix below
|
# Specialized factors for py27.
|
||||||
# please remove the linting env in all cases
|
- TOXENV=py27-pexpect,py27-trial,py27-numpy
|
||||||
- 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
|
|
||||||
- TOXENV=py27-nobyte
|
- 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:
|
jobs:
|
||||||
include:
|
include:
|
||||||
|
@ -97,12 +93,6 @@ after_success:
|
||||||
coverage xml --ignore-errors
|
coverage xml --ignore-errors
|
||||||
coverage report -m --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"
|
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
|
fi
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
|
|
2
AUTHORS
2
AUTHORS
|
@ -204,6 +204,7 @@ Stefan Zimmermann
|
||||||
Stefano Taschini
|
Stefano Taschini
|
||||||
Steffen Allner
|
Steffen Allner
|
||||||
Stephan Obermann
|
Stephan Obermann
|
||||||
|
Sven-Hendrik Haase
|
||||||
Tadek Teleżyński
|
Tadek Teleżyński
|
||||||
Tarcisio Fischer
|
Tarcisio Fischer
|
||||||
Tareq Alayan
|
Tareq Alayan
|
||||||
|
@ -213,6 +214,7 @@ Thomas Hisch
|
||||||
Tim Strazny
|
Tim Strazny
|
||||||
Tom Dalton
|
Tom Dalton
|
||||||
Tom Viner
|
Tom Viner
|
||||||
|
Tomer Keren
|
||||||
Trevor Bekolay
|
Trevor Bekolay
|
||||||
Tyler Goodlet
|
Tyler Goodlet
|
||||||
Tzu-ping Chung
|
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
|
.. 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)
|
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
|
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
|
Joining the Development Team
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
26
appveyor.yml
26
appveyor.yml
|
@ -1,27 +1,29 @@
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- TOXENV: "linting,docs,doctesting"
|
|
||||||
PYTEST_NO_COVERAGE: "1"
|
|
||||||
- TOXENV: "py27"
|
- TOXENV: "py27"
|
||||||
- TOXENV: "py34"
|
|
||||||
- TOXENV: "py35"
|
|
||||||
- TOXENV: "py36"
|
|
||||||
- TOXENV: "py37"
|
- TOXENV: "py37"
|
||||||
|
PYTEST_NO_COVERAGE: "1"
|
||||||
|
- TOXENV: "linting,docs,doctesting"
|
||||||
|
- TOXENV: "py36"
|
||||||
|
- TOXENV: "py35"
|
||||||
|
- TOXENV: "py34"
|
||||||
- TOXENV: "pypy"
|
- TOXENV: "pypy"
|
||||||
PYTEST_NO_COVERAGE: "1"
|
PYTEST_NO_COVERAGE: "1"
|
||||||
- TOXENV: "py27-xdist"
|
# Specialized factors for py27.
|
||||||
- TOXENV: "py27-trial"
|
- TOXENV: "py27-trial,py27-numpy,py27-nobyte"
|
||||||
- TOXENV: "py27-numpy"
|
|
||||||
- TOXENV: "py27-pluggymaster"
|
- TOXENV: "py27-pluggymaster"
|
||||||
PYTEST_NO_COVERAGE: "1"
|
PYTEST_NO_COVERAGE: "1"
|
||||||
- TOXENV: "py36-xdist"
|
- TOXENV: "py27-xdist"
|
||||||
- TOXENV: "py36-trial"
|
# Specialized factors for py36.
|
||||||
- TOXENV: "py36-numpy"
|
- TOXENV: "py36-trial,py36-numpy"
|
||||||
- TOXENV: "py36-pluggymaster"
|
- TOXENV: "py36-pluggymaster"
|
||||||
PYTEST_NO_COVERAGE: "1"
|
PYTEST_NO_COVERAGE: "1"
|
||||||
- TOXENV: "py27-nobyte"
|
|
||||||
- TOXENV: "py36-freeze"
|
- TOXENV: "py36-freeze"
|
||||||
PYTEST_NO_COVERAGE: "1"
|
PYTEST_NO_COVERAGE: "1"
|
||||||
|
- TOXENV: "py36-xdist"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- echo Installed Pythons
|
- 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
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-3.9.1
|
||||||
|
release-3.9.0
|
||||||
release-3.8.2
|
release-3.8.2
|
||||||
release-3.8.1
|
release-3.8.1
|
||||||
release-3.8.0
|
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
|
See http://docs.python.org/library/warnings.html for information
|
||||||
on warning categories.
|
on warning categories.
|
||||||
tmpdir_factory
|
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
|
tmpdir
|
||||||
Return a temporary directory path object
|
Return a temporary directory path object
|
||||||
which is unique to each test function invocation,
|
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.
|
path object.
|
||||||
|
|
||||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
.. _`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
|
no tests ran in 0.12 seconds
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ This should be updated to make use of standard fixture mechanisms:
|
||||||
session.close()
|
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.
|
more information.
|
||||||
|
|
||||||
This has been documented as deprecated for years, but only now we are actually emitting deprecation warnings.
|
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
|
.. deprecated:: 3.9
|
||||||
|
|
||||||
Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector``
|
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.
|
collection.
|
||||||
|
|
||||||
This issue should affect only advanced plugins who create new collection types, so if you see this warning
|
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
|
.. code-block:: python
|
||||||
|
|
||||||
@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
|
@pytest.mark.parametrize("x, y", [(2, 4), (3, 9)])
|
||||||
def test_squared():
|
def test_squared(x, y):
|
||||||
assert x ** x == y
|
assert x ** x == y
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -574,7 +574,7 @@ We can run this::
|
||||||
file $REGENDOC_TMPDIR/b/test_error.py, line 1
|
file $REGENDOC_TMPDIR/b/test_error.py, line 1
|
||||||
def test_root(db): # no db here, will error out
|
def test_root(db): # no db here, will error out
|
||||||
E fixture 'db' not found
|
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.
|
> use 'pytest --fixtures [testpath]' for help on them.
|
||||||
|
|
||||||
$REGENDOC_TMPDIR/b/test_error.py:1
|
$REGENDOC_TMPDIR/b/test_error.py:1
|
||||||
|
|
|
@ -31,16 +31,37 @@ created in the `base temporary directory`_.
|
||||||
p = d / "hello.txt"
|
p = d / "hello.txt"
|
||||||
p.write_text(CONTENT)
|
p.write_text(CONTENT)
|
||||||
assert p.read_text() == CONTENT
|
assert p.read_text() == CONTENT
|
||||||
assert len(tmpdir.listdir()) == 1
|
assert len(list(tmp_path.iterdir())) == 1
|
||||||
assert 0
|
assert 0
|
||||||
|
|
||||||
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::
|
||||||
|
|
||||||
$ pytest test_tmp_path.py
|
$ 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
|
The ``tmp_path_factory`` fixture
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
|
@ -269,6 +269,7 @@ To get a list of the slowest 10 test durations::
|
||||||
|
|
||||||
pytest --durations=10
|
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
|
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
|
`-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python
|
||||||
documentation for other examples and advanced usage.
|
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`:
|
.. _`filterwarnings`:
|
||||||
|
|
||||||
``@pytest.mark.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")
|
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`_
|
*Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_
|
||||||
*plugin.*
|
*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
|
.. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter
|
||||||
.. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings
|
.. _`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`:
|
.. _`asserting warnings`:
|
||||||
|
|
||||||
|
@ -299,43 +323,6 @@ warnings, or index into it to get a particular recorded warning.
|
||||||
|
|
||||||
Full API: :class:`WarningsRecorder`.
|
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:
|
.. _internal-warnings:
|
||||||
|
|
||||||
|
|
|
@ -420,9 +420,21 @@ additionally it is possible to copy examples for a example folder before running
|
||||||
============================= warnings summary =============================
|
============================= warnings summary =============================
|
||||||
$REGENDOC_TMPDIR/test_example.py:4: PytestExperimentalApiWarning: testdir.copy_example is an experimental api that may change over time
|
$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")
|
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
|
-- 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
|
For more information about the result object that ``runpytest()`` returns, and
|
||||||
the methods that it provides please check out the :py:class:`RunResult
|
the methods that it provides please check out the :py:class:`RunResult
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = [
|
requires = [
|
||||||
# sync with setup.py until we discard non-pep-517/518
|
# sync with setup.py until we discard non-pep-517/518
|
||||||
"setuptools>=30.3",
|
"setuptools>=40.0",
|
||||||
"setuptools-scm",
|
"setuptools-scm",
|
||||||
"wheel",
|
"wheel",
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
name = pytest
|
name = pytest
|
||||||
description = pytest: simple powerful testing with Python
|
description = pytest: simple powerful testing with Python
|
||||||
long_description = file: README.rst
|
long_description = file: README.rst
|
||||||
url = "https://docs.pytest.org/en/latest/"
|
url = https://docs.pytest.org/en/latest/
|
||||||
project_urls =
|
project_urls =
|
||||||
Source=https://github.com/pytest-dev/pytest
|
Source=https://github.com/pytest-dev/pytest
|
||||||
Tracker=https://github.com/pytest-dev/pytest/issues
|
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():
|
def main():
|
||||||
setup(
|
setup(
|
||||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
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"},
|
package_dir={"": "src"},
|
||||||
install_requires=INSTALL_REQUIRES,
|
install_requires=INSTALL_REQUIRES,
|
||||||
)
|
)
|
||||||
|
|
|
@ -399,7 +399,7 @@ def _rewrite_test(config, fn):
|
||||||
finally:
|
finally:
|
||||||
del state._indecode
|
del state._indecode
|
||||||
try:
|
try:
|
||||||
tree = ast.parse(source)
|
tree = ast.parse(source, filename=fn.strpath)
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
# Let this pop up again in the real import.
|
# Let this pop up again in the real import.
|
||||||
state.trace("failed to parse: %r" % (fn,))
|
state.trace("failed to parse: %r" % (fn,))
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
""" interactive debugging with PDB, the Python Debugger. """
|
""" interactive debugging with PDB, the Python Debugger. """
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
import os
|
||||||
import pdb
|
import pdb
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
from doctest import UnexpectedException
|
from doctest import UnexpectedException
|
||||||
|
|
||||||
|
from _pytest import outcomes
|
||||||
from _pytest.config import hookimpl
|
from _pytest.config import hookimpl
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -109,9 +111,6 @@ class PdbInvoke(object):
|
||||||
_enter_pdb(node, call.excinfo, report)
|
_enter_pdb(node, call.excinfo, report)
|
||||||
|
|
||||||
def pytest_internalerror(self, excrepr, excinfo):
|
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)
|
tb = _postmortem_traceback(excinfo)
|
||||||
post_mortem(tb)
|
post_mortem(tb)
|
||||||
|
|
||||||
|
@ -164,8 +163,9 @@ def _enter_pdb(node, excinfo, rep):
|
||||||
rep.toterminal(tw)
|
rep.toterminal(tw)
|
||||||
tw.sep(">", "entering PDB")
|
tw.sep(">", "entering PDB")
|
||||||
tb = _postmortem_traceback(excinfo)
|
tb = _postmortem_traceback(excinfo)
|
||||||
post_mortem(tb)
|
|
||||||
rep._pdbshown = True
|
rep._pdbshown = True
|
||||||
|
if post_mortem(tb):
|
||||||
|
outcomes.exit("Quitting debugger")
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,3 +196,4 @@ def post_mortem(t):
|
||||||
p = Pdb()
|
p = Pdb()
|
||||||
p.reset()
|
p.reset()
|
||||||
p.interaction(None, t)
|
p.interaction(None, t)
|
||||||
|
return p.quitting
|
||||||
|
|
|
@ -1371,7 +1371,6 @@ class FixtureManager(object):
|
||||||
fixturedefs = self._arg2fixturedefs[argname]
|
fixturedefs = self._arg2fixturedefs[argname]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
else:
|
|
||||||
return tuple(self._matchfactories(fixturedefs, nodeid))
|
return tuple(self._matchfactories(fixturedefs, nodeid))
|
||||||
|
|
||||||
def _matchfactories(self, fixturedefs, nodeid):
|
def _matchfactories(self, fixturedefs, nodeid):
|
||||||
|
|
|
@ -221,12 +221,14 @@ class _NodeReporter(object):
|
||||||
else:
|
else:
|
||||||
filename, lineno, skipreason = report.longrepr
|
filename, lineno, skipreason = report.longrepr
|
||||||
if skipreason.startswith("Skipped: "):
|
if skipreason.startswith("Skipped: "):
|
||||||
skipreason = bin_xml_escape(skipreason[9:])
|
skipreason = skipreason[9:]
|
||||||
|
details = "%s:%s: %s" % (filename, lineno, skipreason)
|
||||||
|
|
||||||
self.append(
|
self.append(
|
||||||
Junit.skipped(
|
Junit.skipped(
|
||||||
"%s:%s: %s" % (filename, lineno, skipreason),
|
bin_xml_escape(details),
|
||||||
type="pytest.skip",
|
type="pytest.skip",
|
||||||
message=skipreason,
|
message=bin_xml_escape(skipreason),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.write_captured_output(report)
|
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
|
Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list
|
||||||
are all interpolated.
|
are all interpolated.
|
||||||
Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with
|
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
|
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.
|
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
|
return True
|
||||||
|
|
||||||
def _tryconvertpyarg(self, x):
|
def _tryconvertpyarg(self, x):
|
||||||
"""Convert a dotted module name to path.
|
"""Convert a dotted module name to path."""
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
with _patched_find_module():
|
with _patched_find_module():
|
||||||
loader = pkgutil.find_loader(x)
|
loader = pkgutil.find_loader(x)
|
||||||
|
@ -604,7 +602,6 @@ class Session(nodes.FSCollector):
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"file or package not found: " + arg + " (missing __init__.py?)"
|
"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
|
parts[0] = path
|
||||||
return parts
|
return parts
|
||||||
|
|
|
@ -100,6 +100,26 @@ else:
|
||||||
_max = max
|
_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):
|
def make_numbered_dir(root, prefix):
|
||||||
"""create a directory with a increased number as suffix for the given prefix"""
|
"""create a directory with a increased number as suffix for the given prefix"""
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
|
@ -112,6 +132,7 @@ def make_numbered_dir(root, prefix):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
_force_symlink(root, prefix + "current", new_path)
|
||||||
return new_path
|
return new_path
|
||||||
else:
|
else:
|
||||||
raise EnvironmentError(
|
raise EnvironmentError(
|
||||||
|
|
|
@ -17,7 +17,7 @@ from weakref import WeakKeyDictionary
|
||||||
|
|
||||||
from _pytest.capture import MultiCapture, SysCapture
|
from _pytest.capture import MultiCapture, SysCapture
|
||||||
from _pytest._code import Source
|
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.assertion.rewrite import AssertionRewritingHook
|
||||||
from _pytest.pathlib import Path
|
from _pytest.pathlib import Path
|
||||||
from _pytest.compat import safe_str
|
from _pytest.compat import safe_str
|
||||||
|
@ -857,7 +857,7 @@ class Testdir(object):
|
||||||
|
|
||||||
# typically we reraise keyboard interrupts from the child run
|
# typically we reraise keyboard interrupts from the child run
|
||||||
# because it's our user requesting interruption of the testing
|
# 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")
|
calls = reprec.getcalls("pytest_keyboard_interrupt")
|
||||||
if calls and calls[-1].excinfo.type == KeyboardInterrupt:
|
if calls and calls[-1].excinfo.type == KeyboardInterrupt:
|
||||||
raise KeyboardInterrupt()
|
raise KeyboardInterrupt()
|
||||||
|
|
|
@ -30,6 +30,7 @@ def pytest_addoption(parser):
|
||||||
|
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
durations = terminalreporter.config.option.durations
|
durations = terminalreporter.config.option.durations
|
||||||
|
verbose = terminalreporter.config.getvalue("verbose")
|
||||||
if durations is None:
|
if durations is None:
|
||||||
return
|
return
|
||||||
tr = terminalreporter
|
tr = terminalreporter
|
||||||
|
@ -49,6 +50,10 @@ def pytest_terminal_summary(terminalreporter):
|
||||||
dlist = dlist[:durations]
|
dlist = dlist[:durations]
|
||||||
|
|
||||||
for rep in dlist:
|
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("::()::", "::")
|
nodeid = rep.nodeid.replace("::()::", "::")
|
||||||
tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid))
|
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)
|
char = {"xfailed": "x", "skipped": "s"}.get(char, char)
|
||||||
return char in self.reportchars
|
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])
|
fspath = self.config.rootdir.join(nodeid.split("::")[0])
|
||||||
if fspath != self.currentfspath:
|
if fspath != self.currentfspath:
|
||||||
if self.currentfspath is not None and self._show_progress_info:
|
if self.currentfspath is not None and self._show_progress_info:
|
||||||
|
@ -272,7 +272,7 @@ class TerminalReporter(object):
|
||||||
fspath = self.startdir.bestrelpath(fspath)
|
fspath = self.startdir.bestrelpath(fspath)
|
||||||
self._tw.line()
|
self._tw.line()
|
||||||
self._tw.write(fspath + " ")
|
self._tw.write(fspath + " ")
|
||||||
self._tw.write(res)
|
self._tw.write(res, **markup)
|
||||||
|
|
||||||
def write_ensure_prefix(self, prefix, extra="", **kwargs):
|
def write_ensure_prefix(self, prefix, extra="", **kwargs):
|
||||||
if self.currentfspath != prefix:
|
if self.currentfspath != prefix:
|
||||||
|
@ -386,13 +386,6 @@ class TerminalReporter(object):
|
||||||
# probably passed setup/teardown
|
# probably passed setup/teardown
|
||||||
return
|
return
|
||||||
running_xdist = hasattr(rep, "node")
|
running_xdist = hasattr(rep, "node")
|
||||||
if self.verbosity <= 0:
|
|
||||||
if not running_xdist and self.showfspath:
|
|
||||||
self.write_fspath_result(rep.nodeid, letter)
|
|
||||||
else:
|
|
||||||
self._tw.write(letter)
|
|
||||||
else:
|
|
||||||
self._progress_nodeids_reported.add(rep.nodeid)
|
|
||||||
if markup is None:
|
if markup is None:
|
||||||
if rep.passed:
|
if rep.passed:
|
||||||
markup = {"green": True}
|
markup = {"green": True}
|
||||||
|
@ -402,6 +395,13 @@ class TerminalReporter(object):
|
||||||
markup = {"yellow": True}
|
markup = {"yellow": True}
|
||||||
else:
|
else:
|
||||||
markup = {}
|
markup = {}
|
||||||
|
if self.verbosity <= 0:
|
||||||
|
if not running_xdist and self.showfspath:
|
||||||
|
self.write_fspath_result(rep.nodeid, letter, **markup)
|
||||||
|
else:
|
||||||
|
self._tw.write(letter, **markup)
|
||||||
|
else:
|
||||||
|
self._progress_nodeids_reported.add(rep.nodeid)
|
||||||
line = self._locationline(rep.nodeid, *rep.location)
|
line = self._locationline(rep.nodeid, *rep.location)
|
||||||
if not running_xdist:
|
if not running_xdist:
|
||||||
self.write_ensure_prefix(line, word, **markup)
|
self.write_ensure_prefix(line, word, **markup)
|
||||||
|
@ -676,7 +676,9 @@ class TerminalReporter(object):
|
||||||
|
|
||||||
if fspath:
|
if fspath:
|
||||||
res = mkrel(nodeid).replace("::()", "") # parens-normalization
|
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)
|
res += " <- " + self.startdir.bestrelpath(fspath)
|
||||||
else:
|
else:
|
||||||
res = "[location]"
|
res = "[location]"
|
||||||
|
|
|
@ -12,6 +12,13 @@ import pytest
|
||||||
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
|
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):
|
class TestGeneralUsage(object):
|
||||||
def test_config_error(self, testdir):
|
def test_config_error(self, testdir):
|
||||||
testdir.copy_example("conftest_usageerror/conftest.py")
|
testdir.copy_example("conftest_usageerror/conftest.py")
|
||||||
|
@ -590,14 +597,8 @@ class TestInvocationVariants(object):
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines(["*1 passed*"])
|
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")
|
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;
|
# 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
|
# no idea why only pypy and not normal python warn about it here
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
@ -606,7 +607,7 @@ class TestInvocationVariants(object):
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines(["*2 passed*"])
|
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)
|
result = testdir.runpytest("--pyargs", "tpkg.test_missing", syspathinsert=True)
|
||||||
assert result.ret != 0
|
assert result.ret != 0
|
||||||
result.stderr.fnmatch_lines(["*not*found*test_missing*"])
|
result.stderr.fnmatch_lines(["*not*found*test_missing*"])
|
||||||
|
@ -646,18 +647,13 @@ class TestInvocationVariants(object):
|
||||||
# ├── __init__.py
|
# ├── __init__.py
|
||||||
# └── test_world.py
|
# └── test_world.py
|
||||||
|
|
||||||
def join_pythonpath(*dirs):
|
# NOTE: the different/reversed ordering is intentional here.
|
||||||
cur = os.environ.get("PYTHONPATH")
|
monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path))
|
||||||
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:
|
for p in search_path:
|
||||||
monkeypatch.syspath_prepend(p)
|
monkeypatch.syspath_prepend(p)
|
||||||
|
|
||||||
# mixed module and filenames:
|
# mixed module and filenames:
|
||||||
os.chdir("world")
|
monkeypatch.chdir("world")
|
||||||
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world")
|
result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
|
@ -708,8 +704,6 @@ class TestInvocationVariants(object):
|
||||||
pytest.skip(six.text_type(e.args[0]))
|
pytest.skip(six.text_type(e.args[0]))
|
||||||
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False)
|
||||||
|
|
||||||
search_path = ["lib", os.path.join("local", "lib")]
|
|
||||||
|
|
||||||
dirname = "lib"
|
dirname = "lib"
|
||||||
d = testdir.mkdir(dirname)
|
d = testdir.mkdir(dirname)
|
||||||
foo = d.mkdir("foo")
|
foo = d.mkdir("foo")
|
||||||
|
@ -742,13 +736,9 @@ class TestInvocationVariants(object):
|
||||||
# ├── conftest.py
|
# ├── conftest.py
|
||||||
# └── test_bar.py
|
# └── test_bar.py
|
||||||
|
|
||||||
def join_pythonpath(*dirs):
|
# NOTE: the different/reversed ordering is intentional here.
|
||||||
cur = os.getenv("PYTHONPATH")
|
search_path = ["lib", os.path.join("local", "lib")]
|
||||||
if cur:
|
monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path))
|
||||||
dirs += (cur,)
|
|
||||||
return os.pathsep.join(str(p) for p in dirs)
|
|
||||||
|
|
||||||
monkeypatch.setenv("PYTHONPATH", join_pythonpath(*search_path))
|
|
||||||
for p in search_path:
|
for p in search_path:
|
||||||
monkeypatch.syspath_prepend(p)
|
monkeypatch.syspath_prepend(p)
|
||||||
|
|
||||||
|
@ -760,16 +750,16 @@ class TestInvocationVariants(object):
|
||||||
if hasattr(py.path.local, "mksymlinkto"):
|
if hasattr(py.path.local, "mksymlinkto"):
|
||||||
result.stdout.fnmatch_lines(
|
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_bar PASSED*",
|
||||||
"lib/foo/bar/test_bar.py::test_other <- local/lib/foo/bar/test_bar.py PASSED*",
|
"lib/foo/bar/test_bar.py::test_other PASSED*",
|
||||||
"*2 passed*",
|
"*2 passed*",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
[
|
[
|
||||||
"local/lib/foo/bar/test_bar.py::test_bar PASSED*",
|
"*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_other PASSED*",
|
||||||
"*2 passed*",
|
"*2 passed*",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -846,7 +836,10 @@ class TestDurations(object):
|
||||||
result = testdir.runpytest("--durations=10")
|
result = testdir.runpytest("--durations=10")
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines_random(
|
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):
|
def test_calls_show_2(self, testdir):
|
||||||
|
@ -860,6 +853,18 @@ class TestDurations(object):
|
||||||
testdir.makepyfile(self.source)
|
testdir.makepyfile(self.source)
|
||||||
result = testdir.runpytest("--durations=0")
|
result = testdir.runpytest("--durations=0")
|
||||||
assert result.ret == 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 x in "123":
|
||||||
for y in ("call",): # 'setup', 'call', 'teardown':
|
for y in ("call",): # 'setup', 'call', 'teardown':
|
||||||
for line in result.stdout.lines:
|
for line in result.stdout.lines:
|
||||||
|
@ -870,9 +875,9 @@ class TestDurations(object):
|
||||||
|
|
||||||
def test_with_deselected(self, testdir):
|
def test_with_deselected(self, testdir):
|
||||||
testdir.makepyfile(self.source)
|
testdir.makepyfile(self.source)
|
||||||
result = testdir.runpytest("--durations=2", "-k test_1")
|
result = testdir.runpytest("--durations=2", "-k test_2")
|
||||||
assert result.ret == 0
|
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):
|
def test_with_failing_collection(self, testdir):
|
||||||
testdir.makepyfile(self.source)
|
testdir.makepyfile(self.source)
|
||||||
|
@ -892,13 +897,15 @@ class TestDurations(object):
|
||||||
|
|
||||||
class TestDurationWithFixture(object):
|
class TestDurationWithFixture(object):
|
||||||
source = """
|
source = """
|
||||||
|
import pytest
|
||||||
import time
|
import time
|
||||||
frag = 0.001
|
frag = 0.01
|
||||||
def setup_function(func):
|
|
||||||
time.sleep(frag * 3)
|
@pytest.fixture
|
||||||
def test_1():
|
def setup_fixt():
|
||||||
time.sleep(frag*2)
|
time.sleep(frag)
|
||||||
def test_2():
|
|
||||||
|
def test_1(setup_fixt):
|
||||||
time.sleep(frag)
|
time.sleep(frag)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -494,6 +494,12 @@ class TestRequestBasic(object):
|
||||||
reason="this method of test doesn't work on pypy",
|
reason="this method of test doesn't work on pypy",
|
||||||
)
|
)
|
||||||
def test_request_garbage(self, testdir):
|
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(
|
testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1222,3 +1222,19 @@ def test_set_suite_name(testdir, suite_name):
|
||||||
assert result.ret == 0
|
assert result.ret == 0
|
||||||
node = dom.find_first_by_tag("testsuite")
|
node = dom.find_first_by_tag("testsuite")
|
||||||
node.assert_attr(name=expected)
|
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
|
# install dummy debugger class and track which methods were called on it
|
||||||
class _CustomPdb(object):
|
class _CustomPdb(object):
|
||||||
|
quitting = False
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
called.append("init")
|
called.append("init")
|
||||||
|
|
||||||
|
@ -142,6 +144,9 @@ class TestPDB(object):
|
||||||
def test_1():
|
def test_1():
|
||||||
i = 0
|
i = 0
|
||||||
assert i == 1
|
assert i == 1
|
||||||
|
|
||||||
|
def test_not_called_due_to_quit():
|
||||||
|
pass
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||||
|
@ -150,8 +155,9 @@ class TestPDB(object):
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendeof()
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "= 1 failed in" in rest
|
||||||
assert "def test_1" not in rest
|
assert "def test_1" not in rest
|
||||||
|
assert "Exit: Quitting debugger" in rest
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -321,7 +327,7 @@ class TestPDB(object):
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||||
# child.expect(".*import pytest.*")
|
# child.expect(".*import pytest.*")
|
||||||
child.expect("Pdb")
|
child.expect("Pdb")
|
||||||
child.sendeof()
|
child.sendline("c")
|
||||||
child.expect("1 error")
|
child.expect("1 error")
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
|
@ -334,8 +340,20 @@ class TestPDB(object):
|
||||||
)
|
)
|
||||||
p1 = testdir.makepyfile("def test_func(): pass")
|
p1 = testdir.makepyfile("def test_func(): pass")
|
||||||
child = testdir.spawn_pytest("--pdb %s" % p1)
|
child = testdir.spawn_pytest("--pdb %s" % p1)
|
||||||
# child.expect(".*import pytest.*")
|
|
||||||
child.expect("Pdb")
|
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()
|
child.sendeof()
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
|
@ -376,6 +394,7 @@ class TestPDB(object):
|
||||||
rest = child.read().decode("utf8")
|
rest = child.read().decode("utf8")
|
||||||
assert "1 failed" in rest
|
assert "1 failed" in rest
|
||||||
assert "reading from stdin while output" not in rest
|
assert "reading from stdin while output" not in rest
|
||||||
|
assert "BdbQuit" in rest
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
def test_pdb_and_capsys(self, testdir):
|
def test_pdb_and_capsys(self, testdir):
|
||||||
|
@ -518,14 +537,16 @@ class TestPDB(object):
|
||||||
def test_pdb_collection_failure_is_shown(self, testdir):
|
def test_pdb_collection_failure_is_shown(self, testdir):
|
||||||
p1 = testdir.makepyfile("xxx")
|
p1 = testdir.makepyfile("xxx")
|
||||||
result = testdir.runpytest_subprocess("--pdb", p1)
|
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):
|
def test_enter_pdb_hook_is_called(self, testdir):
|
||||||
testdir.makeconftest(
|
testdir.makeconftest(
|
||||||
"""
|
"""
|
||||||
def pytest_enter_pdb(config):
|
def pytest_enter_pdb(config):
|
||||||
assert config.testing_verification == 'configured'
|
assert config.testing_verification == 'configured'
|
||||||
print 'enter_pdb_hook'
|
print('enter_pdb_hook')
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
config.testing_verification = 'configured'
|
config.testing_verification = 'configured'
|
||||||
|
@ -562,7 +583,7 @@ class TestPDB(object):
|
||||||
custom_pdb="""
|
custom_pdb="""
|
||||||
class CustomPdb(object):
|
class CustomPdb(object):
|
||||||
def set_trace(*args, **kwargs):
|
def set_trace(*args, **kwargs):
|
||||||
print 'custom set_trace>'
|
print('custom set_trace>')
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
p1 = testdir.makepyfile(
|
p1 = testdir.makepyfile(
|
||||||
|
|
|
@ -154,7 +154,7 @@ class TestTerminal(object):
|
||||||
)
|
)
|
||||||
result = testdir.runpytest(p2)
|
result = testdir.runpytest(p2)
|
||||||
result.stdout.fnmatch_lines(["*test_p2.py .*", "*1 passed*"])
|
result.stdout.fnmatch_lines(["*test_p2.py .*", "*1 passed*"])
|
||||||
result = testdir.runpytest("-v", p2)
|
result = testdir.runpytest("-vv", p2)
|
||||||
result.stdout.fnmatch_lines(
|
result.stdout.fnmatch_lines(
|
||||||
["*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED*"]
|
["*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
|
assert result.ret == 0
|
||||||
result.stdout.fnmatch_lines(["*a123/test_hello123.py*PASS*"])
|
result.stdout.fnmatch_lines(["*a123/test_hello123.py*PASS*"])
|
||||||
assert " <- " not in result.stdout.str()
|
assert " <- " not in result.stdout.str()
|
||||||
|
|
|
@ -196,6 +196,12 @@ class TestNumberedDir(object):
|
||||||
assert d.name.startswith(self.PREFIX)
|
assert d.name.startswith(self.PREFIX)
|
||||||
assert d.name.endswith(str(i))
|
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):
|
def test_cleanup_lock_create(self, tmp_path):
|
||||||
d = tmp_path.joinpath("test")
|
d = tmp_path.joinpath("test")
|
||||||
d.mkdir()
|
d.mkdir()
|
||||||
|
@ -244,7 +250,7 @@ class TestNumberedDir(object):
|
||||||
|
|
||||||
def test_cleanup_keep(self, tmp_path):
|
def test_cleanup_keep(self, tmp_path):
|
||||||
self._do_cleanup(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)
|
print(a, b)
|
||||||
|
|
||||||
def test_cleanup_locked(self, tmp_path):
|
def test_cleanup_locked(self, tmp_path):
|
||||||
|
|
27
tox.ini
27
tox.ini
|
@ -18,10 +18,10 @@ envlist =
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands =
|
commands =
|
||||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof -ra {posargs:testing}
|
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof
|
||||||
coverage: coverage combine
|
coverage: coverage combine
|
||||||
coverage: coverage report
|
coverage: coverage report
|
||||||
passenv = USER USERNAME
|
passenv = USER USERNAME COVERAGE_* TRAVIS
|
||||||
setenv =
|
setenv =
|
||||||
# configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage"
|
# configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage"
|
||||||
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
||||||
|
@ -36,14 +36,12 @@ deps =
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
|
|
||||||
[testenv:py27-subprocess]
|
[testenv:py27-subprocess]
|
||||||
changedir = .
|
|
||||||
deps =
|
deps =
|
||||||
pytest-xdist>=1.13
|
pytest-xdist>=1.13
|
||||||
py27: mock
|
py27: mock
|
||||||
nose
|
nose
|
||||||
passenv = USER USERNAME TRAVIS
|
|
||||||
commands =
|
commands =
|
||||||
pytest -n auto -ra --runpytest=subprocess {posargs:testing}
|
pytest -n auto --runpytest=subprocess
|
||||||
|
|
||||||
|
|
||||||
[testenv:linting]
|
[testenv:linting]
|
||||||
|
@ -59,9 +57,8 @@ deps =
|
||||||
nose
|
nose
|
||||||
hypothesis>=3.56
|
hypothesis>=3.56
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
passenv = USER USERNAME TRAVIS
|
|
||||||
commands =
|
commands =
|
||||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:testing}
|
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto
|
||||||
|
|
||||||
[testenv:py36-xdist]
|
[testenv:py36-xdist]
|
||||||
# NOTE: copied from above due to https://github.com/tox-dev/tox/issues/706.
|
# NOTE: copied from above due to https://github.com/tox-dev/tox/issues/706.
|
||||||
|
@ -74,16 +71,14 @@ deps =
|
||||||
commands = {[testenv:py27-xdist]commands}
|
commands = {[testenv:py27-xdist]commands}
|
||||||
|
|
||||||
[testenv:py27-pexpect]
|
[testenv:py27-pexpect]
|
||||||
changedir = testing
|
|
||||||
platform = linux|darwin
|
platform = linux|darwin
|
||||||
deps =
|
deps =
|
||||||
pexpect
|
pexpect
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
commands =
|
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]
|
[testenv:py36-pexpect]
|
||||||
changedir = {[testenv:py27-pexpect]changedir}
|
|
||||||
platform = {[testenv:py27-pexpect]platform}
|
platform = {[testenv:py27-pexpect]platform}
|
||||||
deps = {[testenv:py27-pexpect]deps}
|
deps = {[testenv:py27-pexpect]deps}
|
||||||
commands = {[testenv:py27-pexpect]commands}
|
commands = {[testenv:py27-pexpect]commands}
|
||||||
|
@ -95,20 +90,18 @@ deps =
|
||||||
py27: mock
|
py27: mock
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
distribute = true
|
distribute = true
|
||||||
changedir=testing
|
|
||||||
setenv =
|
setenv =
|
||||||
{[testenv]setenv}
|
{[testenv]setenv}
|
||||||
PYTHONDONTWRITEBYTECODE=1
|
PYTHONDONTWRITEBYTECODE=1
|
||||||
passenv = USER USERNAME TRAVIS
|
|
||||||
commands =
|
commands =
|
||||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:.}
|
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs}
|
||||||
|
|
||||||
[testenv:py27-trial]
|
[testenv:py27-trial]
|
||||||
deps =
|
deps =
|
||||||
twisted
|
twisted
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
commands =
|
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]
|
[testenv:py36-trial]
|
||||||
deps = {[testenv:py27-trial]deps}
|
deps = {[testenv:py27-trial]deps}
|
||||||
|
@ -119,7 +112,7 @@ deps =
|
||||||
numpy
|
numpy
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
commands=
|
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]
|
[testenv:py36-numpy]
|
||||||
deps = {[testenv:py27-numpy]deps}
|
deps = {[testenv:py27-numpy]deps}
|
||||||
|
@ -154,7 +147,7 @@ deps =
|
||||||
PyYAML
|
PyYAML
|
||||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||||
commands =
|
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
|
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest
|
||||||
|
|
||||||
[testenv:regen]
|
[testenv:regen]
|
||||||
|
@ -175,7 +168,7 @@ commands =
|
||||||
[testenv:jython]
|
[testenv:jython]
|
||||||
changedir = testing
|
changedir = testing
|
||||||
commands =
|
commands =
|
||||||
{envpython} {envbindir}/py.test-jython -ra {posargs}
|
{envpython} {envbindir}/py.test-jython {posargs}
|
||||||
|
|
||||||
[testenv:py36-freeze]
|
[testenv:py36-freeze]
|
||||||
changedir = testing/freeze
|
changedir = testing/freeze
|
||||||
|
|
Loading…
Reference in New Issue