Merge pull request #3914 from nicoddemus/merge-master-into-features

Merge master into features
This commit is contained in:
Ronny Pfannschmidt 2018-08-31 15:31:00 +02:00 committed by GitHub
commit 01df368d93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 300 additions and 101 deletions

View File

@ -1,4 +1,3 @@
[run]
omit =
# standlonetemplate is read dynamically and tested by test_genscript
*standalonetemplate.py
source = _pytest,testing
parallel = 1

View File

@ -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:

View File

@ -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)
=========================

View File

@ -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

View File

@ -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

1
changelog/3907.doc.rst Normal file
View File

@ -0,0 +1 @@
Corrected type of the exceptions collection passed to ``xfail``: ``raises`` argument accepts a ``tuple`` instead of ``list``.

View File

@ -6,6 +6,7 @@ Release announcements
:maxdepth: 2
release-3.7.4
release-3.7.3
release-3.7.2
release-3.7.1

View File

@ -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

View File

@ -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.

View File

@ -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 ===================

View File

@ -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.

View File

@ -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

View File

@ -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``.

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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",

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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 ",
)

View File

@ -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",
)

View File

@ -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":

View File

@ -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 ",
)

View File

@ -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"

View File

@ -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,
"""\

View File

@ -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*",
]
)

View File

@ -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(

View File

@ -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

View File

@ -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", {}))

View File

@ -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
View File

@ -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