Merge pull request #3387 from nicoddemus/merge-master-into-features
Merge master into features
This commit is contained in:
commit
f79b0324fe
1
AUTHORS
1
AUTHORS
|
@ -190,6 +190,7 @@ Tareq Alayan
|
|||
Ted Xiao
|
||||
Thomas Grainger
|
||||
Thomas Hisch
|
||||
Tim Strazny
|
||||
Tom Dalton
|
||||
Tom Viner
|
||||
Trevor Bekolay
|
||||
|
|
|
@ -136,7 +136,7 @@ Trivial/Internal Changes
|
|||
- Internal ``mark.py`` module has been turned into a package. (`#3250
|
||||
<https://github.com/pytest-dev/pytest/issues/3250>`_)
|
||||
|
||||
- ``pytest`` now depends on the `more_itertools
|
||||
- ``pytest`` now depends on the `more-itertools
|
||||
<https://github.com/erikrose/more-itertools>`_ package. (`#3265
|
||||
<https://github.com/pytest-dev/pytest/issues/3265>`_)
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import pprint
|
|||
import _pytest._code
|
||||
import py
|
||||
import six
|
||||
from collections import Sequence
|
||||
from ..compat import Sequence
|
||||
|
||||
u = six.text_type
|
||||
|
||||
|
|
|
@ -38,6 +38,14 @@ PY35 = sys.version_info[:2] >= (3, 5)
|
|||
PY36 = sys.version_info[:2] >= (3, 6)
|
||||
MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError'
|
||||
|
||||
if _PY3:
|
||||
from collections.abc import MutableMapping as MappingMixin # noqa
|
||||
from collections.abc import Sequence # noqa
|
||||
else:
|
||||
# those raise DeprecationWarnings in Python >=3.7
|
||||
from collections import MutableMapping as MappingMixin # noqa
|
||||
from collections import Sequence # noqa
|
||||
|
||||
|
||||
def _format_args(func):
|
||||
return str(signature(func))
|
||||
|
|
|
@ -413,14 +413,15 @@ def pytest_fixture_post_finalizer(fixturedef, request):
|
|||
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
""" before session.main() is called.
|
||||
""" called after the ``Session`` object has been created and before performing collection
|
||||
and entering the run test loop.
|
||||
|
||||
:param _pytest.main.Session session: the pytest session object
|
||||
"""
|
||||
|
||||
|
||||
def pytest_sessionfinish(session, exitstatus):
|
||||
""" whole test run finishes.
|
||||
""" called after whole test run finished, right before returning the exit status to the system.
|
||||
|
||||
:param _pytest.main.Session session: the pytest session object
|
||||
:param int exitstatus: the status which pytest will return to the system
|
||||
|
|
|
@ -245,11 +245,6 @@ def record_property(request):
|
|||
def test_function(record_property):
|
||||
record_property("example_key", 1)
|
||||
"""
|
||||
request.node.warn(
|
||||
code='C3',
|
||||
message='record_property is an experimental feature',
|
||||
)
|
||||
|
||||
def append_property(name, value):
|
||||
request.node.user_properties.append((name, value))
|
||||
return append_property
|
||||
|
|
|
@ -20,7 +20,8 @@ class MarkerError(Exception):
|
|||
|
||||
|
||||
def param(*values, **kw):
|
||||
"""Specify a parameter in a `pytest.mark.parametrize`_ call.
|
||||
"""Specify a parameter in `pytest.mark.parametrize`_ calls or
|
||||
:ref:`parametrized fixtures <fixture-parametrize-marks>`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from collections import namedtuple, MutableMapping as MappingMixin
|
||||
import warnings
|
||||
from operator import attrgetter
|
||||
import inspect
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from operator import attrgetter
|
||||
|
||||
import attr
|
||||
|
||||
from ..deprecated import MARK_PARAMETERSET_UNPACKING, MARK_INFO_ATTRIBUTE
|
||||
from ..compat import NOTSET, getfslineno
|
||||
from ..compat import NOTSET, getfslineno, MappingMixin
|
||||
from six.moves import map, reduce
|
||||
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import math
|
|||
import sys
|
||||
|
||||
import py
|
||||
from six import binary_type, text_type
|
||||
from six.moves import zip, filterfalse
|
||||
from more_itertools.more import always_iterable
|
||||
|
||||
|
@ -584,7 +585,8 @@ def raises(expected_exception, *args, **kwargs):
|
|||
|
||||
"""
|
||||
__tracebackhide__ = True
|
||||
for exc in filterfalse(isclass, always_iterable(expected_exception)):
|
||||
base_type = (type, text_type, binary_type)
|
||||
for exc in filterfalse(isclass, always_iterable(expected_exception, base_type)):
|
||||
msg = ("exceptions must be old-style classes or"
|
||||
" derived from BaseException, not %s")
|
||||
raise TypeError(msg % type(exc))
|
||||
|
@ -597,6 +599,10 @@ def raises(expected_exception, *args, **kwargs):
|
|||
message = kwargs.pop("message")
|
||||
if "match" in kwargs:
|
||||
match_expr = kwargs.pop("match")
|
||||
if kwargs:
|
||||
msg = 'Unexpected keyword arguments passed to pytest.raises: '
|
||||
msg += ', '.join(kwargs.keys())
|
||||
raise TypeError(msg)
|
||||
return RaisesContext(expected_exception, message, match_expr)
|
||||
elif isinstance(args[0], str):
|
||||
code, = args
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
New ``--show-capture`` command-line option that allows to specify how to display captured output when tests fail: ``no``, ``stdout``, ``stderr``, ``log`` or ``all`` (the default).
|
|
@ -1 +0,0 @@
|
|||
New ``--rootdir`` command-line option to override the rules for discovering the root directory. See `customize <https://docs.pytest.org/en/latest/customize.html>`_ in the documentation for details.
|
|
@ -1 +0,0 @@
|
|||
Added a `reference <https://docs.pytest.org/en/latest/reference.html>`_ page to the docs.
|
|
@ -1 +0,0 @@
|
|||
Suppress ``IOError`` when closing the temporary file used for capturing streams in Python 2.7.
|
|
@ -1 +0,0 @@
|
|||
Fixtures are now instantiated based on their scopes, with higher-scoped fixtures (such as ``session``) being instantiated first than lower-scoped fixtures (such as ``function``). The relative order of fixtures of the same scope is kept unchanged, based in their declaration order and their dependencies.
|
|
@ -1,2 +0,0 @@
|
|||
``record_xml_property`` renamed to ``record_property`` and is now compatible with xdist, markers and any reporter.
|
||||
``record_xml_property`` name is now deprecated.
|
|
@ -1 +0,0 @@
|
|||
``record_xml_property`` fixture is now deprecated in favor of the more generic ``record_property``.
|
|
@ -1 +0,0 @@
|
|||
New ``--nf``, ``--new-first`` options: run new tests first followed by the rest of the tests, in both cases tests are also sorted by the file modified time, with more recent files coming first.
|
|
@ -1 +0,0 @@
|
|||
Defining ``pytest_plugins`` is now deprecated in non-top-level conftest.py files, because they "leak" to the entire directory tree.
|
|
@ -1 +0,0 @@
|
|||
New ``--last-failed-no-failures`` command-line option that allows to specify the behavior of the cache plugin's ```--last-failed`` feature when no tests failed in the last run (or no cache was found): ``none`` or ``all`` (the default).
|
|
@ -1 +0,0 @@
|
|||
New ``--doctest-continue-on-failure`` command-line option to enable doctests to show multiple failures for each snippet, instead of stopping at the first failure.
|
|
@ -1 +0,0 @@
|
|||
Captured log messages are added to the ``<system-out>`` tag in the generated junit xml file if the ``junit_logging`` ini option is set to ``system-out``. If the value of this ini option is ``system-err`, the logs are written to ``<system-err>``. The default value for ``junit_logging`` is ``no``, meaning captured logs are not written to the output file.
|
|
@ -1 +0,0 @@
|
|||
Allow the logging plugin to handle ``pytest_runtest_logstart`` and ``pytest_runtest_logfinish`` hooks when live logs are enabled.
|
|
@ -1 +0,0 @@
|
|||
Passing `--log-cli-level` in the command-line now automatically activates live logging.
|
|
@ -1 +0,0 @@
|
|||
Add command line option ``--deselect`` to allow deselection of individual tests at collection time.
|
|
@ -1 +0,0 @@
|
|||
Captured logs are printed before entering pdb.
|
|
@ -1 +0,0 @@
|
|||
Deselected item count is now shown before tests are run, e.g. ``collected X items / Y deselected``.
|
|
@ -1 +0,0 @@
|
|||
Change minimum requirement of ``attrs`` to ``17.4.0``.
|
|
@ -1 +0,0 @@
|
|||
The builtin module ``platform`` is now available for use in expressions in ``pytest.mark``.
|
|
@ -1 +0,0 @@
|
|||
Renamed example directories so all tests pass when ran from the base directory.
|
|
@ -1 +0,0 @@
|
|||
Remove usage of deprecated ``metafunc.addcall`` in our own tests.
|
|
@ -1 +0,0 @@
|
|||
Internal ``mark.py`` module has been turned into a package.
|
|
@ -1 +0,0 @@
|
|||
The *short test summary info* section now is displayed after tracebacks and warnings in the terminal.
|
|
@ -1 +0,0 @@
|
|||
``pytest`` now depends on the `more_itertools <https://github.com/erikrose/more-itertools>`_ package.
|
|
@ -1 +0,0 @@
|
|||
Added warning when ``[pytest]`` section is used in a ``.cfg`` file passed with ``-c``
|
|
@ -1 +0,0 @@
|
|||
``nodeids`` can now be passed explicitly to ``FSCollector`` and ``Node`` constructors.
|
|
@ -1 +0,0 @@
|
|||
Internal refactoring of ``FormattedExcinfo`` to use ``attrs`` facilities and remove old support code for legacy Python versions.
|
|
@ -1 +0,0 @@
|
|||
New ``--verbosity`` flag to set verbosity level explicitly.
|
|
@ -1 +0,0 @@
|
|||
Refactoring to unify how verbosity is handled internally.
|
|
@ -1,2 +0,0 @@
|
|||
Fixed ``clear()`` method on ``caplog`` fixture which cleared ``records``,
|
||||
but not the ``text`` property.
|
|
@ -1 +0,0 @@
|
|||
Internal refactoring to better integrate with argparse.
|
|
@ -1 +0,0 @@
|
|||
Fix a python example when calling a fixture in doc/en/usage.rst
|
|
@ -1 +0,0 @@
|
|||
``pytest.approx`` now accepts comparing a numpy array with a scalar.
|
|
@ -1,3 +0,0 @@
|
|||
During test collection, when stdin is not allowed to be read, the
|
||||
``DontReadFromStdin`` object still allow itself to be iterable and
|
||||
resolved to an iterator without crashing.
|
|
@ -0,0 +1 @@
|
|||
Import some modules from ``collections`` instead of ``collections.abc`` as the former modules trigger ``DeprecationWarning`` in Python 3.7.
|
|
@ -0,0 +1 @@
|
|||
``pytest.raises`` now raises ``TypeError`` when receiving an unknown keyword argument.
|
|
@ -0,0 +1,2 @@
|
|||
record_property is no longer experimental, removing the warnings was forgotten.
|
||||
|
|
@ -0,0 +1 @@
|
|||
``pytest.raises`` now works with exception classes that look like iterables.
|
|
@ -2,7 +2,7 @@
|
|||
Development Guide
|
||||
=================
|
||||
|
||||
Some general guidelines regarding development in pytest for core maintainers and general contributors. Nothing here
|
||||
Some general guidelines regarding development in pytest for maintainers and contributors. Nothing here
|
||||
is set in stone and can't be changed, feel free to suggest improvements or changes in the workflow.
|
||||
|
||||
|
||||
|
@ -37,72 +37,19 @@ Any question, feature, bug or proposal is welcome as an issue. Users are encoura
|
|||
GitHub issues should use labels to categorize them. Labels should be created sporadically, to fill a niche; we should
|
||||
avoid creating labels just for the sake of creating them.
|
||||
|
||||
Here is a list of labels and a brief description mentioning their intent.
|
||||
Each label should include a description in the GitHub's interface stating its purpose.
|
||||
|
||||
Temporary labels
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
**Type**
|
||||
To classify issues for a special event it is encouraged to create a temporary label. This helps those involved to find
|
||||
the relevant issues to work on. Examples of that are sprints in Python events or global hacking events.
|
||||
|
||||
* ``type: backward compatibility``: issue that will cause problems with old pytest versions.
|
||||
* ``type: bug``: problem that needs to be addressed.
|
||||
* ``type: deprecation``: feature that will be deprecated in the future.
|
||||
* ``type: docs``: documentation missing or needing clarification.
|
||||
* ``type: enhancement``: new feature or API change, should be merged into ``features``.
|
||||
* ``type: feature-branch``: new feature or API change, should be merged into ``features``.
|
||||
* ``type: infrastructure``: improvement to development/releases/CI structure.
|
||||
* ``type: performance``: performance or memory problem/improvement.
|
||||
* ``type: proposal``: proposal for a new feature, often to gather opinions or design the API around the new feature.
|
||||
* ``type: question``: question regarding usage, installation, internals or how to test something.
|
||||
* ``type: refactoring``: internal improvements to the code.
|
||||
* ``type: regression``: indicates a problem that was introduced in a release which was working previously.
|
||||
* ``temporary: EP2017 sprint``: candidate issues or PRs tackled during the EuroPython 2017
|
||||
|
||||
**Status**
|
||||
Issues created at those events should have other relevant labels added as well.
|
||||
|
||||
* ``status: critical``: grave problem or usability issue that affects lots of users.
|
||||
* ``status: easy``: easy issue that is friendly to new contributors.
|
||||
* ``status: help wanted``: core developers need help from experts on this topic.
|
||||
* ``status: needs information``: reporter needs to provide more information; can be closed after 2 or more weeks of inactivity.
|
||||
|
||||
**Topic**
|
||||
|
||||
* ``topic: collection``
|
||||
* ``topic: fixtures``
|
||||
* ``topic: parametrize``
|
||||
* ``topic: reporting``
|
||||
* ``topic: selection``
|
||||
* ``topic: tracebacks``
|
||||
|
||||
**Plugin (internal or external)**
|
||||
|
||||
* ``plugin: cache``
|
||||
* ``plugin: capture``
|
||||
* ``plugin: doctests``
|
||||
* ``plugin: junitxml``
|
||||
* ``plugin: monkeypatch``
|
||||
* ``plugin: nose``
|
||||
* ``plugin: pastebin``
|
||||
* ``plugin: pytester``
|
||||
* ``plugin: tmpdir``
|
||||
* ``plugin: unittest``
|
||||
* ``plugin: warnings``
|
||||
* ``plugin: xdist``
|
||||
|
||||
|
||||
**OS**
|
||||
|
||||
Issues specific to a single operating system. Do not use as a means to indicate where an issue originated from, only
|
||||
for problems that happen **only** in that system.
|
||||
|
||||
* ``os: linux``
|
||||
* ``os: mac``
|
||||
* ``os: windows``
|
||||
|
||||
**Temporary**
|
||||
|
||||
Used to classify issues for limited time, to help find issues related in events for example.
|
||||
They should be removed after they are no longer relevant.
|
||||
|
||||
* ``temporary: EP2017 sprint``:
|
||||
* ``temporary: sprint-candidate``:
|
||||
Those labels should be removed after they are no longer relevant.
|
||||
|
||||
|
||||
.. include:: ../../HOWTORELEASE.rst
|
||||
|
|
|
@ -358,7 +358,7 @@ get on the terminal - we are working on that)::
|
|||
> int(s)
|
||||
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||
|
||||
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:609>:1: ValueError
|
||||
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:613>:1: ValueError
|
||||
______________________ TestRaises.test_raises_doesnt _______________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
|
|
|
@ -294,7 +294,7 @@ The fixtures requested by ``test_foo`` will be instantiated in the following ord
|
|||
|
||||
1. ``s1``: is the highest-scoped fixture (``session``).
|
||||
2. ``m1``: is the second highest-scoped fixture (``module``).
|
||||
3. ``tempdir``: is a ``function``-scoped fixture, required by ``f1``: it needs to be instantiated at this point
|
||||
3. ``tmpdir``: is a ``function``-scoped fixture, required by ``f1``: it needs to be instantiated at this point
|
||||
because it is a dependency of ``f1``.
|
||||
4. ``f1``: is the first ``function``-scoped fixture in ``test_foo`` parameter list.
|
||||
5. ``f2``: is the last ``function``-scoped fixture in ``test_foo`` parameter list.
|
||||
|
@ -623,6 +623,40 @@ Running the above tests results in the following test IDs being used::
|
|||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
|
||||
.. _`fixture-parametrize-marks`:
|
||||
|
||||
Using marks with parametrized fixtures
|
||||
--------------------------------------
|
||||
|
||||
:func:`pytest.param` can be used to apply marks in values sets of parametrized fixtures in the same way
|
||||
that they can be used with :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>`.
|
||||
|
||||
Example::
|
||||
|
||||
# content of test_fixture_marks.py
|
||||
import pytest
|
||||
@pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)])
|
||||
def data_set(request):
|
||||
return request.param
|
||||
|
||||
def test_data(data_set):
|
||||
pass
|
||||
|
||||
Running this test will *skip* the invocation of ``data_set`` with value ``2``::
|
||||
|
||||
$ pytest test_fixture_marks.py -v
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.5
|
||||
cachedir: .pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_fixture_marks.py::test_data[0] PASSED [ 33%]
|
||||
test_fixture_marks.py::test_data[1] PASSED [ 66%]
|
||||
test_fixture_marks.py::test_data[2] SKIPPED [100%]
|
||||
|
||||
=================== 2 passed, 1 skipped in 0.12 seconds ====================
|
||||
|
||||
.. _`interdependent fixtures`:
|
||||
|
||||
Modularity: using fixtures from a fixture function
|
||||
|
|
|
@ -529,6 +529,8 @@ Initialization hooks called for plugins and ``conftest.py`` files.
|
|||
.. autofunction:: pytest_addhooks
|
||||
.. autofunction:: pytest_configure
|
||||
.. autofunction:: pytest_unconfigure
|
||||
.. autofunction:: pytest_sessionstart
|
||||
.. autofunction:: pytest_sessionfinish
|
||||
|
||||
Test running hooks
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -85,8 +85,8 @@ sub directory but not for other directories::
|
|||
|
||||
Here is how you might run it::
|
||||
|
||||
pytest test_flat.py # will not show "setting up"
|
||||
pytest a/test_sub.py # will show "setting up"
|
||||
pytest test_flat.py --capture=no # will not show "setting up"
|
||||
pytest a/test_sub.py --capture=no # will show "setting up"
|
||||
|
||||
.. note::
|
||||
If you have ``conftest.py`` files which do not reside in a
|
||||
|
|
2
setup.py
2
setup.py
|
@ -60,7 +60,7 @@ def main():
|
|||
'six>=1.10.0',
|
||||
'setuptools',
|
||||
'attrs>=17.4.0',
|
||||
'more_itertools>=4.0.0',
|
||||
'more-itertools>=4.0.0',
|
||||
]
|
||||
# if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy;
|
||||
# used by tox.ini to test with pluggy master
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
from _pytest.outcomes import Failed
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
|
@ -61,6 +62,11 @@ class TestRaises(object):
|
|||
with pytest.raises(TypeError):
|
||||
pytest.raises('wrong', lambda: None)
|
||||
|
||||
def test_invalid_arguments_to_raises(self):
|
||||
with pytest.raises(TypeError, match='unknown'):
|
||||
with pytest.raises(TypeError, unknown='bogus'):
|
||||
raise ValueError()
|
||||
|
||||
def test_tuple(self):
|
||||
with pytest.raises((KeyError, ValueError)):
|
||||
raise KeyError('oops')
|
||||
|
@ -142,3 +148,20 @@ class TestRaises(object):
|
|||
with pytest.raises(ValueError):
|
||||
with pytest.raises(IndexError, match='nomatch'):
|
||||
int('asdf')
|
||||
|
||||
def test_raises_exception_looks_iterable(self):
|
||||
from six import add_metaclass
|
||||
|
||||
class Meta(type(object)):
|
||||
def __getitem__(self, item):
|
||||
return 1/0
|
||||
|
||||
def __len__(self):
|
||||
return 1
|
||||
|
||||
@add_metaclass(Meta)
|
||||
class ClassLooksIterableException(Exception):
|
||||
pass
|
||||
|
||||
with pytest.raises(Failed, match="DID NOT RAISE <class 'raises.ClassLooksIterableException'>"):
|
||||
pytest.raises(ClassLooksIterableException, lambda: None)
|
||||
|
|
|
@ -868,17 +868,13 @@ def test_record_property(testdir):
|
|||
def test_record(record_property, other):
|
||||
record_property("foo", "<1");
|
||||
""")
|
||||
result, dom = runandparse(testdir, '-rw')
|
||||
result, dom = runandparse(testdir, '-rwv')
|
||||
node = dom.find_first_by_tag("testsuite")
|
||||
tnode = node.find_first_by_tag("testcase")
|
||||
psnode = tnode.find_first_by_tag('properties')
|
||||
pnodes = psnode.find_by_tag('property')
|
||||
pnodes[0].assert_attr(name="bar", value="1")
|
||||
pnodes[1].assert_attr(name="foo", value="<1")
|
||||
result.stdout.fnmatch_lines([
|
||||
'test_record_property.py::test_record',
|
||||
'*record_property*experimental*',
|
||||
])
|
||||
|
||||
|
||||
def test_record_property_same_name(testdir):
|
||||
|
|
|
@ -113,7 +113,7 @@ class TestDeprecatedCall(object):
|
|||
pass
|
||||
|
||||
msg = 'Did not produce DeprecationWarning or PendingDeprecationWarning'
|
||||
with pytest.raises(AssertionError, matches=msg):
|
||||
with pytest.raises(AssertionError, match=msg):
|
||||
if mode == 'call':
|
||||
pytest.deprecated_call(f)
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue