Merge pull request #3914 from nicoddemus/merge-master-into-features
Merge master into features
This commit is contained in:
commit
01df368d93
|
@ -1,4 +1,3 @@
|
|||
[run]
|
||||
omit =
|
||||
# standlonetemplate is read dynamically and tested by test_genscript
|
||||
*standalonetemplate.py
|
||||
source = _pytest,testing
|
||||
parallel = 1
|
||||
|
|
65
.travis.yml
65
.travis.yml
|
@ -1,8 +1,9 @@
|
|||
sudo: false
|
||||
language: python
|
||||
stages:
|
||||
- linting
|
||||
- test
|
||||
- baseline
|
||||
- name: test
|
||||
if: repo = pytest-dev/pytest AND tag IS NOT present
|
||||
- name: deploy
|
||||
if: repo = pytest-dev/pytest AND tag IS present
|
||||
python:
|
||||
|
@ -11,13 +12,8 @@ install:
|
|||
- pip install --upgrade --pre tox
|
||||
env:
|
||||
matrix:
|
||||
# coveralls is not listed in tox's envlist, but should run in travis
|
||||
- TOXENV=coveralls
|
||||
# note: please use "tox --listenvs" to populate the build matrix below
|
||||
# please remove the linting env in all cases
|
||||
- TOXENV=py27
|
||||
- TOXENV=py34
|
||||
- TOXENV=py36
|
||||
- TOXENV=py27-pexpect
|
||||
- TOXENV=py27-xdist
|
||||
- TOXENV=py27-trial
|
||||
|
@ -30,20 +26,42 @@ env:
|
|||
- TOXENV=py36-pluggymaster
|
||||
- TOXENV=py27-nobyte
|
||||
- TOXENV=doctesting
|
||||
- TOXENV=docs
|
||||
- TOXENV=docs PYTEST_NO_COVERAGE=1
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- env: TOXENV=pypy
|
||||
# Coverage tracking is slow with pypy, skip it.
|
||||
- env: TOXENV=pypy PYTEST_NO_COVERAGE=1
|
||||
python: 'pypy-5.4'
|
||||
- env: TOXENV=py35
|
||||
python: '3.5'
|
||||
- env: TOXENV=py36-freeze
|
||||
- env: TOXENV=py36-freeze PYTEST_NO_COVERAGE=1
|
||||
python: '3.6'
|
||||
- env: TOXENV=py37
|
||||
python: '3.7'
|
||||
sudo: required
|
||||
dist: xenial
|
||||
- &test-macos
|
||||
language: generic
|
||||
os: osx
|
||||
osx_image: xcode9.4
|
||||
sudo: required
|
||||
install:
|
||||
- python -m pip install --pre tox
|
||||
env: TOXENV=py27
|
||||
- <<: *test-macos
|
||||
env: TOXENV=py37
|
||||
before_install:
|
||||
- brew update
|
||||
- brew upgrade python
|
||||
- brew unlink python
|
||||
- brew link python
|
||||
|
||||
- stage: baseline
|
||||
env: TOXENV=py27
|
||||
- env: TOXENV=py34
|
||||
- env: TOXENV=py36
|
||||
- env: TOXENV=linting PYTEST_NO_COVERAGE=1
|
||||
|
||||
- stage: deploy
|
||||
python: '3.6'
|
||||
|
@ -60,12 +78,33 @@ jobs:
|
|||
on:
|
||||
tags: true
|
||||
repo: pytest-dev/pytest
|
||||
- stage: linting
|
||||
python: '3.6'
|
||||
env: TOXENV=linting
|
||||
|
||||
before_script:
|
||||
- |
|
||||
if [[ "$PYTEST_NO_COVERAGE" != 1 ]]; then
|
||||
export _PYTEST_TOX_COVERAGE_RUN="env COVERAGE_FILE=$PWD/.coverage COVERAGE_PROCESS_START=$PWD/.coveragerc coverage run --source {envsitepackagesdir}/_pytest/,$PWD/testing -m"
|
||||
export _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
|
||||
fi
|
||||
|
||||
script: tox --recreate
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [[ "$PYTEST_NO_COVERAGE" != 1 ]]; then
|
||||
set -e
|
||||
pip install codecov
|
||||
coverage combine
|
||||
coverage xml
|
||||
coverage report -m
|
||||
codecov --required -X gcov pycov search -f coverage.xml --flags ${TOXENV//-/ }
|
||||
|
||||
# Coveralls does not support merged reports.
|
||||
if [[ "$TOXENV" = py37 ]]; then
|
||||
pip install coveralls
|
||||
coveralls
|
||||
fi
|
||||
fi
|
||||
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
|
|
|
@ -18,6 +18,31 @@ with advance notice in the **Deprecations** section of releases.
|
|||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 3.7.4 (2018-08-29)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#3506 <https://github.com/pytest-dev/pytest/issues/3506>`_: Fix possible infinite recursion when writing ``.pyc`` files.
|
||||
|
||||
|
||||
- `#3853 <https://github.com/pytest-dev/pytest/issues/3853>`_: Cache plugin now obeys the ``-q`` flag when ``--last-failed`` and ``--failed-first`` flags are used.
|
||||
|
||||
|
||||
- `#3883 <https://github.com/pytest-dev/pytest/issues/3883>`_: Fix bad console output when using ``console_output_style=classic``.
|
||||
|
||||
|
||||
- `#3888 <https://github.com/pytest-dev/pytest/issues/3888>`_: Fix macOS specific code using ``capturemanager`` plugin in doctests.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#3902 <https://github.com/pytest-dev/pytest/issues/3902>`_: Fix pytest.org links
|
||||
|
||||
|
||||
pytest 3.7.3 (2018-08-26)
|
||||
=========================
|
||||
|
||||
|
|
|
@ -28,10 +28,13 @@ taking a lot of time to make a new one.
|
|||
|
||||
#. After all tests pass and the PR has been approved, publish to PyPI by pushing the tag::
|
||||
|
||||
git tag <VERSION>
|
||||
git push git@github.com:pytest-dev/pytest.git <VERSION>
|
||||
|
||||
Wait for the deploy to complete, then make sure it is `available on PyPI <https://pypi.org/project/pytest>`_.
|
||||
|
||||
#. Merge the PR into ``master``.
|
||||
|
||||
#. Send an email announcement with the contents from::
|
||||
|
||||
doc/en/announce/release-<VERSION>.rst
|
||||
|
|
20
README.rst
20
README.rst
|
@ -1,5 +1,5 @@
|
|||
.. image:: http://docs.pytest.org/en/latest/_static/pytest1.png
|
||||
:target: http://docs.pytest.org
|
||||
.. image:: https://docs.pytest.org/en/latest/_static/pytest1.png
|
||||
:target: https://docs.pytest.org/en/latest/
|
||||
:align: center
|
||||
:alt: pytest
|
||||
|
||||
|
@ -66,23 +66,23 @@ To execute it::
|
|||
========================== 1 failed in 0.04 seconds ===========================
|
||||
|
||||
|
||||
Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <http://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
|
||||
Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started <https://docs.pytest.org/en/latest/getting-started.html#our-first-test-run>`_ for more examples.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Detailed info on failing `assert statements <http://docs.pytest.org/en/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
|
||||
- Detailed info on failing `assert statements <https://docs.pytest.org/en/latest/assert.html>`_ (no need to remember ``self.assert*`` names);
|
||||
|
||||
- `Auto-discovery
|
||||
<http://docs.pytest.org/en/latest/goodpractices.html#python-test-discovery>`_
|
||||
<https://docs.pytest.org/en/latest/goodpractices.html#python-test-discovery>`_
|
||||
of test modules and functions;
|
||||
|
||||
- `Modular fixtures <http://docs.pytest.org/en/latest/fixture.html>`_ for
|
||||
- `Modular fixtures <https://docs.pytest.org/en/latest/fixture.html>`_ for
|
||||
managing small or parametrized long-lived test resources;
|
||||
|
||||
- Can run `unittest <http://docs.pytest.org/en/latest/unittest.html>`_ (or trial),
|
||||
`nose <http://docs.pytest.org/en/latest/nose.html>`_ test suites out of the box;
|
||||
- Can run `unittest <https://docs.pytest.org/en/latest/unittest.html>`_ (or trial),
|
||||
`nose <https://docs.pytest.org/en/latest/nose.html>`_ test suites out of the box;
|
||||
|
||||
- Python 2.7, Python 3.4+, PyPy 2.3, Jython 2.5 (untested);
|
||||
|
||||
|
@ -92,7 +92,7 @@ Features
|
|||
Documentation
|
||||
-------------
|
||||
|
||||
For full documentation, including installation, tutorials and PDF documents, please see http://docs.pytest.org.
|
||||
For full documentation, including installation, tutorials and PDF documents, please see https://docs.pytest.org/en/latest/.
|
||||
|
||||
|
||||
Bugs/Requests
|
||||
|
@ -104,7 +104,7 @@ Please use the `GitHub issue tracker <https://github.com/pytest-dev/pytest/issue
|
|||
Changelog
|
||||
---------
|
||||
|
||||
Consult the `Changelog <http://docs.pytest.org/en/latest/changelog.html>`__ page for fixes and enhancements of each version.
|
||||
Consult the `Changelog <https://docs.pytest.org/en/latest/changelog.html>`__ page for fixes and enhancements of each version.
|
||||
|
||||
|
||||
License
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Corrected type of the exceptions collection passed to ``xfail``: ``raises`` argument accepts a ``tuple`` instead of ``list``.
|
|
@ -6,6 +6,7 @@ Release announcements
|
|||
:maxdepth: 2
|
||||
|
||||
|
||||
release-3.7.4
|
||||
release-3.7.3
|
||||
release-3.7.2
|
||||
release-3.7.1
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
pytest-3.7.4
|
||||
=======================================
|
||||
|
||||
pytest 3.7.4 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:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Jiri Kuncar
|
||||
* Steve Piercy
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
|
@ -200,17 +200,17 @@ You can ask which markers exist for your test suite - the list includes our just
|
|||
$ pytest --markers
|
||||
@pytest.mark.webtest: mark a test as a webtest.
|
||||
|
||||
@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see http://pytest.org/latest/warnings.html#pytest-mark-filterwarnings
|
||||
@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings
|
||||
|
||||
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
||||
|
||||
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
|
||||
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see https://docs.pytest.org/en/latest/skipping.html
|
||||
|
||||
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
|
||||
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/latest/skipping.html
|
||||
|
||||
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
|
||||
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see https://docs.pytest.org/en/latest/parametrize.html for more info and examples.
|
||||
|
||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see https://docs.pytest.org/en/latest/fixture.html#usefixtures
|
||||
|
||||
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||
|
||||
|
@ -376,17 +376,17 @@ The ``--markers`` option always gives you a list of available markers::
|
|||
$ pytest --markers
|
||||
@pytest.mark.env(name): mark test to run only on named environment
|
||||
|
||||
@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see http://pytest.org/latest/warnings.html#pytest-mark-filterwarnings
|
||||
@pytest.mark.filterwarnings(warning): add a warning filter to the given test. see https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings
|
||||
|
||||
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
|
||||
|
||||
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
|
||||
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see https://docs.pytest.org/en/latest/skipping.html
|
||||
|
||||
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
|
||||
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See https://docs.pytest.org/en/latest/skipping.html
|
||||
|
||||
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
|
||||
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see https://docs.pytest.org/en/latest/parametrize.html for more info and examples.
|
||||
|
||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
|
||||
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see https://docs.pytest.org/en/latest/fixture.html#usefixtures
|
||||
|
||||
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||
|
||||
|
|
|
@ -617,5 +617,5 @@ get on the terminal - we are working on that)::
|
|||
Metafunc.addcall is deprecated and scheduled to be removed in pytest 4.0.
|
||||
Please use Metafunc.parametrize instead.
|
||||
|
||||
-- Docs: http://doc.pytest.org/en/latest/warnings.html
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
================== 42 failed, 1 warnings in 0.12 seconds ===================
|
||||
|
|
|
@ -7,7 +7,7 @@ pytest-2.3: reasoning for fixture/funcarg evolution
|
|||
|
||||
**Target audience**: Reading this document requires basic knowledge of
|
||||
python testing, xUnit setup methods and the (previous) basic pytest
|
||||
funcarg mechanism, see http://pytest.org/2.2.4/funcargs.html
|
||||
funcarg mechanism, see https://docs.pytest.org/en/latest/historical-notes.html#funcargs-and-pytest-funcarg.
|
||||
If you are new to pytest, then you can simply ignore this
|
||||
section and read the other sections.
|
||||
|
||||
|
|
|
@ -277,7 +277,7 @@ on a particular platform::
|
|||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to be more specific as to why the test is failing, you can specify
|
||||
a single exception, or a list of exceptions, in the ``raises`` argument.
|
||||
a single exception, or a tuple of exceptions, in the ``raises`` argument.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ Running pytest now produces this output::
|
|||
$REGENDOC_TMPDIR/test_show_warnings.py:4: UserWarning: api v1, should use functions from v2
|
||||
warnings.warn(UserWarning("api v1, should use functions from v2"))
|
||||
|
||||
-- Docs: http://doc.pytest.org/en/latest/warnings.html
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
=================== 1 passed, 1 warnings in 0.12 seconds ===================
|
||||
|
||||
Pytest by default catches all warnings except for ``DeprecationWarning`` and ``PendingDeprecationWarning``.
|
||||
|
|
|
@ -422,7 +422,7 @@ additionally it is possible to copy examples for a example folder before running
|
|||
$REGENDOC_TMPDIR/test_example.py:4: PytestExerimentalApiWarning: testdir.copy_example is an experimental api that may change over time
|
||||
testdir.copy_example("test_example.py")
|
||||
|
||||
-- Docs: http://doc.pytest.org/en/latest/warnings.html
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
=================== 2 passed, 1 warnings in 0.12 seconds ===================
|
||||
|
||||
For more information about the result object that ``runpytest()`` returns, and
|
||||
|
|
|
@ -9,11 +9,11 @@ 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:
|
||||
|
||||
http://doc.pytest.org/en/latest/changelog.html
|
||||
https://docs.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
http://docs.pytest.org
|
||||
https://docs.pytest.org/en/latest/
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ This is a bug-fix release, being a drop-in replacement. To upgrade::
|
|||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The full changelog is available at http://doc.pytest.org/en/latest/changelog.html.
|
||||
The full changelog is available at https://docs.pytest.org/en/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
|
|
2
setup.py
2
setup.py
|
@ -92,7 +92,7 @@ def main():
|
|||
description="pytest: simple powerful testing with Python",
|
||||
long_description=long_description,
|
||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
||||
url="http://pytest.org",
|
||||
url="https://docs.pytest.org/en/latest/",
|
||||
project_urls={
|
||||
"Source": "https://github.com/pytest-dev/pytest",
|
||||
"Tracker": "https://github.com/pytest-dev/pytest/issues",
|
||||
|
|
|
@ -64,11 +64,16 @@ class AssertionRewritingHook(object):
|
|||
self._rewritten_names = set()
|
||||
self._register_with_pkg_resources()
|
||||
self._must_rewrite = set()
|
||||
# flag to guard against trying to rewrite a pyc file while we are already writing another pyc file,
|
||||
# which might result in infinite recursion (#3506)
|
||||
self._writing_pyc = False
|
||||
|
||||
def set_session(self, session):
|
||||
self.session = session
|
||||
|
||||
def find_module(self, name, path=None):
|
||||
if self._writing_pyc:
|
||||
return None
|
||||
state = self.config._assertstate
|
||||
state.trace("find_module called for: %s" % name)
|
||||
names = name.rsplit(".", 1)
|
||||
|
@ -151,7 +156,11 @@ class AssertionRewritingHook(object):
|
|||
# Probably a SyntaxError in the test.
|
||||
return None
|
||||
if write:
|
||||
_write_pyc(state, co, source_stat, pyc)
|
||||
self._writing_pyc = True
|
||||
try:
|
||||
_write_pyc(state, co, source_stat, pyc)
|
||||
finally:
|
||||
self._writing_pyc = False
|
||||
else:
|
||||
state.trace("found cached rewritten pyc for %r" % (fn,))
|
||||
self.modules[name] = co, pyc
|
||||
|
|
|
@ -132,7 +132,7 @@ class LFPlugin(object):
|
|||
self._no_failures_behavior = self.config.getoption("last_failed_no_failures")
|
||||
|
||||
def pytest_report_collectionfinish(self):
|
||||
if self.active:
|
||||
if self.active and self.config.getoption("verbose") >= 0:
|
||||
if not self._previously_failed_count:
|
||||
return None
|
||||
noun = "failure" if self._previously_failed_count == 1 else "failures"
|
||||
|
|
|
@ -203,7 +203,8 @@ class DoctestItem(pytest.Item):
|
|||
return
|
||||
capman = self.config.pluginmanager.getplugin("capturemanager")
|
||||
if capman:
|
||||
out, err = capman.suspend_global_capture(in_=True)
|
||||
capman.suspend_global_capture(in_=True)
|
||||
out, err = capman.read_global_capture()
|
||||
sys.stdout.write(out)
|
||||
sys.stderr.write(err)
|
||||
|
||||
|
|
|
@ -173,13 +173,14 @@ def pytest_configure(config):
|
|||
"or a list of tuples of values if argnames specifies multiple names. "
|
||||
"Example: @parametrize('arg1', [1,2]) would lead to two calls of the "
|
||||
"decorated test function, one with arg1=1 and another with arg1=2."
|
||||
"see http://pytest.org/latest/parametrize.html for more info and "
|
||||
"examples.",
|
||||
"see https://docs.pytest.org/en/latest/parametrize.html for more info "
|
||||
"and examples.",
|
||||
)
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"usefixtures(fixturename1, fixturename2, ...): mark tests as needing "
|
||||
"all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures ",
|
||||
"all of the specified fixtures. see "
|
||||
"https://docs.pytest.org/en/latest/fixture.html#usefixtures ",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ def pytest_configure(config):
|
|||
"results in a True value. Evaluation happens within the "
|
||||
"module global context. Example: skipif('sys.platform == \"win32\"') "
|
||||
"skips the test if we are on the win32 platform. see "
|
||||
"http://pytest.org/latest/skipping.html",
|
||||
"https://docs.pytest.org/en/latest/skipping.html",
|
||||
)
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
|
@ -61,7 +61,7 @@ def pytest_configure(config):
|
|||
"and run=False if you don't even want to execute the test function. "
|
||||
"If only specific exception(s) are expected, you can list them in "
|
||||
"raises, and if the test fails in other ways, it will be reported as "
|
||||
"a true failure. See http://pytest.org/latest/skipping.html",
|
||||
"a true failure. See https://docs.pytest.org/en/latest/skipping.html",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ class TerminalReporter(object):
|
|||
def write_fspath_result(self, nodeid, res):
|
||||
fspath = self.config.rootdir.join(nodeid.split("::")[0])
|
||||
if fspath != self.currentfspath:
|
||||
if self.currentfspath is not None:
|
||||
if self.currentfspath is not None and self._show_progress_info:
|
||||
self._write_progress_information_filling_space()
|
||||
self.currentfspath = fspath
|
||||
fspath = self.startdir.bestrelpath(fspath)
|
||||
|
@ -358,12 +358,12 @@ class TerminalReporter(object):
|
|||
def pytest_runtest_logreport(self, report):
|
||||
rep = report
|
||||
res = self.config.hook.pytest_report_teststatus(report=rep)
|
||||
cat, letter, word = res
|
||||
category, letter, word = res
|
||||
if isinstance(word, tuple):
|
||||
word, markup = word
|
||||
else:
|
||||
markup = None
|
||||
self.stats.setdefault(cat, []).append(rep)
|
||||
self.stats.setdefault(category, []).append(rep)
|
||||
self._tests_ran = True
|
||||
if not letter and not word:
|
||||
# probably passed setup/teardown
|
||||
|
@ -703,7 +703,7 @@ class TerminalReporter(object):
|
|||
indented = "\n".join(" " + x for x in lines)
|
||||
self._tw.line(indented)
|
||||
self._tw.line()
|
||||
self._tw.line("-- Docs: http://doc.pytest.org/en/latest/warnings.html")
|
||||
self._tw.line("-- Docs: https://docs.pytest.org/en/latest/warnings.html")
|
||||
|
||||
def summary_passes(self):
|
||||
if self.config.option.tbstyle != "no":
|
||||
|
|
|
@ -53,7 +53,7 @@ def pytest_configure(config):
|
|||
config.addinivalue_line(
|
||||
"markers",
|
||||
"filterwarnings(warning): add a warning filter to the given test. "
|
||||
"see http://pytest.org/latest/warnings.html#pytest-mark-filterwarnings ",
|
||||
"see https://docs.pytest.org/en/latest/warnings.html#pytest-mark-filterwarnings ",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -32,10 +32,8 @@ def test_code_with_class():
|
|||
pytest.raises(TypeError, "_pytest._code.Code(A)")
|
||||
|
||||
|
||||
if True:
|
||||
|
||||
def x():
|
||||
pass
|
||||
def x():
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def test_code_fullsource():
|
||||
|
@ -48,7 +46,7 @@ def test_code_source():
|
|||
code = _pytest._code.Code(x)
|
||||
src = code.source()
|
||||
expected = """def x():
|
||||
pass"""
|
||||
raise NotImplementedError()"""
|
||||
assert str(src) == expected
|
||||
|
||||
|
||||
|
@ -85,9 +83,9 @@ def test_unicode_handling():
|
|||
raise Exception(value)
|
||||
|
||||
excinfo = pytest.raises(Exception, f)
|
||||
str(excinfo)
|
||||
if sys.version_info[0] < 3:
|
||||
text_type(excinfo)
|
||||
text_type(excinfo)
|
||||
if sys.version_info < (3,):
|
||||
bytes(excinfo)
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info[0] >= 3, reason="python 2 only issue")
|
||||
|
@ -105,25 +103,25 @@ def test_unicode_handling_syntax_error():
|
|||
|
||||
def test_code_getargs():
|
||||
def f1(x):
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
c1 = _pytest._code.Code(f1)
|
||||
assert c1.getargs(var=True) == ("x",)
|
||||
|
||||
def f2(x, *y):
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
c2 = _pytest._code.Code(f2)
|
||||
assert c2.getargs(var=True) == ("x", "y")
|
||||
|
||||
def f3(x, **z):
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
c3 = _pytest._code.Code(f3)
|
||||
assert c3.getargs(var=True) == ("x", "z")
|
||||
|
||||
def f4(x, *y, **z):
|
||||
pass
|
||||
raise NotImplementedError()
|
||||
|
||||
c4 = _pytest._code.Code(f4)
|
||||
assert c4.getargs(var=True) == ("x", "y", "z")
|
||||
|
@ -188,11 +186,14 @@ class TestReprFuncArgs(object):
|
|||
|
||||
tw = TWMock()
|
||||
|
||||
args = [("unicode_string", u"São Paulo"), ("utf8_string", "S\xc3\xa3o Paulo")]
|
||||
args = [("unicode_string", u"São Paulo"), ("utf8_string", b"S\xc3\xa3o Paulo")]
|
||||
|
||||
r = ReprFuncArgs(args)
|
||||
r.toterminal(tw)
|
||||
if sys.version_info[0] >= 3:
|
||||
assert tw.lines[0] == "unicode_string = São Paulo, utf8_string = São Paulo"
|
||||
assert (
|
||||
tw.lines[0]
|
||||
== r"unicode_string = São Paulo, utf8_string = b'S\xc3\xa3o Paulo'"
|
||||
)
|
||||
else:
|
||||
assert tw.lines[0] == "unicode_string = São Paulo, utf8_string = São Paulo"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# flake8: noqa
|
||||
# disable flake check on this file because some constructs are strange
|
||||
# or redundant on purpose and can't be disable on a line-by-line basis
|
||||
|
@ -41,15 +42,11 @@ def test_source_str_function():
|
|||
|
||||
|
||||
def test_unicode():
|
||||
try:
|
||||
unicode
|
||||
except NameError:
|
||||
return
|
||||
x = Source(unicode("4"))
|
||||
x = Source(u"4")
|
||||
assert str(x) == "4"
|
||||
co = _pytest._code.compile(unicode('u"\xc3\xa5"', "utf8"), mode="eval")
|
||||
co = _pytest._code.compile(u'u"å"', mode="eval")
|
||||
val = eval(co)
|
||||
assert isinstance(val, unicode)
|
||||
assert isinstance(val, six.text_type)
|
||||
|
||||
|
||||
def test_source_from_function():
|
||||
|
@ -632,7 +629,7 @@ def test_issue55():
|
|||
assert str(s) == ' round_trip("""\n""")'
|
||||
|
||||
|
||||
def XXXtest_multiline():
|
||||
def test_multiline():
|
||||
source = getstatement(
|
||||
0,
|
||||
"""\
|
||||
|
|
|
@ -116,7 +116,7 @@ def test_resultlog_is_deprecated(testdir):
|
|||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"*--result-log is deprecated and scheduled for removal in pytest 4.0*",
|
||||
"*See https://docs.pytest.org/*/usage.html#creating-resultlog-format-files for more information*",
|
||||
"*See https://docs.pytest.org/en/latest/usage.html#creating-resultlog-format-files for more information*",
|
||||
]
|
||||
)
|
||||
|
||||
|
|
|
@ -1584,6 +1584,7 @@ class TestFixtureManagerParseFactories(object):
|
|||
values = []
|
||||
"""
|
||||
)
|
||||
testdir.syspathinsert(testdir.tmpdir.dirname)
|
||||
package = testdir.mkdir("package")
|
||||
package.join("__init__.py").write("")
|
||||
package.join("conftest.py").write(
|
||||
|
|
|
@ -1124,3 +1124,32 @@ def test_simple_failure():
|
|||
|
||||
result = testdir.runpytest()
|
||||
result.stdout.fnmatch_lines("*E*assert (1 + 1) == 3")
|
||||
|
||||
|
||||
def test_rewrite_infinite_recursion(testdir, pytestconfig, monkeypatch):
|
||||
"""Fix infinite recursion when writing pyc files: if an import happens to be triggered when writing the pyc
|
||||
file, this would cause another call to the hook, which would trigger another pyc writing, which could
|
||||
trigger another import, and so on. (#3506)"""
|
||||
from _pytest.assertion import rewrite
|
||||
|
||||
testdir.syspathinsert()
|
||||
testdir.makepyfile(test_foo="def test_foo(): pass")
|
||||
testdir.makepyfile(test_bar="def test_bar(): pass")
|
||||
|
||||
original_write_pyc = rewrite._write_pyc
|
||||
|
||||
write_pyc_called = []
|
||||
|
||||
def spy_write_pyc(*args, **kwargs):
|
||||
# make a note that we have called _write_pyc
|
||||
write_pyc_called.append(True)
|
||||
# try to import a module at this point: we should not try to rewrite this module
|
||||
assert hook.find_module("test_bar") is None
|
||||
return original_write_pyc(*args, **kwargs)
|
||||
|
||||
monkeypatch.setattr(rewrite, "_write_pyc", spy_write_pyc)
|
||||
monkeypatch.setattr(sys, "dont_write_bytecode", False)
|
||||
|
||||
hook = AssertionRewritingHook(pytestconfig)
|
||||
assert hook.find_module("test_foo") is not None
|
||||
assert len(write_pyc_called) == 1
|
||||
|
|
|
@ -615,13 +615,19 @@ class TestLastFailed(object):
|
|||
@pytest.mark.parametrize("opt", ["--ff", "--lf"])
|
||||
def test_lf_and_ff_prints_no_needless_message(self, quiet, opt, testdir):
|
||||
# Issue 3853
|
||||
testdir.makepyfile("def test(): pass")
|
||||
testdir.makepyfile("def test(): assert 0")
|
||||
args = [opt]
|
||||
if quiet:
|
||||
args.append("-q")
|
||||
result = testdir.runpytest(*args)
|
||||
assert "run all" not in result.stdout.str()
|
||||
|
||||
result = testdir.runpytest(*args)
|
||||
if quiet:
|
||||
assert "run all" not in result.stdout.str()
|
||||
else:
|
||||
assert "rerun previous" in result.stdout.str()
|
||||
|
||||
def get_cached_last_failed(self, testdir):
|
||||
config = testdir.parseconfigure()
|
||||
return sorted(config.cache.get("cache/lastfailed", {}))
|
||||
|
|
|
@ -3,6 +3,7 @@ terminal reporting of the full testing process.
|
|||
"""
|
||||
from __future__ import absolute_import, division, print_function
|
||||
import collections
|
||||
import os
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
|
@ -472,7 +473,7 @@ class TestTerminalFunctional(object):
|
|||
|
||||
def test_show_deselected_items_using_markexpr_before_test_execution(self, testdir):
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
test_show_deselected="""
|
||||
import pytest
|
||||
|
||||
@pytest.mark.foo
|
||||
|
@ -491,7 +492,7 @@ class TestTerminalFunctional(object):
|
|||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"collected 3 items / 1 deselected",
|
||||
"*test_show_des*.py ..*",
|
||||
"*test_show_deselected.py ..*",
|
||||
"*= 2 passed, 1 deselected in * =*",
|
||||
]
|
||||
)
|
||||
|
@ -1134,7 +1135,53 @@ def test_no_trailing_whitespace_after_inifile_word(testdir):
|
|||
assert "inifile: tox.ini\n" in result.stdout.str()
|
||||
|
||||
|
||||
class TestProgress(object):
|
||||
class TestClassicOutputStyle(object):
|
||||
"""Ensure classic output style works as expected (#3883)"""
|
||||
|
||||
@pytest.fixture
|
||||
def test_files(self, testdir):
|
||||
testdir.makepyfile(
|
||||
**{
|
||||
"test_one.py": "def test_one(): pass",
|
||||
"test_two.py": "def test_two(): assert 0",
|
||||
"sub/test_three.py": """
|
||||
def test_three_1(): pass
|
||||
def test_three_2(): assert 0
|
||||
def test_three_3(): pass
|
||||
""",
|
||||
}
|
||||
)
|
||||
|
||||
def test_normal_verbosity(self, testdir, test_files):
|
||||
result = testdir.runpytest("-o", "console_output_style=classic")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"test_one.py .",
|
||||
"test_two.py F",
|
||||
"sub{}test_three.py .F.".format(os.sep),
|
||||
"*2 failed, 3 passed in*",
|
||||
]
|
||||
)
|
||||
|
||||
def test_verbose(self, testdir, test_files):
|
||||
result = testdir.runpytest("-o", "console_output_style=classic", "-v")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"test_one.py::test_one PASSED",
|
||||
"test_two.py::test_two FAILED",
|
||||
"sub{}test_three.py::test_three_1 PASSED".format(os.sep),
|
||||
"sub{}test_three.py::test_three_2 FAILED".format(os.sep),
|
||||
"sub{}test_three.py::test_three_3 PASSED".format(os.sep),
|
||||
"*2 failed, 3 passed in*",
|
||||
]
|
||||
)
|
||||
|
||||
def test_quiet(self, testdir, test_files):
|
||||
result = testdir.runpytest("-o", "console_output_style=classic", "-q")
|
||||
result.stdout.fnmatch_lines([".F.F.", "*2 failed, 3 passed in*"])
|
||||
|
||||
|
||||
class TestProgressOutputStyle(object):
|
||||
@pytest.fixture
|
||||
def many_tests_files(self, testdir):
|
||||
testdir.makepyfile(
|
||||
|
|
49
tox.ini
49
tox.ini
|
@ -17,13 +17,21 @@ envlist =
|
|||
docs
|
||||
|
||||
[testenv]
|
||||
commands = pytest --lsof -ra {posargs:testing}
|
||||
commands =
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof -ra {env:_PYTEST_TEST_OPTS:} {posargs:testing}
|
||||
coverage: coverage report -m --skip-covered
|
||||
setenv =
|
||||
coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m
|
||||
coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess
|
||||
coverage: COVERAGE_FILE={toxinidir}/.coverage
|
||||
coverage: COVERAGE_PROCESS_START={toxinidir}/.coveragerc
|
||||
passenv = USER USERNAME
|
||||
deps =
|
||||
hypothesis>=3.56
|
||||
nose
|
||||
mock
|
||||
requests
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
|
||||
[testenv:py27-subprocess]
|
||||
changedir = .
|
||||
|
@ -47,9 +55,10 @@ deps =
|
|||
mock
|
||||
nose
|
||||
hypothesis>=3.56
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
changedir=testing
|
||||
commands =
|
||||
pytest -n8 -ra {posargs:.}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n8 -ra {posargs:.}
|
||||
|
||||
[testenv:py36-xdist]
|
||||
deps = {[testenv:py27-xdist]deps}
|
||||
|
@ -58,9 +67,11 @@ commands = {[testenv:py27-xdist]commands}
|
|||
[testenv:py27-pexpect]
|
||||
changedir = testing
|
||||
platform = linux|darwin
|
||||
deps = pexpect
|
||||
deps =
|
||||
pexpect
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra test_pdb.py test_terminal.py test_unittest.py
|
||||
|
||||
[testenv:py36-pexpect]
|
||||
changedir = {[testenv:py27-pexpect]changedir}
|
||||
|
@ -73,26 +84,32 @@ deps =
|
|||
pytest-xdist>=1.13
|
||||
hypothesis>=3.56
|
||||
mock
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
distribute = true
|
||||
changedir=testing
|
||||
setenv =
|
||||
{[testenv]setenv}
|
||||
PYTHONDONTWRITEBYTECODE=1
|
||||
commands =
|
||||
pytest -n3 -ra {posargs:.}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n3 -ra {posargs:.}
|
||||
|
||||
[testenv:py27-trial]
|
||||
deps = twisted
|
||||
deps =
|
||||
twisted
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
pytest -ra {posargs:testing/test_unittest.py}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/test_unittest.py}
|
||||
|
||||
[testenv:py36-trial]
|
||||
deps = {[testenv:py27-trial]deps}
|
||||
commands = {[testenv:py27-trial]commands}
|
||||
|
||||
[testenv:py27-numpy]
|
||||
deps = numpy
|
||||
deps =
|
||||
numpy
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands=
|
||||
pytest -ra {posargs:testing/python/approx.py}
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/python/approx.py}
|
||||
|
||||
[testenv:py36-numpy]
|
||||
deps = {[testenv:py27-numpy]deps}
|
||||
|
@ -100,6 +117,7 @@ commands = {[testenv:py27-numpy]commands}
|
|||
|
||||
[testenv:py27-pluggymaster]
|
||||
setenv=
|
||||
{[testenv]setenv}
|
||||
_PYTEST_SETUP_SKIP_PLUGGY_DEP=1
|
||||
deps =
|
||||
{[testenv]deps}
|
||||
|
@ -123,15 +141,13 @@ commands =
|
|||
|
||||
[testenv:doctesting]
|
||||
basepython = python
|
||||
usedevelop = True
|
||||
skipsdist = True
|
||||
# ensure the given pyargs can't mean anything else
|
||||
changedir = doc/
|
||||
deps =
|
||||
PyYAML
|
||||
{env:_PYTEST_TOX_EXTRA_DEP:}
|
||||
commands =
|
||||
pytest -ra en
|
||||
pytest --doctest-modules --pyargs _pytest
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra doc/en
|
||||
{env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest
|
||||
|
||||
[testenv:regen]
|
||||
changedir = doc/en
|
||||
|
@ -155,7 +171,8 @@ commands =
|
|||
|
||||
[testenv:py36-freeze]
|
||||
changedir = testing/freeze
|
||||
deps = pyinstaller
|
||||
deps =
|
||||
pyinstaller
|
||||
commands =
|
||||
{envpython} create_executable.py
|
||||
{envpython} tox_run.py
|
||||
|
@ -170,7 +187,7 @@ deps =
|
|||
coveralls
|
||||
codecov
|
||||
commands =
|
||||
coverage run --source=_pytest -m pytest testing
|
||||
coverage run -m pytest testing
|
||||
coverage report -m
|
||||
coveralls
|
||||
codecov
|
||||
|
|
Loading…
Reference in New Issue