diff --git a/AUTHORS b/AUTHORS index 5582b4b5162..cf31e038961 100644 --- a/AUTHORS +++ b/AUTHORS @@ -175,5 +175,6 @@ Vidar T. Fauske Vitaly Lashmanov Vlad Dragos Wouter van Ackooy +Xuan Luong Xuecong Liao Zoltán Máté diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0cf7c1a1799..829f691ad5f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,53 @@ .. 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 `_) + +- Allow tests declared as ``@staticmethod`` to use fixtures. (`#2699 + `_) + +- Fixed edge-case during collection: attributes which raised ``pytest.fail`` + when accessed would abort the entire collection. (`#2707 + `_) + +- Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args. (`#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 + `_) + +- 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 + `_) + + +Trivial/Internal Changes +------------------------ + +- Fixed minor error in 'Good Practices/Manual Integration' code snippet. + (`#2691 `_) + +- Fixed typo in goodpractices.rst. (`#2721 + `_) + +- Improve user guidance regarding ``--resultlog`` deprecation. (`#2739 + `_) + + Pytest 3.2.1 (2017-08-08) ========================= diff --git a/_pytest/compat.py b/_pytest/compat.py index da9f3d9a4ef..45491a722c1 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -84,7 +84,15 @@ def num_mock_patch_args(function): 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 # assert not isclass(function) realfunction = function diff --git a/_pytest/fixtures.py b/_pytest/fixtures.py index 4386500f4e4..f57031e1ad0 100644 --- a/_pytest/fixtures.py +++ b/_pytest/fixtures.py @@ -957,11 +957,7 @@ def __init__(self, session): def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not hasattr(node, "nofuncargs"): - if cls is not None: - startindex = 1 - else: - startindex = None - argnames = getfuncargnames(func, startindex) + argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = getattr(func, "usefixtures", None) diff --git a/changelog/2653.doc b/changelog/2653.doc deleted file mode 100644 index 202a06da9db..00000000000 --- a/changelog/2653.doc +++ /dev/null @@ -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. diff --git a/changelog/2681.bugfix b/changelog/2681.bugfix deleted file mode 100644 index a29c31fb7f0..00000000000 --- a/changelog/2681.bugfix +++ /dev/null @@ -1 +0,0 @@ -Calling the deprecated `request.getfuncargvalue()` now shows the source of the call. diff --git a/changelog/2691.trivial b/changelog/2691.trivial deleted file mode 100644 index 9e101894a22..00000000000 --- a/changelog/2691.trivial +++ /dev/null @@ -1 +0,0 @@ -Fixed minor error in 'Good Practices/Manual Integration' code snippet. \ No newline at end of file diff --git a/changelog/2707.bugfix b/changelog/2707.bugfix deleted file mode 100644 index 291e1489cf2..00000000000 --- a/changelog/2707.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed edge-case during collection: attributes which raised ``pytest.fail`` when accessed would abort the entire collection. diff --git a/changelog/2721.trivial b/changelog/2721.trivial deleted file mode 100644 index 21c9e09e4a4..00000000000 --- a/changelog/2721.trivial +++ /dev/null @@ -1 +0,0 @@ -Fixed typo in goodpractices.rst. diff --git a/changelog/2731.bugfix b/changelog/2731.bugfix deleted file mode 100644 index 493ea503bb3..00000000000 --- a/changelog/2731.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix ``ReprFuncArgs`` with mixed unicode and UTF-8 args. diff --git a/changelog/2739.trivial b/changelog/2739.trivial deleted file mode 100644 index 861f4d341f4..00000000000 --- a/changelog/2739.trivial +++ /dev/null @@ -1 +0,0 @@ -Improve user guidance regarding ``--resultlog`` deprecation. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index b6df7deecfe..a822adda5d2 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.2.2 release-3.2.1 release-3.2.0 release-3.1.3 diff --git a/doc/en/announce/release-3.2.2.rst b/doc/en/announce/release-3.2.2.rst new file mode 100644 index 00000000000..599bf872775 --- /dev/null +++ b/doc/en/announce/release-3.2.2.rst @@ -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 diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 52627245cb9..0dbc67310ae 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -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. +.. _`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 `). 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=(,) 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 ---------------------------------------------------- diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 7508d726faf..288b5716047 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.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:570>:1: ValueError + <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python_api.py:579>:1: ValueError _______ TestRaises.test_raises_doesnt ________ self = diff --git a/testing/python/collect.py b/testing/python/collect.py index d6743739211..6b9c6db4e2f 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -147,11 +147,21 @@ class test(object): ]) def test_static_method(self, testdir): + """Support for collecting staticmethod tests (#2528, #2699)""" testdir.getmodulecol(""" + import pytest class Test(object): @staticmethod def test_something(): pass + + @pytest.fixture + def fix(self): + return 1 + + @staticmethod + def test_fix(fix): + assert fix == 1 """) result = testdir.runpytest() if sys.version_info < (2, 7): @@ -162,8 +172,8 @@ def test_something(): ]) else: result.stdout.fnmatch_lines([ - "*collected 1 item*", - "*1 passed in*", + "*collected 2 items*", + "*2 passed in*", ]) def test_setup_teardown_class_as_classmethod(self, testdir): diff --git a/testing/python/fixture.py b/testing/python/fixture.py index f8aef802fa4..06b08d68eea 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -29,10 +29,16 @@ class A(object): def f(self, arg1, arg2="hello"): pass + @staticmethod + def static(arg1, arg2): + pass + assert fixtures.getfuncargnames(A().f) == ('arg1',) if sys.version_info < (3, 0): assert fixtures.getfuncargnames(A.f) == ('arg1',) + assert fixtures.getfuncargnames(A.static, cls=A) == ('arg1', 'arg2') + class TestFillFixtures(object): def test_fillfuncargs_exposed(self):