Merge pull request #6432 from blueyed/merge-master-into-features

Merge master into features
This commit is contained in:
Daniel Hahler 2020-01-10 14:44:30 +01:00 committed by GitHub
commit 2d488f7615
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 512 additions and 87 deletions

123
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,123 @@
# evaluating GitHub actions for CI, disconsider failures when evaluating PRs
#
# this is still missing:
# - deploy
# - coverage
# - upload github notes
#
name: main
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
name: [
"windows-py35",
"windows-py36",
"windows-py37",
"windows-py37-pluggy",
"windows-py38",
"ubuntu-py35",
"ubuntu-py36",
"ubuntu-py37",
"ubuntu-py37-pluggy",
"ubuntu-py37-freeze",
"ubuntu-py38",
"ubuntu-pypy3",
"macos-py37",
"macos-py38",
"linting",
]
include:
- name: "windows-py35"
python: "3.5"
os: windows-latest
tox_env: "py35-xdist"
- name: "windows-py36"
python: "3.6"
os: windows-latest
tox_env: "py36-xdist"
- name: "windows-py37"
python: "3.7"
os: windows-latest
tox_env: "py37-twisted-numpy"
- name: "windows-py37-pluggy"
python: "3.7"
os: windows-latest
tox_env: "py37-pluggymaster-xdist"
- name: "windows-py38"
python: "3.8"
os: windows-latest
tox_env: "py38"
- name: "ubuntu-py35"
python: "3.5"
os: ubuntu-latest
tox_env: "py35-xdist"
- name: "ubuntu-py36"
python: "3.6"
os: ubuntu-latest
tox_env: "py36-xdist"
- name: "ubuntu-py37"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-lsof-numpy-oldattrs-pexpect-twisted"
- name: "ubuntu-py37-pluggy"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-pluggymaster-xdist"
- name: "ubuntu-py37-freeze"
python: "3.7"
os: ubuntu-latest
tox_env: "py37-freeze"
- name: "ubuntu-py38"
python: "3.8"
os: ubuntu-latest
tox_env: "py38-xdist"
- name: "ubuntu-pypy3"
python: "pypy3"
os: ubuntu-latest
tox_env: "pypy3-xdist"
- name: "macos-py37"
python: "3.7"
os: macos-latest
tox_env: "py37-xdist"
- name: "macos-py38"
python: "3.8"
os: macos-latest
tox_env: "py38-xdist"
- name: "linting"
python: "3.7"
os: ubuntu-latest
tox_env: "linting,docs,doctesting"
steps:
- uses: actions/checkout@v1
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Test
run: tox -e ${{ matrix.tox_env }}

View File

@ -8,7 +8,7 @@ repos:
rev: v1.0.0
hooks:
- id: blacken-docs
additional_dependencies: [black==19.3b0]
additional_dependencies: [black==19.10b0]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.2.3
hooks:

View File

@ -80,9 +80,9 @@ jobs:
addons:
apt:
packages:
# required by publish_gh_release_notes
# required by publish-gh-release-notes
- pandoc
after_deploy: tox -e publish_gh_release_notes
after_deploy: tox -e publish-gh-release-notes
deploy:
provider: pypi
user: nicoddemus

View File

@ -238,6 +238,7 @@ Samuele Pedroni
Sankt Petersbug
Segev Finer
Serhii Mozghovyi
Seth Junot
Simon Gomizelj
Skylar Downes
Srinivas Reddy Thatiparthy

View File

@ -51,7 +51,8 @@ Fix bugs
Look through the `GitHub issues for bugs <https://github.com/pytest-dev/pytest/labels/type:%20bug>`_.
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs.
:ref:`Talk <contact>` to developers to find out how you can fix specific bugs. To indicate that you are going
to work on a particular issue, add a comment to that effect on the specific issue.
Don't forget to check the issue trackers of your favourite plugins, too!

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2004-2019 Holger Krekel and others
Copyright (c) 2004-2020 Holger Krekel and others
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@ -112,12 +112,12 @@ Support pytest
--------------
`Open Collective`_ is an online funding platform for open and transparent communities.
It provide tools to raise money and share your finances in full transparency.
It provides tools to raise money and share your finances in full transparency.
It is the platform of choice for individuals and companies that want to make one-time or
monthly donations directly to the project.
See more datails in the `pytest collective`_.
See more details in the `pytest collective`_.
.. _Open Collective: https://opencollective.com
.. _pytest collective: https://opencollective.com/pytest
@ -145,7 +145,7 @@ Tidelift will coordinate the fix and disclosure.
License
-------
Copyright Holger Krekel and others, 2004-2019.
Copyright Holger Krekel and others, 2004-2020.
Distributed under the terms of the `MIT`_ license, pytest is free and open source software.

View File

@ -39,6 +39,9 @@ jobs:
py37-pluggymaster-xdist:
python.version: '3.7'
tox.env: 'py37-pluggymaster-xdist'
py38-xdist:
python.version: '3.8'
tox.env: 'py38-xdist'
maxParallel: 10
steps:

View File

@ -0,0 +1,2 @@
Fix a ``pytest-xdist`` crash when dealing with exceptions raised in subprocesses created by the
``multiprocessing`` module.

View File

@ -0,0 +1 @@
Optimized automatic renaming of test parameter IDs.

View File

@ -0,0 +1 @@
Fix parsing of outcomes containing multiple errors with ``testdir`` results (regression in 5.3.0).

View File

@ -20,6 +20,10 @@ Release announcements
release-5.1.0
release-5.0.1
release-5.0.0
release-4.6.9
release-4.6.8
release-4.6.7
release-4.6.6
release-4.6.5
release-4.6.4
release-4.6.3

View File

@ -3,13 +3,13 @@ pytest-2.3: improved fixtures / better unittest integration
pytest-2.3 comes with many major improvements for fixture/funcarg management
and parametrized testing in Python. It is now easier, more efficient and
more predicatable to re-run the same tests with different fixture
more predictable to re-run the same tests with different fixture
instances. Also, you can directly declare the caching "scope" of
fixtures so that dependent tests throughout your whole test suite can
re-use database or other expensive fixture objects with ease. Lastly,
it's possible for fixture functions (formerly known as funcarg
factories) to use other fixtures, allowing for a completely modular and
re-useable fixture design.
re-usable fixture design.
For detailed info and tutorial-style examples, see:

View File

@ -91,7 +91,7 @@ holger krekel
it might be the cause for other finalizers to fail.
- fix ordering when mock.patch or other standard decorator-wrappings
are used with test methods. This fixues issue346 and should
are used with test methods. This fixes issue346 and should
help with random "xdist" collection failures. Thanks to
Ronny Pfannschmidt and Donald Stufft for helping to isolate it.

View File

@ -35,7 +35,7 @@ holger krekel
- fix issue435: make reload() work when assert rewriting is active.
Thanks Daniel Hahler.
- fix issue616: conftest.py files and their contained fixutres are now
- fix issue616: conftest.py files and their contained fixtures are now
properly considered for visibility, independently from the exact
current working directory and test arguments that are used.
Many thanks to Eric Siegerman and his PR235 which contains

View File

@ -0,0 +1,20 @@
pytest-4.6.6
=======================================
pytest 4.6.6 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
* Michael Goerz
Happy testing,
The pytest Development Team

View File

@ -0,0 +1,19 @@
pytest-4.6.7
=======================================
pytest 4.6.7 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
* Daniel Hahler
Happy testing,
The pytest Development Team

View File

@ -0,0 +1,20 @@
pytest-4.6.8
=======================================
pytest 4.6.8 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
* Ryan Mast
Happy testing,
The pytest Development Team

View File

@ -0,0 +1,21 @@
pytest-4.6.9
=======================================
pytest 4.6.9 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
* Felix Yan
* Hugo
Happy testing,
The pytest Development Team

View File

@ -1,3 +1,5 @@
.. _`changelog`:
=========
Changelog
=========
@ -815,6 +817,38 @@ Improved Documentation
- `#5416 <https://github.com/pytest-dev/pytest/issues/5416>`_: Fix PytestUnknownMarkWarning in run/skip example.
pytest 4.6.9 (2020-01-04)
=========================
Bug Fixes
---------
- `#6301 <https://github.com/pytest-dev/pytest/issues/6301>`_: Fix assertion rewriting for egg-based distributions and ``editable`` installs (``pip install --editable``).
pytest 4.6.8 (2019-12-19)
=========================
Features
--------
- `#5471 <https://github.com/pytest-dev/pytest/issues/5471>`_: JUnit XML now includes a timestamp and hostname in the testsuite tag.
Bug Fixes
---------
- `#5430 <https://github.com/pytest-dev/pytest/issues/5430>`_: junitxml: Logs for failed test are now passed to junit report in case the test fails during call phase.
Trivial/Internal Changes
------------------------
- `#6345 <https://github.com/pytest-dev/pytest/issues/6345>`_: Pin ``colorama`` to ``0.4.1`` only for Python 3.4 so newer Python versions can still receive colorama updates.
pytest 4.6.7 (2019-12-05)
=========================
@ -5343,7 +5377,7 @@ time or change existing behaviors in order to make them less surprising/more use
Thanks Ronny Pfannschmidt for most of the merging work.
- "-r" option now accepts "a" to include all possible reports, similar
to passing "fEsxXw" explicitly (isse960).
to passing "fEsxXw" explicitly (issue960).
Thanks Abhijeet Kasurde for the PR.
- avoid python3.5 deprecation warnings by introducing version
@ -5633,7 +5667,7 @@ time or change existing behaviors in order to make them less surprising/more use
- fix issue435: make reload() work when assert rewriting is active.
Thanks Daniel Hahler.
- fix issue616: conftest.py files and their contained fixutres are now
- fix issue616: conftest.py files and their contained fixtures are now
properly considered for visibility, independently from the exact
current working directory and test arguments that are used.
Many thanks to Eric Siegerman and his PR235 which contains
@ -7180,7 +7214,7 @@ Bug fixes:
- streamlined plugin loading: order is now as documented in
customize.html: setuptools, ENV, commandline, conftest.
also setuptools entry point names are turned to canonical namees ("pytest_*")
also setuptools entry point names are turned to canonical names ("pytest_*")
- automatically skip tests that need 'capfd' but have no os.dup

View File

