From 4e1609b12eb1a44b0fc8519de458362d7fd8cdf2 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Mon, 28 Nov 2016 00:55:49 +0100 Subject: [PATCH 01/33] Add `type` validation. Argparse driven argument type validation is added for the `--junit-xml` and `--confcutdir` arguments. The commit partially reverts #2080. Closes #2089. --- CHANGELOG.rst | 8 ++++---- _pytest/config.py | 27 +++++++++++++++++++++++---- _pytest/junitxml.py | 3 +++ _pytest/main.py | 4 +++- testing/test_junitxml.py | 4 ++++ 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 77b67ddbb..4025eb24b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ 3.0.5.dev0 ========== +* Now ``--confcutdir`` and ``--junit-xml`` are properly validated if they are directories + and filenames, respectively (`#2089`_ and `#2078`_). Thanks to `@lwm`_ for the PR. + * Add hint to error message hinting possible missing ``__init__.py`` (`#478`_). Thanks `@DuncanBetts`_. * Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing. @@ -10,10 +13,6 @@ ``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_). Thanks `@nmundar`_ for the PR. -* An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding - subtle bugs (`#2078`_). - Thanks `@nicoddemus`_ for the PR. - * Fix error message using ``approx`` with complex numbers (`#2082`_). Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR. @@ -33,6 +32,7 @@ .. _@nedbat: https://github.com/nedbat .. _@nmundar: https://github.com/nmundar +.. _#2089: https://github.com/pytest-dev/pytest/issues/2089 .. _#478: https://github.com/pytest-dev/pytest/issues/478 .. _#2034: https://github.com/pytest-dev/pytest/issues/2034 .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 diff --git a/_pytest/config.py b/_pytest/config.py index 61123f6ac..4eed5ace1 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -70,6 +70,28 @@ class UsageError(Exception): """ error in pytest usage or invocation""" +def filename_arg(path, optname): + """ Argparse type validator for filename arguments. + + :path: path of filename + :optname: name of the option + """ + if os.path.isdir(path): + raise UsageError("{0} must be a filename, given: {1}".format(optname, path)) + return path + + +def directory_arg(path, optname): + """Argparse type validator for directory arguments. + + :path: path of directory + :optname: name of the option + """ + if not os.path.isdir(path): + raise UsageError("{0} must be a directory, given: {1}".format(optname, path)) + return path + + _preinit = [] default_plugins = ( @@ -996,7 +1018,6 @@ class Config(object): "(are you using python -O?)\n") def _preparse(self, args, addopts=True): - import pytest self._initini(args) if addopts: args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args @@ -1009,9 +1030,7 @@ class Config(object): self.pluginmanager.consider_env() self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy()) confcutdir = self.known_args_namespace.confcutdir - if confcutdir and not os.path.isdir(confcutdir): - raise pytest.UsageError('--confcutdir must be a directory, given: {0}'.format(confcutdir)) - if confcutdir is None and self.inifile: + if self.known_args_namespace.confcutdir is None and self.inifile: confcutdir = py.path.local(self.inifile).dirname self.known_args_namespace.confcutdir = confcutdir try: diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index 4b9103949..317382e63 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -8,12 +8,14 @@ Based on initial code from Ross Lawley. # Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/ # src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd +import functools import py import os import re import sys import time import pytest +from _pytest.config import filename_arg # Python 2.X and 3.X compatibility if sys.version_info[0] < 3: @@ -214,6 +216,7 @@ def pytest_addoption(parser): action="store", dest="xmlpath", metavar="path", + type=functools.partial(filename_arg, optname="--junitxml"), default=None, help="create junit-xml style report file at given path.") group.addoption( diff --git a/_pytest/main.py b/_pytest/main.py index 2b5b12875..2562df3af 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -1,4 +1,5 @@ """ core implementation of testing process: init, session, runtest loop. """ +import functools import os import sys @@ -11,6 +12,7 @@ try: except ImportError: from UserDict import DictMixin as MappingMixin +from _pytest.config import directory_arg from _pytest.runner import collect_one_node tracebackcutdir = py.path.local(_pytest.__file__).dirpath() @@ -58,7 +60,7 @@ def pytest_addoption(parser): # when changing this to --conf-cut-dir, config.py Conftest.setinitial # needs upgrading as well group.addoption('--confcutdir', dest="confcutdir", default=None, - metavar="dir", + metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"), help="only load conftest.py's relative to specified dir.") group.addoption('--noconftest', action="store_true", dest="noconftest", default=False, diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 443b8111b..abbc9cd33 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -715,6 +715,10 @@ def test_logxml_makedir(testdir): assert result.ret == 0 assert testdir.tmpdir.join("path/to/results.xml").check() +def test_logxml_check_isdir(testdir): + """Give an error if --junit-xml is a directory (#2089)""" + result = testdir.runpytest("--junit-xml=.") + result.stderr.fnmatch_lines(["*--junitxml must be a filename*"]) def test_escaped_parametrized_names_xml(testdir): testdir.makepyfile(""" From 6473c3d87e9cbcbf39976ee98a56bf620e848249 Mon Sep 17 00:00:00 2001 From: Duncan Betts Date: Mon, 28 Nov 2016 14:27:12 +0000 Subject: [PATCH 02/33] Improved description of functionality for Issue #687 --- CHANGELOG.rst | 3 +++ doc/en/fixture.rst | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 77b67ddbb..300812383 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,8 @@ * Add hint to error message hinting possible missing ``__init__.py`` (`#478`_). Thanks `@DuncanBetts`_. +* More accurately describe when fixture finalization occurs in documentation (`#687`_). Thanks `@DuncanBetts`_. + * Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing. Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR. @@ -34,6 +36,7 @@ .. _@nmundar: https://github.com/nmundar .. _#478: https://github.com/pytest-dev/pytest/issues/478 +.. _#687: https://github.com/pytest-dev/pytest/issues/687 .. _#2034: https://github.com/pytest-dev/pytest/issues/2034 .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index b0595bc9d..510a4edf9 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -318,8 +318,7 @@ the ``with`` statement ends. request.addfinalizer(fin) return smtp # provide the fixture value - The ``fin`` function will execute when the last test using - the fixture in the module has finished execution. + The ``fin`` function will execute when the last test in the module has finished execution. This method is still fully supported, but ``yield`` is recommended from 2.10 onward because it is considered simpler and better describes the natural code flow. From 40cffacadc05ef652782d99409b99fa4ed8c7bc0 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 28 Nov 2016 21:33:15 +0100 Subject: [PATCH 03/33] minor: fix grammar with help for --setup-{only,show} --- _pytest/setuponly.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_pytest/setuponly.py b/_pytest/setuponly.py index 0ecdbc2bd..1752c575f 100644 --- a/_pytest/setuponly.py +++ b/_pytest/setuponly.py @@ -5,9 +5,9 @@ import sys def pytest_addoption(parser): group = parser.getgroup("debugconfig") group.addoption('--setuponly', '--setup-only', action="store_true", - help="only setup fixtures, don't execute the tests.") + help="only setup fixtures, do not execute tests.") group.addoption('--setupshow', '--setup-show', action="store_true", - help="show setup fixtures while executing the tests.") + help="show setup of fixtures while executing tests.") @pytest.hookimpl(hookwrapper=True) From f8d195253e1d7a63c7783585e5f4412908455322 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 30 Nov 2016 22:23:02 -0200 Subject: [PATCH 04/33] Remove support code for earlier Python 3 version in Source.compile This code leaves None in sys.modules as a side effect but is no longer needed in the Python 3 versions we support. Fix #2103 --- CHANGELOG.rst | 6 +++++- _pytest/_code/source.py | 8 -------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4e0c2f9c1..460ecc573 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,7 +18,10 @@ * Fix error message using ``approx`` with complex numbers (`#2082`_). Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR. -* +* Remove internal code meant to support earlier Python 3 versions that produced the side effect + of leaving ``None`` in ``sys.modules`` when expressions were evaluated by pytest (for example passing a condition + as a string to ``pytest.mark.skipif``)(`#2103`_). + Thanks `@jaraco`_ for the report and `@nicoddemus`_ for the PR. * Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks `@nedbat`_. @@ -41,6 +44,7 @@ .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 .. _#2082: https://github.com/pytest-dev/pytest/issues/2082 +.. _#2103: https://github.com/pytest-dev/pytest/issues/2103 3.0.4 diff --git a/_pytest/_code/source.py b/_pytest/_code/source.py index 522150b55..f69d045b5 100644 --- a/_pytest/_code/source.py +++ b/_pytest/_code/source.py @@ -192,14 +192,6 @@ class Source(object): if flag & _AST_FLAG: return co lines = [(x + "\n") for x in self.lines] - if sys.version_info[0] >= 3: - # XXX py3's inspect.getsourcefile() checks for a module - # and a pep302 __loader__ ... we don't have a module - # at code compile-time so we need to fake it here - m = ModuleType("_pycodecompile_pseudo_module") - py.std.inspect.modulesbyfile[filename] = None - py.std.sys.modules[None] = m - m.__loader__ = 1 py.std.linecache.cache[filename] = (1, None, lines, filename) return co From 30f0152ae6abecd911a0db87d137466af1cd39f9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 30 Nov 2016 22:34:02 -0200 Subject: [PATCH 05/33] Remove unused import --- _pytest/_code/source.py | 1 - 1 file changed, 1 deletion(-) diff --git a/_pytest/_code/source.py b/_pytest/_code/source.py index f69d045b5..fcec0f5ca 100644 --- a/_pytest/_code/source.py +++ b/_pytest/_code/source.py @@ -4,7 +4,6 @@ from bisect import bisect_right import sys import inspect, tokenize import py -from types import ModuleType cpy_compile = compile try: From c856537e7163b657f8ff32021ab5cb3f2991435f Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Thu, 1 Dec 2016 13:20:42 +0100 Subject: [PATCH 06/33] Add warning for incorrect passing args to `-o`. --- CHANGELOG.rst | 6 ++++++ _pytest/config.py | 5 ++++- _pytest/helpconfig.py | 2 +- testing/test_config.py | 10 +++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 460ecc573..dd9de9687 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,10 @@ 3.0.5.dev0 ========== +* Add warning when not passing ``option=value`` correctly to ``-o/--override-ini`` (`#2105`_). + Also improved the help documentation. Thanks to `@mbukatov`_ for the report and + `@lwm`_ for the PR. + * Now ``--confcutdir`` and ``--junit-xml`` are properly validated if they are directories and filenames, respectively (`#2089`_ and `#2078`_). Thanks to `@lwm`_ for the PR. @@ -30,6 +34,7 @@ * +.. _@mbukatov: https://github.com/mbukatov .. _@dupuy: https://bitbucket.org/dupuy/ .. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j @@ -45,6 +50,7 @@ .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 .. _#2082: https://github.com/pytest-dev/pytest/issues/2082 .. _#2103: https://github.com/pytest-dev/pytest/issues/2103 +.. _#2105: https://github.com/pytest-dev/pytest/issues/2105 3.0.4 diff --git a/_pytest/config.py b/_pytest/config.py index 4eed5ace1..fe386ed0b 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -1149,7 +1149,10 @@ class Config(object): if self.getoption("override_ini", None): for ini_config_list in self.option.override_ini: for ini_config in ini_config_list: - (key, user_ini_value) = ini_config.split("=", 1) + try: + (key, user_ini_value) = ini_config.split("=", 1) + except ValueError: + raise UsageError("-o/--override-ini expects option=value style.") if key == name: value = user_ini_value return value diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py index dd161275b..6e66b11c4 100644 --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -23,7 +23,7 @@ def pytest_addoption(parser): group._addoption( '-o', '--override-ini', nargs='*', dest="override_ini", action="append", - help="override config option, e.g. `-o xfail_strict=True`.") + help="override config option with option=value style, e.g. `-o xfail_strict=True`.") @pytest.hookimpl(hookwrapper=True) diff --git a/testing/test_config.py b/testing/test_config.py index 1567dd27c..21ceab1e2 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -83,7 +83,7 @@ class TestParseIni: """) result = testdir.inline_run("--confcutdir=.") assert result.ret == 0 - + class TestConfigCmdlineParsing: def test_parsing_again_fails(self, testdir): config = testdir.parseconfig() @@ -732,6 +732,14 @@ class TestOverrideIniArgs: "ini3:True", "ini4:False"]) + def test_override_ini_usage_error_bad_style(self, testdir): + testdir.makeini(""" + [pytest] + xdist_strict=False + """) + result = testdir.runpytest("--override-ini", 'xdist_strict True', "-s") + result.stderr.fnmatch_lines(["*ERROR* *expects option=value*"]) + def test_with_arg_outside_cwd_without_inifile(self, tmpdir, monkeypatch): monkeypatch.chdir(str(tmpdir)) a = tmpdir.mkdir("a") From bc0f7e62430a3dba644303b4d966c166c84e86e2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 1 Dec 2016 15:50:08 -0200 Subject: [PATCH 07/33] Fix false-positive assert rewrite warnings when using 'pytest_plugins' pytest would emit false positive warnings about assertion-rewrite when a module appears multiple times in plugins which depend on other plugins using the 'pytest_plugins' mechanism --- CHANGELOG.rst | 4 ++++ _pytest/assertion/rewrite.py | 9 ++++----- testing/test_assertrewrite.py | 13 +++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dd9de9687..48ea722bf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -22,6 +22,10 @@ * Fix error message using ``approx`` with complex numbers (`#2082`_). Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR. +* Fixed false-positives warnings from assertion rewrite hook for modules imported more than + once by the ``pytest_plugins`` mechanism. + Thanks `@nicoddemus`_ for the PR. + * Remove internal code meant to support earlier Python 3 versions that produced the side effect of leaving ``None`` in ``sys.modules`` when expressions were evaluated by pytest (for example passing a condition as a string to ``pytest.mark.skipif``)(`#2103`_). diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py index 9ad08391c..abf5b491f 100644 --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -186,16 +186,15 @@ class AssertionRewritingHook(object): """ already_imported = set(names).intersection(set(sys.modules)) if already_imported: - for name in names: + for name in already_imported: if name not in self._rewritten_names: - self._warn_already_imported(already_imported) + self._warn_already_imported(name) self._must_rewrite.update(names) - def _warn_already_imported(self, names): + def _warn_already_imported(self, name): self.config.warn( 'P1', - 'Modules are already imported so can not be re-written: %s' % - ','.join(names)) + 'Module already imported so can not be re-written: %s' % name) def load_module(self, name): # If there is an existing module object named 'fullname' in diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 5f36d4a6b..8e26cdb1b 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -682,6 +682,19 @@ def test_rewritten(): hook.mark_rewrite('test_remember_rewritten_modules') assert warnings == [] + def test_rewrite_warning_using_pytest_plugins(self, testdir, monkeypatch): + testdir.makepyfile(**{ + 'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']", + 'core.py': "", + 'gui.py': "pytest_plugins = ['core', 'sci']", + 'sci.py': "pytest_plugins = ['core']", + 'test_rewrite_warning_pytest_plugins.py': "def test(): pass", + }) + testdir.chdir() + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines(['*= 1 passed in *=*']) + assert 'pytest-warning summary' not in result.stdout.str() + class TestAssertionRewriteHookDetails(object): def test_loader_is_package_false_for_module(self, testdir): From 81528ea81f84937c2364b4fc1108d219b7b4ec61 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 21 Nov 2016 12:50:21 -0200 Subject: [PATCH 08/33] Remove hook proxy cache Fix #2016 --- CHANGELOG.rst | 6 ++++++ _pytest/main.py | 30 ++++++++++++------------------ _pytest/pytester.py | 1 + testing/test_conftest.py | 25 +++++++++++++++++++++++++ testing/test_pluginmanager.py | 22 +++++++++++++++++++++- 5 files changed, 65 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 48ea722bf..c4a5b5144 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,6 +26,10 @@ once by the ``pytest_plugins`` mechanism. Thanks `@nicoddemus`_ for the PR. +* Remove an internal cache which could cause hooks from ``conftest.py`` files in + sub-directories to be called in other directories incorrectly (`#2016`_). + Thanks `@d-b-w`_ for the report and `@nicoddemus`_ for the PR. + * Remove internal code meant to support earlier Python 3 versions that produced the side effect of leaving ``None`` in ``sys.modules`` when expressions were evaluated by pytest (for example passing a condition as a string to ``pytest.mark.skipif``)(`#2103`_). @@ -40,6 +44,7 @@ .. _@mbukatov: https://github.com/mbukatov .. _@dupuy: https://bitbucket.org/dupuy/ +.. _@d-b-w: https://bitbucket.org/d-b-w/ .. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j .. _@DuncanBetts: https://github.com/DuncanBetts @@ -49,6 +54,7 @@ .. _#2089: https://github.com/pytest-dev/pytest/issues/2089 .. _#478: https://github.com/pytest-dev/pytest/issues/478 .. _#687: https://github.com/pytest-dev/pytest/issues/687 +.. _#2016: https://github.com/pytest-dev/pytest/issues/2016 .. _#2034: https://github.com/pytest-dev/pytest/issues/2034 .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 diff --git a/_pytest/main.py b/_pytest/main.py index 2562df3af..52876c12a 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -539,7 +539,6 @@ class Session(FSCollector): def __init__(self, config): FSCollector.__init__(self, config.rootdir, parent=None, config=config, session=self) - self._fs2hookproxy = {} self.testsfailed = 0 self.testscollected = 0 self.shouldstop = False @@ -570,23 +569,18 @@ class Session(FSCollector): return path in self._initialpaths def gethookproxy(self, fspath): - try: - return self._fs2hookproxy[fspath] - except KeyError: - # check if we have the common case of running - # hooks with all conftest.py filesall conftest.py - pm = self.config.pluginmanager - my_conftestmodules = pm._getconftestmodules(fspath) - remove_mods = pm._conftest_plugins.difference(my_conftestmodules) - if remove_mods: - # one or more conftests are not in use at this fspath - proxy = FSHookProxy(fspath, pm, remove_mods) - else: - # all plugis are active for this fspath - proxy = self.config.hook - - self._fs2hookproxy[fspath] = proxy - return proxy + # check if we have the common case of running + # hooks with all conftest.py filesall conftest.py + pm = self.config.pluginmanager + my_conftestmodules = pm._getconftestmodules(fspath) + remove_mods = pm._conftest_plugins.difference(my_conftestmodules) + if remove_mods: + # one or more conftests are not in use at this fspath + proxy = FSHookProxy(fspath, pm, remove_mods) + else: + # all plugis are active for this fspath + proxy = self.config.hook + return proxy def perform_collect(self, args=None, genitems=True): hook = self.config.hook diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 8aa5c0c4f..17ff529a6 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -478,6 +478,7 @@ class Testdir: ret = None for name, value in items: p = self.tmpdir.join(name).new(ext=ext) + p.dirpath().ensure_dir() source = Source(value) def my_totext(s, encoding="utf-8"): diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 6dce13859..c0fa74701 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -423,3 +423,28 @@ def test_conftest_exception_handling(testdir): res = testdir.runpytest() assert res.ret == 4 assert 'raise ValueError()' in [line.strip() for line in res.errlines] + + +def test_hook_proxy(testdir): + """Session's gethookproxy() would cache conftests incorrectly (#2016). + It was decided to remove the cache altogether. + """ + testdir.makepyfile(**{ + 'root/demo-0/test_foo1.py': "def test1(): pass", + + 'root/demo-a/test_foo2.py': "def test1(): pass", + 'root/demo-a/conftest.py': """ + def pytest_ignore_collect(path, config): + return True + """, + + 'root/demo-b/test_foo3.py': "def test1(): pass", + 'root/demo-c/test_foo4.py': "def test1(): pass", + }) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + '*test_foo1.py*', + '*test_foo3.py*', + '*test_foo4.py*', + '*3 passed*', + ]) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index d636102f7..45ad321a3 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -4,7 +4,8 @@ import py import os from _pytest.config import get_config, PytestPluginManager -from _pytest.main import EXIT_NOTESTSCOLLECTED +from _pytest.main import EXIT_NOTESTSCOLLECTED, Session + @pytest.fixture def pytestpm(): @@ -133,6 +134,25 @@ class TestPytestPluginInteractions: finally: undo() + def test_hook_proxy(self, testdir): + """Test the gethookproxy function(#2016)""" + config = testdir.parseconfig() + session = Session(config) + testdir.makepyfile(**{ + 'tests/conftest.py': '', + 'tests/subdir/conftest.py': '', + }) + + conftest1 = testdir.tmpdir.join('tests/conftest.py') + conftest2 = testdir.tmpdir.join('tests/subdir/conftest.py') + + config.pluginmanager._importconftest(conftest1) + ihook_a = session.gethookproxy(testdir.tmpdir.join('tests')) + assert ihook_a is not None + config.pluginmanager._importconftest(conftest2) + ihook_b = session.gethookproxy(testdir.tmpdir.join('tests')) + assert ihook_a is not ihook_b + def test_warn_on_deprecated_multicall(self, pytestpm): warnings = [] From 7480342710ea7b1389811c5316a70457070d8baf Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 2 Dec 2016 09:22:47 -0200 Subject: [PATCH 09/33] Fix typo in docstring of register_assert_rewrite --- _pytest/assertion/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py index 18cb7d32c..3f14a7ae7 100644 --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -29,7 +29,7 @@ def pytest_namespace(): def register_assert_rewrite(*names): - """Register a module name to be rewritten on import. + """Register one or more module names to be rewritten on import. This function will make sure that this module or all modules inside the package will get their assert statements rewritten. From 1f0401ab620e66416e3293c980274cd81a80eefb Mon Sep 17 00:00:00 2001 From: Ismail Date: Fri, 2 Dec 2016 15:09:38 +0000 Subject: [PATCH 10/33] Fix minor typo --- doc/en/goodpractices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/goodpractices.rst b/doc/en/goodpractices.rst index d1e3e66fd..43b15a077 100644 --- a/doc/en/goodpractices.rst +++ b/doc/en/goodpractices.rst @@ -127,7 +127,7 @@ required configurations. The reason for this somewhat evolved importing technique is that in larger projects multiple test modules might import from each other and thus deriving a canonical import name helps - to avoid surprises such as a test modules getting imported twice. + to avoid surprises such as a test module getting imported twice. .. _`virtualenv`: http://pypi.python.org/pypi/virtualenv From 57c44899164c3ff7a521886eb43906c48ba3ef1f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 2 Dec 2016 19:28:45 -0200 Subject: [PATCH 11/33] Use a simple ``+-`` ASCII string in the string representation of pytest.approx In Python 2 Fix #2111 --- CHANGELOG.rst | 21 +++++++++++++------- _pytest/python.py | 10 ++-------- testing/python/approx.py | 41 ++++++++++++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c4a5b5144..8776726f2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,11 @@ * Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing. Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR. +* In Python 2, use a simple ``+-`` ASCII string in the string representation of ``pytest.approx`` (for example ``"4 +- 4.0e-06"``) + because it is brittle to handle that in different contexts and representations internally in pytest + which can result in bugs such as `#2111`_. In Python 3, the representation still uses ``±`` (for example ``4 ± 4.0e-06``). + Thanks `@kerrick-lyft`_ for the report and `@nicoddemus`_ for the PR. + * Using ``item.Function``, ``item.Module``, etc., is now issuing deprecation warnings, prefer ``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_). Thanks `@nmundar`_ for the PR. @@ -42,25 +47,27 @@ * -.. _@mbukatov: https://github.com/mbukatov -.. _@dupuy: https://bitbucket.org/dupuy/ -.. _@d-b-w: https://bitbucket.org/d-b-w/ -.. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j +.. _@d-b-w: https://bitbucket.org/d-b-w/ .. _@DuncanBetts: https://github.com/DuncanBetts +.. _@dupuy: https://bitbucket.org/dupuy/ +.. _@kerrick-lyft: https://github.com/kerrick-lyft +.. _@lwm: https://github.com/lwm +.. _@mbukatov: https://github.com/mbukatov .. _@nedbat: https://github.com/nedbat .. _@nmundar: https://github.com/nmundar -.. _#2089: https://github.com/pytest-dev/pytest/issues/2089 -.. _#478: https://github.com/pytest-dev/pytest/issues/478 -.. _#687: https://github.com/pytest-dev/pytest/issues/687 .. _#2016: https://github.com/pytest-dev/pytest/issues/2016 .. _#2034: https://github.com/pytest-dev/pytest/issues/2034 .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 .. _#2082: https://github.com/pytest-dev/pytest/issues/2082 +.. _#2089: https://github.com/pytest-dev/pytest/issues/2089 .. _#2103: https://github.com/pytest-dev/pytest/issues/2103 .. _#2105: https://github.com/pytest-dev/pytest/issues/2105 +.. _#2111: https://github.com/pytest-dev/pytest/issues/2111 +.. _#478: https://github.com/pytest-dev/pytest/issues/478 +.. _#687: https://github.com/pytest-dev/pytest/issues/687 3.0.4 diff --git a/_pytest/python.py b/_pytest/python.py index 76cf4bd64..e46f2f1bc 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1434,16 +1434,10 @@ class ApproxNonIterable(object): except ValueError: vetted_tolerance = '???' - plus_minus = u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance) - - # In python2, __repr__() must return a string (i.e. not a unicode - # object). In python3, __repr__() must return a unicode object - # (although now strings are unicode objects and bytes are what - # strings were). if sys.version_info[0] == 2: - return plus_minus.encode('utf-8') + return '{0} +- {1}'.format(self.expected, vetted_tolerance) else: - return plus_minus + return u'{0} \u00b1 {1}'.format(self.expected, vetted_tolerance) def __eq__(self, actual): # Short-circuit exact equality. diff --git a/testing/python/approx.py b/testing/python/approx.py index d6bb1f9cf..fc1cbf9ab 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1,5 +1,5 @@ # encoding: utf-8 - +import sys import pytest import doctest @@ -9,6 +9,7 @@ from decimal import Decimal from fractions import Fraction inf, nan = float('inf'), float('nan') + class MyDocTestRunner(doctest.DocTestRunner): def __init__(self): @@ -22,13 +23,17 @@ class MyDocTestRunner(doctest.DocTestRunner): class TestApprox: def test_repr_string(self): - # Just make sure the Unicode handling doesn't raise any exceptions. - print(approx(1.0)) - print(approx([1.0, 2.0, 3.0])) - print(approx(inf)) - print(approx(1.0, rel=nan)) - print(approx(1.0, rel=inf)) - print(approx(1.0j, rel=inf)) + # for some reason in Python 2.6 it is not displaying the tolerance representation correctly + plus_minus = u'\u00b1' if sys.version_info[0] > 2 else u'+-' + tol1, tol2, infr = '1.0e-06', '2.0e-06', 'inf' + if sys.version_info[:2] == (2, 6): + tol1, tol2, infr = '???', '???', '???' + assert repr(approx(1.0)) == '1.0 {pm} {tol1}'.format(pm=plus_minus, tol1=tol1) + assert repr(approx([1.0, 2.0])) == '1.0 {pm} {tol1}, 2.0 {pm} {tol2}'.format(pm=plus_minus, tol1=tol1, tol2=tol2) + assert repr(approx(inf)) == 'inf' + assert repr(approx(1.0, rel=nan)) == '1.0 {pm} ???'.format(pm=plus_minus) + assert repr(approx(1.0, rel=inf)) == '1.0 {pm} {infr}'.format(pm=plus_minus, infr=infr) + assert repr(approx(1.0j, rel=inf)) == '1j' def test_operator_overloading(self): assert 1 == approx(1, rel=1e-6, abs=1e-12) @@ -285,3 +290,23 @@ class TestApprox: runner = MyDocTestRunner() runner.run(test) + def test_unicode_plus_minus(self, testdir): + """ + Comparing approx instances inside lists should not produce an error in the detailed diff. + Integration test for issue #2111. + """ + testdir.makepyfile(""" + import pytest + def test_foo(): + assert [3] == [pytest.approx(4)] + """) + expected = '4.0e-06' + # for some reason in Python 2.6 it is not displaying the tolerance representation correctly + if sys.version_info[:2] == (2, 6): + expected = '???' + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + '*At index 0 diff: 3 != 4 * {0}'.format(expected), + '=* 1 failed in *=', + ]) + From 0febd855e1ad121c179389d1c012601b44ec7114 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 10:06:58 -0200 Subject: [PATCH 12/33] Bump version to 3.0.5 --- _pytest/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 15043e71c..be20d3d41 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.5.dev0' +__version__ = '3.0.5' From 833acb9d3c24602a8ababa53bb24b9edc5be40ab Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 10:07:37 -0200 Subject: [PATCH 13/33] Finalize CHANGELOG for 3.0.5 --- CHANGELOG.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8776726f2..cfcb012f2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,5 @@ -3.0.5.dev0 -========== +3.0.5 +===== * Add warning when not passing ``option=value`` correctly to ``-o/--override-ini`` (`#2105`_). Also improved the help documentation. Thanks to `@mbukatov`_ for the report and @@ -43,10 +43,6 @@ * Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks `@nedbat`_. -* - -* - .. _@adler-j: https://github.com/adler-j .. _@d-b-w: https://bitbucket.org/d-b-w/ .. _@DuncanBetts: https://github.com/DuncanBetts From 31f114e51f0e6eed208bfd95188790170544a610 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 10:19:27 -0200 Subject: [PATCH 14/33] Add release announcement for 3.0.5 --- doc/en/announce/index.rst | 1 + doc/en/announce/release-3.0.5.rst | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 doc/en/announce/release-3.0.5.rst diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index a1bf7bed7..44b29cae1 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.0.5 release-3.0.4 release-3.0.3 release-3.0.2 diff --git a/doc/en/announce/release-3.0.5.rst b/doc/en/announce/release-3.0.5.rst new file mode 100644 index 000000000..3e2419d7e --- /dev/null +++ b/doc/en/announce/release-3.0.5.rst @@ -0,0 +1,27 @@ +pytest-3.0.5 +============ + +pytest 3.0.5 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The changelog is available at http://doc.pytest.org/en/latest/changelog.html. + +Thanks to all who contributed to this release, among them: + +* Ana Vojnovic +* Bruno Oliveira +* Daniel Hahler +* Duncan Betts +* Igor Starikov +* Ismail +* Luke Murphy +* Ned Batchelder +* Ronny Pfannschmidt +* Sebastian Ramacher +* nmundar + +Happy testing, +The pytest Development Team From f592c7746a53999f52df46db764b31d9fbb987f9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 07:22:06 -0500 Subject: [PATCH 15/33] Regendocs for 3.0.5 --- doc/en/assert.rst | 4 ++-- doc/en/cache.rst | 6 +++--- doc/en/capture.rst | 2 +- doc/en/doctest.rst | 2 +- doc/en/example/markers.rst | 28 ++++++++++++++-------------- doc/en/example/nonpython.rst | 6 +++--- doc/en/example/parametrize.rst | 12 ++++++------ doc/en/example/pythoncollection.rst | 6 +++--- doc/en/example/reportingdemo.rst | 4 ++-- doc/en/example/simple.rst | 22 +++++++++++----------- doc/en/fixture.rst | 10 +++++----- doc/en/getting-started.rst | 4 ++-- doc/en/index.rst | 18 ++++++++++-------- doc/en/parametrize.rst | 4 ++-- doc/en/skipping.rst | 2 +- doc/en/tmpdir.rst | 2 +- doc/en/unittest.rst | 2 +- 17 files changed, 68 insertions(+), 66 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index 675dece57..f898391df 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -26,7 +26,7 @@ you will see the return value of the function call:: $ pytest test_assert1.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -170,7 +170,7 @@ if you run this module:: $ pytest test_assert2.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/cache.rst b/doc/en/cache.rst index 4baae4c96..dc1f91286 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -80,7 +80,7 @@ If you then run it with ``--lf``:: $ pytest --lf ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 run-last-failure: rerun last 2 failures rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items @@ -122,7 +122,7 @@ of ``FF`` and dots):: $ pytest --ff ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 run-last-failure: rerun last 2 failures first rootdir: $REGENDOC_TMPDIR, inifile: collected 50 items @@ -227,7 +227,7 @@ You can always peek at the content of the cache using the $ py.test --cache-show ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: cachedir: $REGENDOC_TMPDIR/.cache ------------------------------- cache values ------------------------------- diff --git a/doc/en/capture.rst b/doc/en/capture.rst index 454655d7e..7ee73b992 100644 --- a/doc/en/capture.rst +++ b/doc/en/capture.rst @@ -64,7 +64,7 @@ of the failing function and hide the other one:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 5a1122515..513d9aed9 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -49,7 +49,7 @@ then you can just invoke ``pytest`` without command line options:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 1 items diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 2f5f29e0d..7e48e6f2e 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -31,7 +31,7 @@ You can then restrict a test run to only run tests marked with ``webtest``:: $ pytest -v -m webtest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -45,7 +45,7 @@ Or the inverse, running all tests except the webtest ones:: $ pytest -v -m "not webtest" ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -66,7 +66,7 @@ tests based on their module, class, method, or function name:: $ pytest -v test_server.py::TestClass::test_method ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 5 items @@ -79,7 +79,7 @@ You can also select on the class:: $ pytest -v test_server.py::TestClass ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -92,7 +92,7 @@ Or select multiple nodes:: $ pytest -v test_server.py::TestClass test_server.py::test_send_http ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items @@ -130,7 +130,7 @@ select tests based on their names:: $ pytest -v -k http # running with the above defined example module ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -144,7 +144,7 @@ And you can also run all tests except the ones that match the keyword:: $ pytest -k "not send_http" -v ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -160,7 +160,7 @@ Or to select "http" and "quick" tests:: $ pytest -k "http or quick" -v ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -352,7 +352,7 @@ the test needs:: $ pytest -E stage2 ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -364,7 +364,7 @@ and here is one that specifies exactly the environment needed:: $ pytest -E stage1 ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -485,7 +485,7 @@ then you will see two test skipped and two executed tests as expected:: $ pytest -rs # this option reports skip reasons ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -499,7 +499,7 @@ Note that if you specify a platform via the marker-command line option like this $ pytest -m linux2 ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -551,7 +551,7 @@ We can now use the ``-m option`` to select one set:: $ pytest -m interface --tb=short ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -573,7 +573,7 @@ or to select both "event" and "interface" tests:: $ pytest -m "interface or event" --tb=short ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index e0670aeba..817e5693f 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -27,7 +27,7 @@ now execute the test specification:: nonpython $ pytest test_simple.yml ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collected 2 items @@ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode:: nonpython $ pytest -v ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collecting ... collected 2 items @@ -81,7 +81,7 @@ interesting to just look at the collection tree:: nonpython $ pytest --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collected 2 items diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index fee2b6dcc..dac070c84 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -130,7 +130,7 @@ objects, they are still using the default pytest representation:: $ pytest test_time.py --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 6 items @@ -181,7 +181,7 @@ this is a fully self-contained example which you can run with:: $ pytest test_scenarios.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -194,7 +194,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia $ pytest --collect-only test_scenarios.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -259,7 +259,7 @@ Let's first see how it looks like at collection time:: $ pytest test_backends.py --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -320,7 +320,7 @@ The result of this test will be successful:: $ pytest test_indirect_list.py --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -447,7 +447,7 @@ If you run this with reporting for skips enabled:: $ pytest -rs test_module.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index f1e9a976d..3fa8834bd 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -117,7 +117,7 @@ then the test collection looks like this:: $ pytest --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 2 items @@ -163,7 +163,7 @@ You can always peek at the collection tree without running tests like this:: . $ pytest --collect-only pythoncollection.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 3 items @@ -230,7 +230,7 @@ will be left out:: $ pytest --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 0 items diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 061097cc3..0817458ad 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -11,7 +11,7 @@ get on the terminal - we are working on that):: assertion $ pytest failure_demo.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/assertion, inifile: collected 42 items @@ -359,7 +359,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.py:1204>:1: ValueError + <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1207>:1: ValueError _______ TestRaises.test_raises_doesnt ________ self = diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 032f83c08..3dd6fe92e 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -113,7 +113,7 @@ directory with the above conftest.py:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items @@ -164,7 +164,7 @@ and when running it will see a skipped "slow" test:: $ pytest -rs # "-rs" means report details on the little 's' ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -178,7 +178,7 @@ Or run it including the ``slow`` marked test:: $ pytest --runslow ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -302,7 +302,7 @@ which will add the string to the test header accordingly:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 project deps: mylib-1.1 rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items @@ -327,7 +327,7 @@ which will add info only when run with "--v":: $ pytest -v ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache info1: did you know that ... did you? @@ -340,7 +340,7 @@ and nothing when run plainly:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 0 items @@ -374,7 +374,7 @@ Now we can profile which test functions execute the slowest:: $ pytest --durations=3 ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items @@ -440,7 +440,7 @@ If we run this:: $ pytest -rx ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -519,7 +519,7 @@ We can run this:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 7 items @@ -627,7 +627,7 @@ and run them:: $ pytest test_module.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -721,7 +721,7 @@ and run it:: $ pytest -s test_module.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 510a4edf9..07a85e9b3 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -70,7 +70,7 @@ marked ``smtp`` fixture function. Running the test looks like this:: $ pytest test_smtpsimple.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -188,7 +188,7 @@ inspect what is going on and can now run the tests:: $ pytest test_module.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -519,7 +519,7 @@ Running the above tests results in the following test IDs being used:: $ pytest --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 11 items @@ -572,7 +572,7 @@ Here we declare an ``app`` fixture which receives the previously defined $ pytest -v test_appsetup.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -641,7 +641,7 @@ Let's run the tests in verbose mode and with looking at the print-output:: $ pytest -v -s test_module.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index a3e21e54a..e398e4db5 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -26,7 +26,7 @@ Installation:: To check your installation has installed the correct version:: $ pytest --version - This is pytest version 3.0.4, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py + This is pytest version 3.0.5, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py .. _`simpletest`: @@ -46,7 +46,7 @@ That's it. You can execute the test function now:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/index.rst b/doc/en/index.rst index 67b13d3e3..ce1618e66 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -24,21 +24,23 @@ An example of a simple test: To execute it:: $ pytest - ============================= test session starts ============================= + ======= test session starts ======== + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items - + test_sample.py F - - ================================== FAILURES =================================== - _________________________________ test_answer _________________________________ - + + ======= FAILURES ======== + _______ test_answer ________ + def test_answer(): > assert inc(3) == 5 E assert 4 == 5 E + where 4 = inc(3) - + test_sample.py:5: AssertionError - ========================== 1 failed in 0.04 seconds =========================== + ======= 1 failed in 0.12 seconds ======== Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See :ref:`Getting Started ` for more examples. diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index 5cfedac8c..052d0e72e 100644 --- a/doc/en/parametrize.rst +++ b/doc/en/parametrize.rst @@ -55,7 +55,7 @@ them in turn:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items @@ -103,7 +103,7 @@ Let's run this:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index a024b43a4..afa33444e 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -224,7 +224,7 @@ Running it with the report-on-xfail option gives this output:: example $ pytest -rx xfail_demo.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/example, inifile: collected 7 items diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index 3287ff30f..56e4190c5 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -29,7 +29,7 @@ Running this would result in a passed test except for the last $ pytest test_tmpdir.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 0bc0209e7..179347eb9 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -100,7 +100,7 @@ the ``self.db`` values in the traceback:: $ pytest test_unittest_db.py ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items From 3a0a1d2de3ae1cfded8adaec9dcd9b9a6864cc9d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 12:51:00 -0200 Subject: [PATCH 16/33] Bump version to 3.0.6.dev0 --- CHANGELOG.rst | 15 +++++++++++++++ _pytest/__init__.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cfcb012f2..d49214e3f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,18 @@ +3.0.6.dev0 +========== + +* + +* + +* + +* + +* + + + 3.0.5 ===== diff --git a/_pytest/__init__.py b/_pytest/__init__.py index be20d3d41..8546ff02b 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.5' +__version__ = '3.0.6.dev0' From 8afca5d0fa56953f6bceff0fbfa1969feb04a134 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Dec 2016 17:21:01 -0200 Subject: [PATCH 17/33] Add release dates to CHANGELOG entry Fix #721 --- CHANGELOG.rst | 252 +++++++++++++++++++++++++------------------------- 1 file changed, 126 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d49214e3f..707253958 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,5 @@ -3.0.6.dev0 -========== +3.0.6.dev0 (unreleased) +======================= * @@ -13,8 +13,8 @@ -3.0.5 -===== +3.0.5 (2016-12-05) +================== * Add warning when not passing ``option=value`` correctly to ``-o/--override-ini`` (`#2105`_). Also improved the help documentation. Thanks to `@mbukatov`_ for the report and @@ -81,8 +81,8 @@ .. _#687: https://github.com/pytest-dev/pytest/issues/687 -3.0.4 -===== +3.0.4 (2016-11-09) +================== * Import errors when collecting test modules now display the full traceback (`#1976`_). Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR. @@ -135,8 +135,8 @@ .. _#1649: https://github.com/pytest-dev/pytest/issues/1649 -3.0.3 -===== +3.0.3 (2016-09-28) +================== * The ``ids`` argument to ``parametrize`` again accepts ``unicode`` strings in Python 2 (`#1905`_). @@ -174,8 +174,8 @@ -3.0.2 -===== +3.0.2 (2016-09-01) +================== * Improve error message when passing non-string ids to ``pytest.mark.parametrize`` (`#1857`_). Thanks `@okken`_ for the report and `@nicoddemus`_ for the PR. @@ -214,8 +214,8 @@ .. _#1898: https://github.com/pytest-dev/pytest/issues/1898 -3.0.1 -===== +3.0.1 (2016-08-23) +================== * Fix regression when ``importorskip`` is used at module level (`#1822`_). Thanks `@jaraco`_ and `@The-Compiler`_ for the report and `@nicoddemus`_ for the PR. @@ -240,8 +240,8 @@ .. _#1849: https://github.com/pytest-dev/pytest/issues/1849 -3.0.0 -===== +3.0.0 (2016-08-18) +================== **Incompatible changes** @@ -666,8 +666,8 @@ time or change existing behaviors in order to make them less surprising/more use .. _@matthiasha: https://github.com/matthiasha -2.9.2 -===== +2.9.2 (2016-05-31) +================== **Bug Fixes** @@ -705,8 +705,8 @@ time or change existing behaviors in order to make them less surprising/more use .. _@astraw38: https://github.com/astraw38 -2.9.1 -===== +2.9.1 (2016-03-17) +================== **Bug Fixes** @@ -741,8 +741,8 @@ time or change existing behaviors in order to make them less surprising/more use .. _@asottile: https://github.com/asottile -2.9.0 -===== +2.9.0 (2016-02-29) +================== **New Features** @@ -862,13 +862,13 @@ time or change existing behaviors in order to make them less surprising/more use .. _@pquentin: https://github.com/pquentin .. _@ioggstream: https://github.com/ioggstream -2.8.7 -===== +2.8.7 (2016-01-24) +================== - fix #1338: use predictable object resolution for monkeypatch -2.8.6 -===== +2.8.6 (2016-01-21) +================== - fix #1259: allow for double nodeids in junitxml, this was a regression failing plugins combinations @@ -899,8 +899,8 @@ time or change existing behaviors in order to make them less surprising/more use Thanks Georgy Dyuldin for the PR. -2.8.5 -===== +2.8.5 (2015-12-11) +================== - fix #1243: fixed issue where class attributes injected during collection could break pytest. PR by Alexei Kozlenok, thanks Ronny Pfannschmidt and Bruno Oliveira for the review and help. @@ -913,8 +913,8 @@ time or change existing behaviors in order to make them less surprising/more use Bruno Oliveira for the PR. -2.8.4 -===== +2.8.4 (2015-12-06) +================== - fix #1190: ``deprecated_call()`` now works when the deprecated function has been already called by another test in the same @@ -937,8 +937,8 @@ time or change existing behaviors in order to make them less surprising/more use - a number of documentation modernizations wrt good practices. Thanks Bruno Oliveira for the PR. -2.8.3 -===== +2.8.3 (2015-11-18) +================== - fix #1169: add __name__ attribute to testcases in TestCaseFunction to support the @unittest.skip decorator on functions and methods. @@ -965,8 +965,8 @@ time or change existing behaviors in order to make them less surprising/more use system integrity protection (thanks Florian) -2.8.2 -===== +2.8.2 (2015-10-07) +================== - fix #1085: proper handling of encoding errors when passing encoded byte strings to pytest.parametrize in Python 2. @@ -985,8 +985,8 @@ time or change existing behaviors in order to make them less surprising/more use Thanks Sergey B Kirpichev and Vital Kudzelka for contributing and Bruno Oliveira for the PR. -2.8.1 -===== +2.8.1 (2015-09-29) +================== - fix #1034: Add missing nodeid on pytest_logwarning call in addhook. Thanks Simon Gomizelj for the PR. @@ -1032,8 +1032,8 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue 1029: transform errors when writing cache values into pytest-warnings -2.8.0 -===== +2.8.0 (2015-09-18) +================== - new ``--lf`` and ``-ff`` options to run only the last failing tests or "failing tests first" from the last run. This functionality is provided @@ -1222,8 +1222,8 @@ time or change existing behaviors in order to make them less surprising/more use properly used to discover ``rootdir`` and ``ini`` files. Thanks Peter Lauri for the report and Bruno Oliveira for the PR. -2.7.3 (compared to 2.7.2) -============================= +2.7.3 (2015-09-15) +================== - Allow 'dev', 'rc', or other non-integer version strings in ``importorskip``. Thanks to Eric Hunsberger for the PR. @@ -1265,8 +1265,8 @@ time or change existing behaviors in order to make them less surprising/more use directories created by this fixture (defaults to $TEMP/pytest-$USER). Thanks Bruno Oliveira for the PR. -2.7.2 (compared to 2.7.1) -============================= +2.7.2 (2015-06-23) +================== - fix issue767: pytest.raises value attribute does not contain the exception instance on Python 2.6. Thanks Eric Siegerman for providing the test @@ -1294,8 +1294,8 @@ time or change existing behaviors in order to make them less surprising/more use which has a refined algorithm for traceback generation. -2.7.1 (compared to 2.7.0) -============================= +2.7.1 (2015-05-19) +================== - fix issue731: do not get confused by the braces which may be present and unbalanced in an object's repr while collapsing False @@ -1327,8 +1327,8 @@ time or change existing behaviors in order to make them less surprising/more use - reintroduced _pytest fixture of the pytester plugin which is used at least by pytest-xdist. -2.7.0 (compared to 2.6.4) -============================= +2.7.0 (2015-03-26) +================== - fix issue435: make reload() work when assert rewriting is active. Thanks Daniel Hahler. @@ -1397,8 +1397,8 @@ time or change existing behaviors in order to make them less surprising/more use ``sys.last_traceback`` are set, so that a user can inspect the error via postmortem debugging (almarklein). -2.6.4 -===== +2.6.4 (2014-10-24) +================== - Improve assertion failure reporting on iterables, by using ndiff and pprint. @@ -1426,8 +1426,8 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue614: fixed pastebin support. -2.6.3 -===== +2.6.3 (2014-09-24) +================== - fix issue575: xunit-xml was reporting collection errors as failures instead of errors, thanks Oleg Sinyavskiy. @@ -1453,8 +1453,8 @@ time or change existing behaviors in order to make them less surprising/more use - check xfail/skip also with non-python function test items. Thanks Floris Bruynooghe. -2.6.2 -===== +2.6.2 (2014-09-05) +================== - Added function pytest.freeze_includes(), which makes it easy to embed pytest into executables using tools like cx_freeze. @@ -1482,8 +1482,8 @@ time or change existing behaviors in order to make them less surprising/more use replace the py.test introspection message but are shown in addition to them. -2.6.1 -===== +2.6.1 (2014-08-07) +================== - No longer show line numbers in the --verbose output, the output is now purely the nodeid. The line number is still shown in failure reports. @@ -1619,8 +1619,8 @@ time or change existing behaviors in order to make them less surprising/more use in monkeypatch plugin. Improves output in documentation. -2.5.2 -===== +2.5.2 (2014-01-29) +================== - fix issue409 -- better interoperate with cx_freeze by not trying to import from collections.abc which causes problems @@ -1647,8 +1647,8 @@ time or change existing behaviors in order to make them less surprising/more use - make capfd/capsys.capture private, its unused and shouldnt be exposed -2.5.1 -===== +2.5.1 (2013-12-17) +================== - merge new documentation styling PR from Tobias Bieniek. @@ -1668,8 +1668,8 @@ time or change existing behaviors in order to make them less surprising/more use -2.5.0 -===== +2.5.0 (2013-12-12) +================== - dropped python2.5 from automated release testing of pytest itself which means it's probably going to break soon (but still works @@ -1804,8 +1804,8 @@ time or change existing behaviors in order to make them less surprising/more use - fix verbose reporting for @mock'd test functions -2.4.2 -===== +2.4.2 (2013-10-04) +================== - on Windows require colorama and a newer py lib so that py.io.TerminalWriter() now uses colorama instead of its own ctypes hacks. (fixes issue365) @@ -1835,8 +1835,8 @@ time or change existing behaviors in order to make them less surprising/more use - add pluginmanager.do_configure(config) as a link to config.do_configure() for plugin-compatibility -2.4.1 -===== +2.4.1 (2013-10-02) +================== - When using parser.addoption() unicode arguments to the "type" keyword should also be converted to the respective types. @@ -2020,8 +2020,8 @@ Bug fixes: ".section(title)" and ".line(msg)" methods to print extra information at the end of a test run. -2.3.5 -===== +2.3.5 (2013-04-30) +================== - fix issue169: respect --tb=style with setup/teardown errors as well. @@ -2085,8 +2085,8 @@ Bug fixes: - fix issue266 - accept unicode in MarkEvaluator expressions -2.3.4 -===== +2.3.4 (2012-11-20) +================== - yielded test functions will now have autouse-fixtures active but cannot accept fixtures as funcargs - it's anyway recommended to @@ -2105,8 +2105,8 @@ Bug fixes: need to write as -k "TestClass and test_method" to match a certain method in a certain test class. -2.3.3 -===== +2.3.3 (2012-11-06) +================== - fix issue214 - parse modules that contain special objects like e. g. flask's request object which blows up on getattr access if no request @@ -2137,8 +2137,8 @@ Bug fixes: - fix issue127 - improve documentation for pytest_addoption() and add a ``config.getoption(name)`` helper function for consistency. -2.3.2 -===== +2.3.2 (2012-10-25) +================== - fix issue208 and fix issue29 use new py version to avoid long pauses when printing tracebacks in long modules @@ -2170,8 +2170,8 @@ Bug fixes: - add tox.ini to pytest distribution so that ignore-dirs and others config bits are properly distributed for maintainers who run pytest-own tests -2.3.1 -===== +2.3.1 (2012-10-20) +================== - fix issue202 - fix regression: using "self" from fixture functions now works as expected (it's the same "self" instance that a test method @@ -2183,8 +2183,8 @@ Bug fixes: - link to web pages from --markers output which provides help for pytest.mark.* usage. -2.3.0 -===== +2.3.0 (2012-10-19) +================== - fix issue202 - better automatic names for parametrized test functions - fix issue139 - introduce @pytest.fixture which allows direct scoping @@ -2262,8 +2262,8 @@ Bug fixes: - py.test -vv will show all of assert comparisations instead of truncating -2.2.4 -===== +2.2.4 (2012-05-22) +================== - fix error message for rewritten assertions involving the % operator - fix issue 126: correctly match all invalid xml characters for junitxml @@ -2279,13 +2279,13 @@ Bug fixes: - fix issue #144: better mangle test ids to junitxml classnames - upgrade distribute_setup.py to 0.6.27 -2.2.3 -===== +2.2.3 (2012-02-05) +================== - fix uploaded package to only include neccesary files -2.2.2 -===== +2.2.2 (2012-02-05) +================== - fix issue101: wrong args to unittest.TestCase test function now produce better output @@ -2304,8 +2304,8 @@ Bug fixes: - allow adding of attributes to test reports such that it also works with distributed testing (no upgrade of pytest-xdist needed) -2.2.1 -===== +2.2.1 (2011-12-16) +================== - fix issue99 (in pytest and py) internallerrors with resultlog now produce better output - fixed by normalizing pytest_internalerror @@ -2321,8 +2321,8 @@ Bug fixes: - fix collection crash due to unknown-source collected items, thanks to Ralf Schmitt (fixed by depending on a more recent pylib) -2.2.0 -===== +2.2.0 (2011-11-18) +================== - fix issue90: introduce eager tearing down of test items so that teardown function are called earlier. @@ -2356,8 +2356,8 @@ Bug fixes: - simplify junitxml output code by relying on py.xml - add support for skip properties on unittest classes and functions -2.1.3 -===== +2.1.3 (2011-10-18) +================== - fix issue79: assertion rewriting failed on some comparisons in boolops - correctly handle zero length arguments (a la pytest '') @@ -2365,8 +2365,8 @@ Bug fixes: - fix issue75 / skipping test failure on jython - fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests -2.1.2 -===== +2.1.2 (2011-09-24) +================== - fix assertion rewriting on files with windows newlines on some Python versions - refine test discovery by package/module name (--pyargs), thanks Florian Mayer @@ -2388,8 +2388,8 @@ Bug fixes: - fix issue61: assertion rewriting on boolean operations with 3 or more operands - you can now build a man page with "cd doc ; make man" -2.1.0 -===== +2.1.0 (2011-07-09) +================== - fix issue53 call nosestyle setup functions with correct ordering - fix issue58 and issue59: new assertion code fixes @@ -2408,8 +2408,8 @@ Bug fixes: - report KeyboardInterrupt even if interrupted during session startup - fix issue 35 - provide PDF doc version and download link from index page -2.0.3 -===== +2.0.3 (2011-05-11) +================== - fix issue38: nicer tracebacks on calls to hooks, particularly early configure/sessionstart ones @@ -2428,8 +2428,8 @@ Bug fixes: - fix issue37: avoid invalid characters in junitxml's output -2.0.2 -===== +2.0.2 (2011-03-09) +================== - tackle issue32 - speed up test runs of very quick test functions by reducing the relative overhead @@ -2480,8 +2480,8 @@ Bug fixes: - avoid std unittest assertion helper code in tracebacks (thanks Ronny) -2.0.1 -===== +2.0.1 (2011-02-07) +================== - refine and unify initial capturing so that it works nicely even if the logging module is used on an early-loaded conftest.py @@ -2529,8 +2529,8 @@ Bug fixes: parametraization remains the "pytest_generate_tests" mechanism, see the docs. -2.0.0 -===== +2.0.0 (2010-11-25) +================== - pytest-2.0 is now its own package and depends on pylib-2.0 - new ability: python -m pytest / python -m pytest.main ability @@ -2574,8 +2574,8 @@ Bug fixes: - add ability to use "class" level for cached_setup helper - fix strangeness: mark.* objects are now immutable, create new instances -1.3.4 -===== +1.3.4 (2010-09-14) +================== - fix issue111: improve install documentation for windows - fix issue119: fix custom collectability of __init__.py as a module @@ -2583,8 +2583,8 @@ Bug fixes: - fix issue115: unify internal exception passthrough/catching/GeneratorExit - fix issue118: new --tb=native for presenting cpython-standard exceptions -1.3.3 -===== +1.3.3 (2010-07-30) +================== - fix issue113: assertion representation problem with triple-quoted strings (and possibly other cases) @@ -2598,8 +2598,8 @@ Bug fixes: (thanks Armin Ronacher for reporting) - remove trailing whitespace in all py/text distribution files -1.3.2 -===== +1.3.2 (2010-07-08) +================== **New features** @@ -2671,8 +2671,8 @@ Bug fixes: - fix homedir detection on Windows - ship distribute_setup.py version 0.6.13 -1.3.1 -===== +1.3.1 (2010-05-25) +================== **New features** @@ -2741,8 +2741,8 @@ Bug fixes: (and internally be more careful when presenting unexpected byte sequences) -1.3.0 -===== +1.3.0 (2010-05-05) +================== - deprecate --report option in favour of a new shorter and easier to remember -r option: it takes a string argument consisting of any @@ -2806,8 +2806,8 @@ Bug fixes: - added links to the new capturelog and coverage plugins -1.2.0 -===== +1.2.0 (2010-01-18) +================== - refined usage and options for "py.cleanup":: @@ -2845,8 +2845,8 @@ Bug fixes: - fix plugin links -1.1.1 -===== +1.1.1 (2009-11-24) +================== - moved dist/looponfailing from py.test core into a new separately released pytest-xdist plugin. @@ -2929,8 +2929,8 @@ Bug fixes: - fix docs, fix internal bin/ script generation -1.1.0 -===== +1.1.0 (2009-11-05) +================== - introduce automatic plugin registration via 'pytest11' entrypoints via setuptools' pkg_resources.iter_entry_points @@ -3033,16 +3033,16 @@ Bug fixes: * simplified internal localpath implementation -1.0.2 -===== +1.0.2 (2009-08-27) +================== * fixing packaging issues, triggered by fedora redhat packaging, also added doc, examples and contrib dirs to the tarball. * added a documentation link to the new django plugin. -1.0.1 -===== +1.0.1 (2009-08-19) +================== * added a 'pytest_nose' plugin which handles nose.SkipTest, nose-style function/method/generator setup/teardown and @@ -3075,14 +3075,14 @@ Bug fixes: * simplified multicall mechanism and plugin architecture, renamed some internal methods and argnames -1.0.0 -===== +1.0.0 (2009-08-04) +================== * more terse reporting try to show filesystem path relatively to current dir * improve xfail output a bit -1.0.0b9 -======= +1.0.0b9 (2009-07-31) +==================== * cleanly handle and report final teardown of test setup @@ -3115,8 +3115,8 @@ Bug fixes: * item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr) -1.0.0b8 -======= +1.0.0b8 (2009-07-22) +==================== * pytest_unittest-plugin is now enabled by default @@ -3169,8 +3169,8 @@ Bug fixes: * make __name__ == "__channelexec__" for remote_exec code -1.0.0b3 -======= +1.0.0b3 (2009-06-19) +==================== * plugin classes are removed: one now defines hooks directly in conftest.py or global pytest_*.py From f42a954cb3ced2dad27fd973d8316b2191cc55fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oscar=20Hellstr=C3=B6m?= Date: Tue, 29 Nov 2016 10:25:57 +0100 Subject: [PATCH 18/33] Also update yield teardown for Issue #687 --- doc/en/fixture.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 07a85e9b3..bbc4a95c4 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -257,8 +257,9 @@ the code after the *yield* statement serves as the teardown code.:: print("teardown smtp") smtp.close() -The ``print`` and ``smtp.close()`` statements will execute when the last test using -the fixture in the module has finished execution, regardless of the exception status of the tests. +The ``print`` and ``smtp.close()`` statements will execute when the last test in +the module has finished execution, regardless of the exception status of the +tests. Let's execute it:: From 81c9bdcd0b6a0853e1883d797b93636488665340 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 10 Dec 2016 16:55:04 -0200 Subject: [PATCH 19/33] Mention that Python also adds CWD to sys.path using python -m --- doc/en/usage.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/usage.rst b/doc/en/usage.rst index ef63a8e06..4f01081ce 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -16,8 +16,8 @@ You can invoke testing through the Python interpreter from the command line:: python -m pytest [...] -This is equivalent to invoking the command line script ``pytest [...]`` -directly. +This is almost equivalent to invoking the command line script ``pytest [...]`` +directly, except that python will also add the current directory to ``sys.path``. Getting help on version, option names, environment variables -------------------------------------------------------------- From 3a59acf69f0121302bcddd34f71fcd74b966ce7c Mon Sep 17 00:00:00 2001 From: Dmitry Malinovsky Date: Sun, 11 Dec 2016 21:59:11 +0600 Subject: [PATCH 20/33] Use inspect to properly detect generators. Fixes #2129 --- _pytest/compat.py | 15 ++++++++++----- testing/conftest.py | 7 +++++++ testing/test_compat.py | 12 ++++++++++++ testing/test_compat_3.py | 15 +++++++++++++++ testing/test_compat_35.py | 12 ++++++++++++ 5 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 testing/conftest.py create mode 100644 testing/test_compat.py create mode 100644 testing/test_compat_3.py create mode 100644 testing/test_compat_35.py diff --git a/_pytest/compat.py b/_pytest/compat.py index 51fc3bc5c..7a3d0af81 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -19,6 +19,12 @@ except ImportError: # pragma: no cover # Only available in Python 3.4+ or as a backport enum = None +try: + import asyncio +except ImportError: # pragma: no cover + # Only available in Python 3.4+ or as a backport + asyncio = None + _PY3 = sys.version_info > (3, 0) _PY2 = not _PY3 @@ -42,11 +48,10 @@ REGEX_TYPE = type(re.compile('')) def is_generator(func): - try: - return _pytest._code.getrawcode(func).co_flags & 32 # generator function - except AttributeError: # builtin functions have no bytecode - # assume them to not be generators - return False + genfunc = inspect.isgeneratorfunction(func) + if asyncio is not None: + return genfunc and not asyncio.iscoroutinefunction(func) + return genfunc def getlocation(function, curdir): diff --git a/testing/conftest.py b/testing/conftest.py new file mode 100644 index 000000000..76a314837 --- /dev/null +++ b/testing/conftest.py @@ -0,0 +1,7 @@ +import sys + +collect_ignore = [] +if sys.version_info[0] < 3: + collect_ignore.append("test_compat_3.py") +if sys.version_info < (3, 5): + collect_ignore.append("test_compat_35.py") diff --git a/testing/test_compat.py b/testing/test_compat.py new file mode 100644 index 000000000..185fc3bd6 --- /dev/null +++ b/testing/test_compat.py @@ -0,0 +1,12 @@ +from _pytest.compat import is_generator + + +def test_is_generator(): + def zap(): + yield + + def foo(): + pass + + assert is_generator(zap) + assert not is_generator(foo) diff --git a/testing/test_compat_3.py b/testing/test_compat_3.py new file mode 100644 index 000000000..a1ee0e6f1 --- /dev/null +++ b/testing/test_compat_3.py @@ -0,0 +1,15 @@ +import pytest +from _pytest.compat import is_generator +try: + import asyncio +except ImportError: + asyncio = None + + +@pytest.mark.skipif(asyncio is None, reason='asyncio is not installed') +def test_is_generator(): + @asyncio.coroutine + def baz(): + yield from [1,2,3] + + assert not is_generator(baz) diff --git a/testing/test_compat_35.py b/testing/test_compat_35.py new file mode 100644 index 000000000..93eecc920 --- /dev/null +++ b/testing/test_compat_35.py @@ -0,0 +1,12 @@ +from _pytest.compat import is_generator + + +def test_is_generator_py35(): + async def foo(): + await foo() + + async def bar(): + pass + + assert not is_generator(foo) + assert not is_generator(bar) From 45eb9b566c318b529219263936a8592cb4c26a88 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 13 Dec 2016 21:28:07 -0200 Subject: [PATCH 21/33] Move compat tests to a single file using testdir This avoids having to resort to skipping modules in conftest.py file and avoids flake8 errors --- testing/conftest.py | 7 ------- testing/test_compat.py | 37 +++++++++++++++++++++++++++++++++++++ testing/test_compat_3.py | 15 --------------- testing/test_compat_35.py | 12 ------------ 4 files changed, 37 insertions(+), 34 deletions(-) delete mode 100644 testing/conftest.py delete mode 100644 testing/test_compat_3.py delete mode 100644 testing/test_compat_35.py diff --git a/testing/conftest.py b/testing/conftest.py deleted file mode 100644 index 76a314837..000000000 --- a/testing/conftest.py +++ /dev/null @@ -1,7 +0,0 @@ -import sys - -collect_ignore = [] -if sys.version_info[0] < 3: - collect_ignore.append("test_compat_3.py") -if sys.version_info < (3, 5): - collect_ignore.append("test_compat_35.py") diff --git a/testing/test_compat.py b/testing/test_compat.py index 185fc3bd6..d704bb807 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,3 +1,6 @@ +import sys + +import pytest from _pytest.compat import is_generator @@ -10,3 +13,37 @@ def test_is_generator(): assert is_generator(zap) assert not is_generator(foo) + + +def test_is_generator_asyncio(testdir): + pytest.importorskip('asyncio') + testdir.makepyfile(""" + from _pytest.compat import is_generator + import asyncio + @asyncio.coroutine + def baz(): + yield from [1,2,3] + + def test_is_generator_asyncio(): + assert not is_generator(baz) + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines(['*1 passed*']) + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason='async syntax available in Python 3.5+') +def test_is_generator_async_syntax(testdir): + testdir.makepyfile(""" + from _pytest.compat import is_generator + def test_is_generator_py35(): + async def foo(): + await foo() + + async def bar(): + pass + + assert not is_generator(foo) + assert not is_generator(bar) + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines(['*1 passed*']) diff --git a/testing/test_compat_3.py b/testing/test_compat_3.py deleted file mode 100644 index a1ee0e6f1..000000000 --- a/testing/test_compat_3.py +++ /dev/null @@ -1,15 +0,0 @@ -import pytest -from _pytest.compat import is_generator -try: - import asyncio -except ImportError: - asyncio = None - - -@pytest.mark.skipif(asyncio is None, reason='asyncio is not installed') -def test_is_generator(): - @asyncio.coroutine - def baz(): - yield from [1,2,3] - - assert not is_generator(baz) diff --git a/testing/test_compat_35.py b/testing/test_compat_35.py deleted file mode 100644 index 93eecc920..000000000 --- a/testing/test_compat_35.py +++ /dev/null @@ -1,12 +0,0 @@ -from _pytest.compat import is_generator - - -def test_is_generator_py35(): - async def foo(): - await foo() - - async def bar(): - pass - - assert not is_generator(foo) - assert not is_generator(bar) From 1312b83866709611aaa9d9d22e3161dfd9b8d244 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 13 Dec 2016 21:33:01 -0200 Subject: [PATCH 22/33] Add CHANGELOG entry for #2129 --- CHANGELOG.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 707253958..3bb525c1e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,7 +3,8 @@ * -* +* pytest no longer recognizes coroutine functions as yield tests (`#2129`_). + Thanks to `@malinoff`_ for the PR. * @@ -12,6 +13,9 @@ * +.. _@malinoff: https://github.com/malinoff + +.. _#2129: https://github.com/pytest-dev/pytest/issues/2129 3.0.5 (2016-12-05) ================== From caee5ce489e4f7058154bea1b4bc371bd384af20 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 13 Dec 2016 21:54:20 -0200 Subject: [PATCH 23/33] Avoid importing asyncio directly because that in turn initializes logging (#8) --- _pytest/compat.py | 19 +++++++++++-------- testing/test_compat.py | 5 +++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/_pytest/compat.py b/_pytest/compat.py index 7a3d0af81..dc3e69545 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -19,11 +19,6 @@ except ImportError: # pragma: no cover # Only available in Python 3.4+ or as a backport enum = None -try: - import asyncio -except ImportError: # pragma: no cover - # Only available in Python 3.4+ or as a backport - asyncio = None _PY3 = sys.version_info > (3, 0) _PY2 = not _PY3 @@ -49,9 +44,17 @@ REGEX_TYPE = type(re.compile('')) def is_generator(func): genfunc = inspect.isgeneratorfunction(func) - if asyncio is not None: - return genfunc and not asyncio.iscoroutinefunction(func) - return genfunc + return genfunc and not iscoroutinefunction(func) + + +def iscoroutinefunction(func): + """Return True if func is a decorated coroutine function. + + Note: copied and modified from Python 3.5's builtin couroutines.py to avoid import asyncio directly, + which in turns also initializes the "logging" module as side-effect (see issue #8). + """ + return (getattr(func, '_is_coroutine', False) or + (hasattr(inspect, 'iscoroutinefunction') and inspect.iscoroutinefunction(func))) def getlocation(function, curdir): diff --git a/testing/test_compat.py b/testing/test_compat.py index d704bb807..1fdd07e29 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -15,8 +15,8 @@ def test_is_generator(): assert not is_generator(foo) +@pytest.mark.skipif(sys.version_info < (3, 4), reason='asyncio available in Python 3.4+') def test_is_generator_asyncio(testdir): - pytest.importorskip('asyncio') testdir.makepyfile(""" from _pytest.compat import is_generator import asyncio @@ -27,7 +27,8 @@ def test_is_generator_asyncio(testdir): def test_is_generator_asyncio(): assert not is_generator(baz) """) - result = testdir.runpytest() + # avoid importing asyncio into pytest's own process, which in turn imports logging (#8) + result = testdir.runpytest_subprocess() result.stdout.fnmatch_lines(['*1 passed*']) From 3f5edc705a336cf7a40dd1117065e9a413d27847 Mon Sep 17 00:00:00 2001 From: Stefan Scherfke Date: Mon, 19 Dec 2016 13:22:25 +0100 Subject: [PATCH 24/33] Explicitly add setuptools to install_requires Setuptools is used in `_pytest/config.py` but was not explicitly listed as requirement. This led to an error when creating a Conda package for pytest since setuptools is not necessarily installed by default in Conda envs. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cdcf3b3bb..f03ab9c40 100644 --- a/setup.py +++ b/setup.py @@ -48,7 +48,7 @@ def has_environment_marker_support(): def main(): - install_requires = ['py>=1.4.29'] # pluggy is vendored in _pytest.vendored_packages + install_requires = ['py>=1.4.29', 'setuptools'] # pluggy is vendored in _pytest.vendored_packages extras_require = {} if has_environment_marker_support(): extras_require[':python_version=="2.6"'] = ['argparse'] From f94189b48b7a50ad51f9b40c6f26a93ccc9565fb Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Tue, 20 Dec 2016 01:48:32 +0100 Subject: [PATCH 25/33] Fix wrong fixture name. Closes #2143. --- doc/en/fixture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index bbc4a95c4..9bc4f6084 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -1002,7 +1002,7 @@ Given the tests file structure is: @pytest.mark.parametrize('username', ['directly-overridden-username-other']) def test_username_other(other_username): - assert username == 'other-directly-overridden-username-other' + assert other_username == 'other-directly-overridden-username-other' In the example above, a fixture value is overridden by the test parameter value. Note that the value of the fixture can be overridden this way even if the test doesn't use it directly (doesn't mention it in the function prototype). From c5f0b751f48d1c44e74d14e7d89772b825ffa332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Tue, 20 Dec 2016 13:36:57 +0100 Subject: [PATCH 26/33] Improve error message when pytest.warns fail The error message contains the expected type of warnings and the warnings that were captured. Add tests. --- _pytest/recwarn.py | 5 ++++- testing/test_recwarn.py | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index 87823bfbc..d66f87e72 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -223,4 +223,7 @@ class WarningsChecker(WarningsRecorder): if self.expected_warning is not None: if not any(r.category in self.expected_warning for r in self): __tracebackhide__ = True - pytest.fail("DID NOT WARN") + pytest.fail("DID NOT WARN. No warnings of type {0} was emitted. " + "The list of emitted warnings is: {1}.".format( + self.expected_warning, + [each.message for each in self])) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 87e5846c2..0f3bf6a14 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,4 +1,5 @@ import warnings +import re import py import pytest from _pytest.recwarn import WarningsRecorder @@ -114,7 +115,7 @@ class TestDeprecatedCall(object): with pytest.raises(pytest.fail.Exception) as ex: with pytest.deprecated_call(): self.dep(1) - assert str(ex.value) == "DID NOT WARN" + assert str(ex.value).startswith("DID NOT WARN") def test_deprecated_call_as_context_manager(self): with pytest.deprecated_call(): @@ -185,17 +186,39 @@ class TestWarns(object): with pytest.warns(RuntimeWarning): warnings.warn("runtime", RuntimeWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.warns(RuntimeWarning): - warnings.warn("user", UserWarning) - - with pytest.raises(pytest.fail.Exception): - with pytest.warns(UserWarning): - warnings.warn("runtime", RuntimeWarning) - with pytest.warns(UserWarning): warnings.warn("user", UserWarning) + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(RuntimeWarning): + warnings.warn("user", UserWarning) + excinfo.match(r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) was emitted. " + r"The list of emitted warnings is: \[UserWarning\('user',\)\].") + + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(UserWarning): + warnings.warn("runtime", RuntimeWarning) + excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. " + r"The list of emitted warnings is: \[RuntimeWarning\('runtime',\)\].") + + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(UserWarning): + pass + excinfo.match(r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) was emitted. " + r"The list of emitted warnings is: \[\].") + + warning_classes = (UserWarning, FutureWarning) + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(warning_classes) as warninfo: + warnings.warn("runtime", RuntimeWarning) + warnings.warn("import", ImportWarning) + + message_template = ("DID NOT WARN. No warnings of type {0} was emitted. " + "The list of emitted warnings is: {1}.") + excinfo.match(re.escape(message_template.format(warning_classes, + [each.message for each in warninfo]))) + + def test_record(self): with pytest.warns(UserWarning) as record: warnings.warn("user", UserWarning) From bfada968d3d1947523a6cf70f59d44620a9505c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Tue, 20 Dec 2016 14:36:10 +0100 Subject: [PATCH 27/33] Update AUTHORS and CHANGELOG.rst following contribution guidelines --- AUTHORS | 1 + CHANGELOG.rst | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 8c7cb19ce..8c6fa1b5d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -82,6 +82,7 @@ Katarzyna Jachim Kevin Cox Lee Kamentsky Lev Maximov +Loic Esteve Lukas Bednar Luke Murphy Maciek Fijalkowski diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 707253958..847d27c51 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,12 +5,17 @@ * -* +* Improve error message when pytest.warns fails (`#2150`_). The type(s) of the + expected warnings and the list of caught warnings is added to the + error message. Thanks `@lesteve`_ for the PR. * * +.. _@lesteve: https://github.com/lesteve + +.. _#2150: https://github.com/pytest-dev/pytest/issues/2150 3.0.5 (2016-12-05) From f7a1d369c35cf2716d84751b4132bfc90c68a162 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 26 Dec 2016 21:47:50 -0200 Subject: [PATCH 28/33] Allow trial environments to fail on CI for now While I agree this is *far* from ideal, IMHO It is better to ignore them for now otherwise we hamper contributors with unrelated errors. We should fix this before the next release. #1989 --- .travis.yml | 3 ++- appveyor.yml | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bbc03d856..a7b84194e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,8 @@ env: matrix: allow_failures: - # py35-trial failing on Linux: #1989 + # see #1989 + - env: TESTENV=py27-trial - env: TESTENV=py35-trial script: tox --recreate -e $TESTENV diff --git a/appveyor.yml b/appveyor.yml index a42aa16dc..c82b81ce9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -27,6 +27,12 @@ environment: - TOXENV: "freeze" - TOXENV: "docs" +matrix: + allow_failures: + # see #1989 + - TOXENV: "py27-trial" + - TOXENV: "py35-trial" + install: - echo Installed Pythons - dir c:\Python* From 0bb8a4a36d8b32f17d6e0cf8aebe9c4a92a99cfa Mon Sep 17 00:00:00 2001 From: Andreas Pelme Date: Tue, 20 Dec 2016 11:22:18 +0100 Subject: [PATCH 29/33] Fixed #2148 - parse directory names properly when args contains ::. This commit also improves readbility in get_dirs_from_args by using self documenting local functions. get_dirs_from_args also now only returns directories that actually exists, and not files to avoid confusion. This commit also removes redundant checks in get_common_ancestor that was already performed in get_dirs_from_args.. --- CHANGELOG.rst | 6 +++++- _pytest/config.py | 47 ++++++++++++++++++++++++++++-------------- testing/test_config.py | 23 +++++++++++++++++++++ 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 847d27c51..6ad73d0c2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -9,13 +9,17 @@ expected warnings and the list of caught warnings is added to the error message. Thanks `@lesteve`_ for the PR. -* +* Specifying tests with colons like ``test_foo.py::test_bar`` for tests in + subdirectories with ini configuration files now uses the correct ini file + (`#2148`_). Thanks `@pelme`_. * .. _@lesteve: https://github.com/lesteve +.. _@pelme: https://github.com/pelme .. _#2150: https://github.com/pytest-dev/pytest/issues/2150 +.. _#2148: https://github.com/pytest-dev/pytest/issues/2148 3.0.5 (2016-12-05) diff --git a/_pytest/config.py b/_pytest/config.py index fe386ed0b..55326447e 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -1228,25 +1228,20 @@ def getcfg(args, warnfunc=None): return None, None, None -def get_common_ancestor(args): - # args are what we get after early command line parsing (usually - # strings, but can be py.path.local objects as well) +def get_common_ancestor(paths): common_ancestor = None - for arg in args: - if str(arg)[0] == "-": - continue - p = py.path.local(arg) - if not p.exists(): + for path in paths: + if not path.exists(): continue if common_ancestor is None: - common_ancestor = p + common_ancestor = path else: - if p.relto(common_ancestor) or p == common_ancestor: + if path.relto(common_ancestor) or path == common_ancestor: continue - elif common_ancestor.relto(p): - common_ancestor = p + elif common_ancestor.relto(path): + common_ancestor = path else: - shared = p.common(common_ancestor) + shared = path.common(common_ancestor) if shared is not None: common_ancestor = shared if common_ancestor is None: @@ -1257,9 +1252,29 @@ def get_common_ancestor(args): def get_dirs_from_args(args): - return [d for d in (py.path.local(x) for x in args - if not str(x).startswith("-")) - if d.exists()] + def is_option(x): + return str(x).startswith('-') + + def get_file_part_from_node_id(x): + return str(x).split('::')[0] + + def get_dir_from_path(path): + if path.isdir(): + return path + return py.path.local(path.dirname) + + # These look like paths but may not exist + possible_paths = ( + py.path.local(get_file_part_from_node_id(arg)) + for arg in args + if not is_option(arg) + ) + + return [ + get_dir_from_path(path) + for path in possible_paths + if path.exists() + ] def determine_setup(inifile, args, warnfunc=None): diff --git a/testing/test_config.py b/testing/test_config.py index 21ceab1e2..6bc867737 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -527,6 +527,29 @@ def test_toolongargs_issue224(testdir): result = testdir.runpytest("-m", "hello" * 500) assert result.ret == EXIT_NOTESTSCOLLECTED +def test_config_in_subdirectory_colon_command_line_issue2148(testdir): + conftest_source = ''' + def pytest_addoption(parser): + parser.addini('foo', 'foo') + ''' + + testdir.makefile('.ini', **{ + 'pytest': '[pytest]\nfoo = root', + 'subdir/pytest': '[pytest]\nfoo = subdir', + }) + + testdir.makepyfile(**{ + 'conftest': conftest_source, + 'subdir/conftest': conftest_source, + 'subdir/test_foo': ''' + def test_foo(pytestconfig): + assert pytestconfig.getini('foo') == 'subdir' + '''}) + + result = testdir.runpytest('subdir/test_foo.py::test_foo') + assert result.ret == 0 + + def test_notify_exception(testdir, capfd): config = testdir.parseconfig() excinfo = pytest.raises(ValueError, "raise ValueError(1)") From 1680eeb3a3cf13892c5fae59a9d251727370df39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 13 Dec 2016 13:49:44 +0100 Subject: [PATCH 30/33] Tests: Check for ModuleNotFoundError on Python 3.6+ Those tests originally checked for ImportError. Since Python 3.6 ModuleNotFoundError is raised in this context instead, the tests didn't work as they are text based (so exception inheritance does not save the day). Fixes https://github.com/pytest-dev/pytest/issues/2132 --- testing/test_doctest.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 4ea2cc58e..196a5670e 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -4,6 +4,10 @@ import _pytest._code from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile import pytest +PY36 = sys.version_info[:2] >= (3, 6) +MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError' + + class TestDoctests: def test_collect_testtextfile(self, testdir): @@ -211,8 +215,8 @@ class TestDoctests: # doctest is never executed because of error during hello.py collection result.stdout.fnmatch_lines([ "*>>> import asdals*", - "*UNEXPECTED*ImportError*", - "ImportError: No module named *asdal*", + "*UNEXPECTED*{e}*".format(e=MODULE_NOT_FOUND_ERROR), + "{e}: No module named *asdal*".format(e=MODULE_NOT_FOUND_ERROR), ]) def test_doctest_unex_importerror_with_module(self, testdir): @@ -227,7 +231,7 @@ class TestDoctests: # doctest is never executed because of error during hello.py collection result.stdout.fnmatch_lines([ "*ERROR collecting hello.py*", - "*ImportError: No module named *asdals*", + "*{e}: No module named *asdals*".format(e=MODULE_NOT_FOUND_ERROR), "*Interrupted: 1 errors during collection*", ]) From 6b24ce2a9d618bbda2c2f1dd70c8d7f43c474473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 13 Dec 2016 15:16:06 +0100 Subject: [PATCH 31/33] Test Python 3.6 on Travis CI Partial fix for https://github.com/pytest-dev/pytest/issues/2134 --- .travis.yml | 3 +++ tox.ini | 1 + 2 files changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index bbc03d856..c4699ec4b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,9 @@ matrix: allow_failures: # py35-trial failing on Linux: #1989 - env: TESTENV=py35-trial + include: + - env: TESTENV=py36 + python: '3.6-dev' script: tox --recreate -e $TESTENV diff --git a/tox.ini b/tox.ini index f3494e8be..a5dec3fdc 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,7 @@ envlist= py33 py34 py35 + py36 pypy {py27,py35}-{pexpect,xdist,trial} py27-nobyte From 515fb099957286b6c692d0fb95b789dbfcae6b0a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Dec 2016 22:01:22 -0200 Subject: [PATCH 32/33] Move module error compatibility code to _pytest.compat --- _pytest/compat.py | 3 +++ testing/test_doctest.py | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/_pytest/compat.py b/_pytest/compat.py index 51fc3bc5c..8f4d0a8e6 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -26,6 +26,9 @@ _PY2 = not _PY3 NoneType = type(None) NOTSET = object() +PY36 = sys.version_info[:2] >= (3, 6) +MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError' + if hasattr(inspect, 'signature'): def _format_args(func): return str(inspect.signature(func)) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 196a5670e..faf75ef33 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,12 +1,10 @@ # encoding: utf-8 import sys import _pytest._code +from _pytest.compat import MODULE_NOT_FOUND_ERROR from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile import pytest -PY36 = sys.version_info[:2] >= (3, 6) -MODULE_NOT_FOUND_ERROR = 'ModuleNotFoundError' if PY36 else 'ImportError' - class TestDoctests: From 7592c5b491ac83c3c2be1b580a3a6afde469114e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Dec 2016 23:20:34 -0200 Subject: [PATCH 33/33] Sort issues and user references in CHANGELOG --- CHANGELOG.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fff42ce3b..9d0b80ecf 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,14 +17,13 @@ * .. _@lesteve: https://github.com/lesteve +.. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme -.. _#2150: https://github.com/pytest-dev/pytest/issues/2150 -.. _#2148: https://github.com/pytest-dev/pytest/issues/2148 - -.. _@malinoff: https://github.com/malinoff - .. _#2129: https://github.com/pytest-dev/pytest/issues/2129 +.. _#2148: https://github.com/pytest-dev/pytest/issues/2148 +.. _#2150: https://github.com/pytest-dev/pytest/issues/2150 + 3.0.5 (2016-12-05) ==================