Merge branch 'master' into features
This commit is contained in:
commit
9273e11f21
1
AUTHORS
1
AUTHORS
|
@ -175,5 +175,6 @@ Vidar T. Fauske
|
||||||
Vitaly Lashmanov
|
Vitaly Lashmanov
|
||||||
Vlad Dragos
|
Vlad Dragos
|
||||||
Wouter van Ackooy
|
Wouter van Ackooy
|
||||||
|
Xuan Luong
|
||||||
Xuecong Liao
|
Xuecong Liao
|
||||||
Zoltán Máté
|
Zoltán Máté
|
||||||
|
|
|
@ -8,6 +8,53 @@
|
||||||
|
|
||||||
.. towncrier release notes start
|
.. towncrier release notes start
|
||||||
|
|
||||||
|
Pytest 3.2.2 (2017-09-06)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
- Calling the deprecated `request.getfuncargvalue()` now shows the source of
|
||||||
|
the call. (`#2681 <https://github.com/pytest-dev/pytest/issues/2681>`_)
|
||||||
|
|
||||||
|
- Allow tests declared as ``@staticmethod`` to use fixtures. (`#2699
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2699>`_)
|
||||||
|
|
||||||
|
- Fixed edge-case during collection: attributes which raised ``pytest.fail``
|
||||||
|
when accessed would abort the entire collection. (`#2707
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2707>`_)
|
||||||
|
|
||||||
|
- Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args. (`#2731
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2731>`_)
|
||||||
|
|
||||||
|
|
||||||
|
Improved Documentation
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
- In examples on working with custom markers, add examples demonstrating the
|
||||||
|
usage of ``pytest.mark.MARKER_NAME.with_args`` in comparison with
|
||||||
|
``pytest.mark.MARKER_NAME.__call__`` (`#2604
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2604>`_)
|
||||||
|
|
||||||
|
- In one of the simple examples, use `pytest_collection_modifyitems()` to skip
|
||||||
|
tests based on a command-line option, allowing its sharing while preventing a
|
||||||
|
user error when acessing `pytest.config` before the argument parsing. (`#2653
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2653>`_)
|
||||||
|
|
||||||
|
|
||||||
|
Trivial/Internal Changes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
- Fixed minor error in 'Good Practices/Manual Integration' code snippet.
|
||||||
|
(`#2691 <https://github.com/pytest-dev/pytest/issues/2691>`_)
|
||||||
|
|
||||||
|
- Fixed typo in goodpractices.rst. (`#2721
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2721>`_)
|
||||||
|
|
||||||
|
- Improve user guidance regarding ``--resultlog`` deprecation. (`#2739
|
||||||
|
<https://github.com/pytest-dev/pytest/issues/2739>`_)
|
||||||
|
|
||||||
|
|
||||||
Pytest 3.2.1 (2017-08-08)
|
Pytest 3.2.1 (2017-08-08)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,15 @@ def num_mock_patch_args(function):
|
||||||
return len(patchings)
|
return len(patchings)
|
||||||
|
|
||||||
|
|
||||||
def getfuncargnames(function, startindex=None):
|
def getfuncargnames(function, startindex=None, cls=None):
|
||||||
|
"""
|
||||||
|
@RonnyPfannschmidt: This function should be refactored when we revisit fixtures. The
|
||||||
|
fixture mechanism should ask the node for the fixture names, and not try to obtain
|
||||||
|
directly from the function object well after collection has occurred.
|
||||||
|
"""
|
||||||
|
if startindex is None and cls is not None:
|
||||||
|
is_staticmethod = isinstance(cls.__dict__.get(function.__name__, None), staticmethod)
|
||||||
|
startindex = 0 if is_staticmethod else 1
|
||||||
# XXX merge with main.py's varnames
|
# XXX merge with main.py's varnames
|
||||||
# assert not isclass(function)
|
# assert not isclass(function)
|
||||||
realfunction = function
|
realfunction = function
|
||||||
|
|
|
@ -957,11 +957,7 @@ class FixtureManager:
|
||||||
|
|
||||||
def getfixtureinfo(self, node, func, cls, funcargs=True):
|
def getfixtureinfo(self, node, func, cls, funcargs=True):
|
||||||
if funcargs and not hasattr(node, "nofuncargs"):
|
if funcargs and not hasattr(node, "nofuncargs"):
|
||||||
if cls is not None:
|
argnames = getfuncargnames(func, cls=cls)
|
||||||
startindex = 1
|
|
||||||
else:
|
|
||||||
startindex = None
|
|
||||||
argnames = getfuncargnames(func, startindex)
|
|
||||||
else:
|
else:
|
||||||
argnames = ()
|
argnames = ()
|
||||||
usefixtures = getattr(func, "usefixtures", None)
|
usefixtures = getattr(func, "usefixtures", None)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
In one of the simple examples, use `pytest_collection_modifyitems()` to skip tests based on a command-line option, allowing its sharing while preventing a user error when acessing `pytest.config` before the argument parsing.
|
|
|
@ -1 +0,0 @@
|
||||||
Calling the deprecated `request.getfuncargvalue()` now shows the source of the call.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed minor error in 'Good Practices/Manual Integration' code snippet.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed edge-case during collection: attributes which raised ``pytest.fail`` when accessed would abort the entire collection.
|
|
|
@ -1 +0,0 @@
|
||||||
Fixed typo in goodpractices.rst.
|
|
|
@ -1 +0,0 @@
|
||||||
Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args.
|
|
|
@ -1 +0,0 @@
|
||||||
Improve user guidance regarding ``--resultlog`` deprecation.
|
|
|
@ -6,6 +6,7 @@ Release announcements
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
|
release-3.2.2
|
||||||
release-3.2.1
|
release-3.2.1
|
||||||
release-3.2.0
|
release-3.2.0
|
||||||
release-3.1.3
|
release-3.1.3
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
pytest-3.2.2
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
pytest 3.2.2 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 http://doc.pytest.org/en/latest/changelog.html.
|
||||||
|
|
||||||
|
Thanks to all who contributed to this release, among them:
|
||||||
|
|
||||||
|
* Andreas Pelme
|
||||||
|
* Antonio Hidalgo
|
||||||
|
* Bruno Oliveira
|
||||||
|
* Felipe Dau
|
||||||
|
* Fernando Macedo
|
||||||
|
* Jesús Espino
|
||||||
|
* Joan Massich
|
||||||
|
* Joe Talbott
|
||||||
|
* Kirill Pinchuk
|
||||||
|
* Ronny Pfannschmidt
|
||||||
|
* Xuan Luong
|
||||||
|
|
||||||
|
|
||||||
|
Happy testing,
|
||||||
|
The pytest Development Team
|
|
@ -395,6 +395,49 @@ The ``--markers`` option always gives you a list of available markers::
|
||||||
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||||
|
|
||||||
|
|
||||||
|
.. _`passing callables to custom markers`:
|
||||||
|
|
||||||
|
Passing a callable to custom markers
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
Below is the config file that will be used in the next examples::
|
||||||
|
|
||||||
|
# content of conftest.py
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
marker = item.get_marker('my_marker')
|
||||||
|
if marker is not None:
|
||||||
|
for info in marker:
|
||||||
|
print('Marker info name={} args={} kwars={}'.format(info.name, info.args, info.kwargs))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time.
|
||||||
|
|
||||||
|
However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator <mark>`). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue::
|
||||||
|
|
||||||
|
# content of test_custom_marker.py
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def hello_world(*args, **kwargs):
|
||||||
|
return 'Hello World'
|
||||||
|
|
||||||
|
@pytest.mark.my_marker.with_args(hello_world)
|
||||||
|
def test_with_args():
|
||||||
|
pass
|
||||||
|
|
||||||
|
The output is as follows::
|
||||||
|
|
||||||
|
$ pytest -q -s
|
||||||
|
Marker info name=my_marker args=(<function hello_world at 0xdeadbeef>,) kwars={}
|
||||||
|
.
|
||||||
|
1 passed in 0.12 seconds
|
||||||
|
|
||||||
|
We can see that the custom marker has its argument set extended with the function ``hello_world``. This is the key different between creating a custom marker as a callable, which invokes ``__call__`` behind the scenes, and using ``with_args``.
|
||||||
|
|
||||||
|
|
||||||
Reading markers which were set from multiple places
|
Reading markers which were set from multiple places
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -358,7 +358,7 @@ get on the terminal - we are working on that)::
|
||||||
> int(s)
|
> int(s)
|
||||||
E ValueError: invalid literal for int() with base 10: 'qwe'
|
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||||
|
|
||||||
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:570>:1: ValueError
|
<0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:579>:1: ValueError
|
||||||
_______ TestRaises.test_raises_doesnt ________
|
_______ TestRaises.test_raises_doesnt ________
|
||||||
|
|
||||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||||
|
|
|
@ -147,11 +147,21 @@ class TestClass(object):
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_static_method(self, testdir):
|
def test_static_method(self, testdir):
|
||||||
|
"""Support for collecting staticmethod tests (#2528, #2699)"""
|
||||||
testdir.getmodulecol("""
|
testdir.getmodulecol("""
|
||||||
|
import pytest
|
||||||
class Test(object):
|
class Test(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def test_something():
|
def test_something():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def fix(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def test_fix(fix):
|
||||||
|
assert fix == 1
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
if sys.version_info < (2, 7):
|
if sys.version_info < (2, 7):
|
||||||
|
@ -162,8 +172,8 @@ class TestClass(object):
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*collected 1 item*",
|
"*collected 2 items*",
|
||||||
"*1 passed in*",
|
"*2 passed in*",
|
||||||
])
|
])
|
||||||
|
|
||||||
def test_setup_teardown_class_as_classmethod(self, testdir):
|
def test_setup_teardown_class_as_classmethod(self, testdir):
|
||||||
|
|
|
@ -29,10 +29,16 @@ def test_getfuncargnames():
|
||||||
def f(self, arg1, arg2="hello"):
|
def f(self, arg1, arg2="hello"):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def static(arg1, arg2):
|
||||||
|
pass
|
||||||
|
|
||||||
assert fixtures.getfuncargnames(A().f) == ('arg1',)
|
assert fixtures.getfuncargnames(A().f) == ('arg1',)
|
||||||
if sys.version_info < (3, 0):
|
if sys.version_info < (3, 0):
|
||||||
assert fixtures.getfuncargnames(A.f) == ('arg1',)
|
assert fixtures.getfuncargnames(A.f) == ('arg1',)
|
||||||
|
|
||||||
|
assert fixtures.getfuncargnames(A.static, cls=A) == ('arg1', 'arg2')
|
||||||
|
|
||||||
|
|
||||||
class TestFillFixtures(object):
|
class TestFillFixtures(object):
|
||||||
def test_fillfuncargs_exposed(self):
|
def test_fillfuncargs_exposed(self):
|
||||||
|
|
Loading…
Reference in New Issue