@ -66,7 +66,7 @@ master_doc = "contents"
# General information about the project.
project = "pytest"
copyright = "20152019, holger krekel and pytest-dev team"
copyright = "20152020, holger krekel and pytest-dev team"
# The language for content autogenerated by Sphinx. Refer to documentation
@ -289,7 +289,7 @@ man_pages = [("usage", "pytest", "pytest usage", ["holger krekel at merlinux eu"
epub_title = "pytest"
epub_author = "holger krekel at merlinux eu"
epub_publisher = "holger krekel at merlinux eu"
epub_copyright = "2013, holger krekel et alii"
epub_copyright = "2013-2020, holger krekel et alii"
# The language of the text. It defaults to the language option
# or en if the language is not set.

View File

@ -1035,15 +1035,19 @@ file:
# content of conftest.py
import pytest
import tempfile
import os
import shutil
import tempfile
import pytest
@pytest.fixture()
def cleandir():
newpath = tempfile.mkdtemp()
os.chdir(newpath)
yield
shutil.rmtree(newpath)
and declare its use in a test module via a ``usefixtures`` marker:

View File

@ -111,7 +111,7 @@ More details can be found in the `original PR <https://github.com/pytest-dev/pyt
.. note::
in a future major relase of pytest we will introduce class based markers,
in a future major release of pytest we will introduce class based markers,
at which point markers will no longer be limited to instances of :py:class:`Mark`.

View File

@ -92,7 +92,7 @@ It provide tools to raise money and share your finances in full transparency.
It is the platform of choice for individuals and companies that want to make one-time or
monthly donations directly to the project.
See more datails in the `pytest collective`_.
See more details in the `pytest collective`_.
.. _Open Collective: https://opencollective.com
.. _pytest collective: https://opencollective.com/pytest
@ -120,7 +120,7 @@ Tidelift will coordinate the fix and disclosure.
License
-------
Copyright Holger Krekel and others, 2004-2017.
Copyright Holger Krekel and others, 2004-2020.
Distributed under the terms of the `MIT`_ license, pytest is free and open source software.

View File

@ -9,7 +9,7 @@ Distributed under the terms of the `MIT`_ license, pytest is free and open sourc
The MIT License (MIT)
Copyright (c) 2004-2019 Holger Krekel and others
Copyright (c) 2004-2020 Holger Krekel and others
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View File

@ -1,31 +1,97 @@
Python 2.7 and 3.4 support plan
===============================
Python 2.7 and 3.4 support
==========================
Python 2.7 EOL is fast approaching, with
upstream support `ending in 2020 <https://legacy.python.org/dev/peps/pep-0373/#id4>`__.
Python 3.4's last release is scheduled for
`March 2019 <https://www.python.org/dev/peps/pep-0429/#release-schedule>`__. pytest is one of
the participating projects of the https://python3statement.org.
It is demanding on the maintainers of an open source project to support many Python versions, as
there's extra cost of keeping code compatible between all versions, while holding back on
features only made possible on newer Python versions.
The **pytest 4.6** series is the last to support Python 2.7 and 3.4, and was released in
**June 2019**. **pytest 5.0** and onwards will support only Python 3.5+.
In case of Python 2 and 3, the difference between the languages makes it even more prominent,
because many new Python 3 features cannot be used in a Python 2/3 compatible code base.
Thanks to the `python_requires`_ ``setuptools`` option,
Python 2.7 and Python 3.4 users using a modern ``pip`` version
will install the last pytest ``4.6`` version automatically even if ``5.0`` or later
Python 2.7 EOL has been reached `in 2020 <https://legacy.python.org/dev/peps/pep-0373/#id4>`__, with
the last release planned for mid-April, 2020.
Python 3.4 EOL has been reached `in 2019 <https://www.python.org/dev/peps/pep-0429/#release-schedule>`__, with the last release made in March, 2019.
For those reasons, in Jun 2019 it was decided that **pytest 4.6** series will be the last to support Python 2.7 and 3.4.
What this means for general users
---------------------------------
Thanks to the `python_requires`_ setuptools option,
Python 2.7 and Python 3.4 users using a modern pip version
will install the last pytest 4.6.X version automatically even if 5.0 or later versions
are available on PyPI.
While pytest ``5.0`` will be the new mainstream and development version, until **January 2020**
the pytest core team plans to make bug-fix releases of the pytest ``4.6`` series by
back-porting patches to the ``4.6-maintenance`` branch that affect Python 2 users.
Users should ensure they are using the latest pip and setuptools versions for this to work.
**After 2020**, the core team will no longer actively backport patches, but the ``4.6-maintenance``
branch will continue to exist so the community itself can contribute patches. The core team will
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
Maintenance of 4.6.X versions
-----------------------------
Until January 2020, the pytest core team ported many bug-fixes from the main release into the
``4.6-maintenance`` branch, with several 4.6.X releases being made along the year.
From now on, the core team will **no longer actively backport patches**, but the ``4.6-maintenance``
branch will continue to exist so the community itself can contribute patches.
The core team will be happy to accept those patches, and make new 4.6.X releases **until mid-2020**
(but consider that date as a ballpark, after that date the team might still decide to make new releases
for critical bugs).
.. _`python_requires`: https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires
Technical Aspects
-----------------
Technical aspects
~~~~~~~~~~~~~~~~~
The technical aspects of the Python 2.7 and 3.4 support plan (such as when releases will occurr, how to backport fixes, etc) is described in issue `#5275 <https://github.com/pytest-dev/pytest/issues/5275>`__.
(This section is a transcript from `#5275 <https://github.com/pytest-dev/pytest/issues/5275>`__).
In this section we describe the technical aspects of the Python 2.7 and 3.4 support plan.
What goes into 4.6.X releases
+++++++++++++++++++++++++++++
New 4.6.X releases will contain bug fixes only.
When will 4.6.X releases happen
+++++++++++++++++++++++++++++++
New 4.6.X releases will happen after we have a few bugs in place to release, or if a few weeks have
passed (say a single bug has been fixed a month after the latest 4.6.X release).
No hard rules here, just ballpark.
Who will handle applying bug fixes
++++++++++++++++++++++++++++++++++
We core maintainers expect that people still using Python 2.7/3.4 and being affected by
bugs to step up and provide patches and/or port bug fixes from the active branches.
We will be happy to guide users interested in doing so, so please don't hesitate to ask.
**Backporting changes into 4.6**
Please follow these instructions:
#. ``git fetch --all --prune``
#. ``git checkout origin/4.6-maintenance -b backport-XXXX`` # use the PR number here
#. Locate the merge commit on the PR, in the *merged* message, for example:
nicoddemus merged commit 0f8b462 into pytest-dev:features
#. ``git cherry-pick -m1 REVISION`` # use the revision you found above (``0f8b462``).
#. Open a PR targeting ``4.6-maintenance``:
* Prefix the message with ``[4.6]`` so it is an obvious backport
* Delete the PR body, it usually contains a duplicate commit message.
**Providing new PRs to 4.6**
Fresh pull requests to ``4.6-maintenance`` will be accepted provided that
the equivalent code in the active branches does not contain that bug (for example, a bug is specific
to Python 2 only).
Bug fixes that also happen in the mainstream version should be first fixed
there, and then backported as per instructions above.

View File

@ -1,3 +1,5 @@
.. _`reference`:
API Reference
=============

View File

@ -17,7 +17,7 @@ It provide tools to raise money and share your finances in full transparency.
It is the platform of choice for individuals and companies that want to make one-time or
monthly donations directly to the project.
See more datails in the `pytest collective`_.
See more details in the `pytest collective`_.
.. _Tidelift: https://tidelift.com

View File

@ -198,7 +198,7 @@ the regular expression ``".*U.*mode is deprecated"``.
Ensuring code triggers a deprecation warning
--------------------------------------------
You can also call a global helper for checking
You can also use :func:`pytest.deprecated_call` for checking
that a certain function call triggers a ``DeprecationWarning`` or
``PendingDeprecationWarning``:
@ -207,13 +207,18 @@ that a certain function call triggers a ``DeprecationWarning`` or
import pytest
def test_global():
pytest.deprecated_call(myfunction, 17)
def test_myfunction_deprecated():
with pytest.deprecated_call():
myfunction(17)
This test will fail if ``myfunction`` does not issue a deprecation warning
when called with a ``17`` argument.
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')``:
caught when using :func:`pytest.warns` or :ref:`recwarn <recwarn>` because
the default Python warnings filters hide
them. If you wish to record them in your own code, use
``warnings.simplefilter('always')``:
.. code-block:: python
@ -223,19 +228,13 @@ command ``warnings.simplefilter('always')``:
def test_deprecation(recwarn):
warnings.simplefilter("always")
warnings.warn("deprecated", DeprecationWarning)
myfunction(17)
assert len(recwarn) == 1
assert recwarn.pop(DeprecationWarning)
You can also use it as a contextmanager:
.. code-block:: python
def test_global():
with pytest.deprecated_call():
myobject.deprecated_method()
The :ref:`recwarn <recwarn>` fixture automatically ensures to reset the warnings
filter at the end of the test, so no global state is leaked.
.. _`asserting warnings`:

View File

@ -6,7 +6,13 @@ This script is meant to be executed after a successful deployment in Travis.
Uses the following environment variables:
* GIT_TAG: the name of the tag of the current commit.
* GH_RELEASE_NOTES_TOKEN: a personal access token with 'repo' permissions. It should be encrypted using:
* GH_RELEASE_NOTES_TOKEN: a personal access token with 'repo' permissions.
Create one at:
https://github.com/settings/tokens
It should be encrypted using:
$travis encrypt GH_RELEASE_NOTES_TOKEN=<token> -r pytest-dev/pytest
@ -33,7 +39,7 @@ def publish_github_release(slug, token, tag_name, body):
def parse_changelog(tag_name):
p = Path(__file__).parent.parent / "CHANGELOG.rst"
p = Path(__file__).parent.parent / "doc/en/changelog.rst"
changelog_lines = p.read_text(encoding="UTF-8").splitlines()
title_regex = re.compile(r"pytest (\d\.\d+\.\d+) \(\d{4}-\d{2}-\d{2}\)")

View File

@ -143,10 +143,12 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder):
exec(co, module.__dict__)
def _early_rewrite_bailout(self, name, state):
"""This is a fast way to get out of rewriting modules. Profiling has
shown that the call to PathFinder.find_spec (inside of the find_spec
from this class) is a major slowdown, so, this method tries to
filter what we're sure won't be rewritten before getting to it.
"""This is a fast way to get out of rewriting modules.
Profiling has shown that the call to PathFinder.find_spec (inside of
the find_spec from this class) is a major slowdown, so, this method
tries to filter what we're sure won't be rewritten before getting to
it.
"""
if self.session is not None and not self._session_paths_checked:
self._session_paths_checked = True

View File

@ -433,9 +433,14 @@ class RunResult:
for line in reversed(self.outlines):
if rex_session_duration.search(line):
outcomes = rex_outcome.findall(line)
return {noun: int(count) for (count, noun) in outcomes}
raise ValueError("Pytest terminal summary report not found")
ret = {noun: int(count) for (count, noun) in outcomes}
break
else:
raise ValueError("Pytest terminal summary report not found")
if "errors" in ret:
assert "error" not in ret
ret["error"] = ret.pop("errors")
return ret
def assert_outcomes(
self,

View File

@ -6,6 +6,7 @@ import os
import sys
import warnings
from collections import Counter
from collections import defaultdict
from collections.abc import Sequence
from functools import partial
from textwrap import dedent
@ -1244,14 +1245,23 @@ def idmaker(argnames, parametersets, idfn=None, ids=None, config=None, item=None
_idvalset(valindex, parameterset, argnames, idfn, ids, config=config, item=item)
for valindex, parameterset in enumerate(parametersets)
]
if len(set(ids)) != len(ids):
# The ids are not unique
duplicates = [testid for testid in ids if ids.count(testid) > 1]
counters = Counter()
for index, testid in enumerate(ids):
if testid in duplicates:
ids[index] = testid + str(counters[testid])
counters[testid] += 1
# All IDs must be unique!
unique_ids = set(ids)
if len(unique_ids) != len(ids):
# Record the number of occurrences of each test ID
test_id_counts = Counter(ids)
# Map the test ID to its next suffix
test_id_suffixes = defaultdict(int)
# Suffix non-unique IDs to make them unique
for index, test_id in enumerate(ids):
if test_id_counts[test_id] > 1:
ids[index] = "{}{}".format(test_id, test_id_suffixes[test_id])
test_id_suffixes[test_id] += 1
return ids

View File

@ -374,8 +374,11 @@ def _report_to_json(report):
]
return result
def serialize_repr_crash(reprcrash):
return reprcrash.__dict__.copy()
def serialize_repr_crash(reprcrash: Optional[ReprFileLocation]):
if reprcrash is not None:
return reprcrash.__dict__.copy()
else:
return None
def serialize_longrepr(rep):
result = {
@ -455,8 +458,11 @@ def _report_kwargs_from_json(reportdict):
]
return ReprTraceback(**repr_traceback_dict)
def deserialize_repr_crash(repr_crash_dict):
return ReprFileLocation(**repr_crash_dict)
def deserialize_repr_crash(repr_crash_dict: Optional[dict]):
if repr_crash_dict is not None:
return ReprFileLocation(**repr_crash_dict)
else:
return None
if (
reportdict["longrepr"]

View File

@ -676,3 +676,25 @@ def test_run_result_repr():
repr(r) == "<RunResult ret=99 len(stdout.lines)=3"
" len(stderr.lines)=4 duration=0.50s>"
)
def test_testdir_outcomes_with_multiple_errors(testdir):
p1 = testdir.makepyfile(
"""
import pytest
@pytest.fixture
def bad_fixture():
raise Exception("bad")
def test_error1(bad_fixture):
pass
def test_error2(bad_fixture):
pass
"""
)
result = testdir.runpytest(str(p1))
result.assert_outcomes(error=2)
assert result.parseoutcomes() == {"error": 2}

View File

@ -305,6 +305,8 @@ class TestReportSerialization:
data = report._to_json()
loaded_report = report_class._from_json(data)
assert loaded_report.failed
check_longrepr(loaded_report.longrepr)
# make sure we don't blow up on ``toterminal`` call; we don't test the actual output because it is very
@ -312,6 +314,60 @@ class TestReportSerialization:
# elsewhere and we do check the contents of the longrepr object after loading it.
loaded_report.longrepr.toterminal(tw_mock)
def test_chained_exceptions_no_reprcrash(
self, testdir, tw_mock,
):
"""Regression test for tracebacks without a reprcrash (#5971)
This happens notably on exceptions raised by multiprocess.pool: the exception transfer
from subprocess to main process creates an artificial exception, which ExceptionInfo
can't obtain the ReprFileLocation from.
"""
testdir.makepyfile(
"""
from concurrent.futures import ProcessPoolExecutor
def func():
raise ValueError('value error')
def test_a():
with ProcessPoolExecutor() as p:
p.submit(func).result()
"""
)
reprec = testdir.inline_run()
reports = reprec.getreports("pytest_runtest_logreport")
def check_longrepr(longrepr):
assert isinstance(longrepr, ExceptionChainRepr)
assert len(longrepr.chain) == 2
entry1, entry2 = longrepr.chain
tb1, fileloc1, desc1 = entry1
tb2, fileloc2, desc2 = entry2
assert "RemoteTraceback" in str(tb1)
assert "ValueError: value error" in str(tb2)
assert fileloc1 is None
assert fileloc2.message == "ValueError: value error"
# 3 reports: setup/call/teardown: get the call report
assert len(reports) == 3
report = reports[1]
assert report.failed
check_longrepr(report.longrepr)
data = report._to_json()
loaded_report = TestReport._from_json(data)
assert loaded_report.failed
check_longrepr(loaded_report.longrepr)
# for same reasons as previous test, ensure we don't blow up here
loaded_report.longrepr.toterminal(tw_mock)
class TestHooks:
"""Test that the hooks are working correctly for plugins"""

View File

@ -468,10 +468,7 @@ reporttypes = [reports.BaseReport, reports.TestReport, reports.CollectReport]
"reporttype", reporttypes, ids=[x.__name__ for x in reporttypes]
)
def test_report_extra_parameters(reporttype):
if hasattr(inspect, "signature"):
args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:]
else:
args = inspect.getargspec(reporttype.__init__)[0][1:]
args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:]
basekw = dict.fromkeys(args, [])
report = reporttype(newthing=1, **basekw)
assert report.newthing == 1

View File

@ -127,7 +127,7 @@ deps =
towncrier
commands = python scripts/release.py {posargs}
[testenv:publish_gh_release_notes]
[testenv:publish-gh-release-notes]
description = create GitHub release after deployment
basepython = python3
usedevelop = True
@ -135,7 +135,7 @@ passenv = GH_RELEASE_NOTES_TOKEN TRAVIS_TAG TRAVIS_REPO_SLUG
deps =
github3.py
pypandoc
commands = python scripts/publish_gh_release_notes.py
commands = python scripts/publish-gh-release-notes.py {posargs}
[pytest]