From 06bb61bbe31829955b36451829fdb9b4ffedc65b Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 20 Nov 2016 11:56:15 -0500 Subject: [PATCH 001/106] Don't fail if imp can't find the source for a .pyc file. #2038 --- AUTHORS | 1 + CHANGELOG.rst | 7 ++++++- _pytest/assertion/rewrite.py | 7 ++++++- testing/test_assertrewrite.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 6de0a112b..8cc6824cd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -101,6 +101,7 @@ Michael Birtwell Michael Droettboom Michael Seifert Mike Lundy +Ned Batchelder Nicolas Delaby Oleg Pidsadnyi Oliver Bestwalter diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 60875f4c4..b87302e8c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,12 +5,17 @@ * -* +* Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks + `@nedbat`_. * * +.. _@nedbat: https://github.com/nedbat + +.. _#2038: https://github.com/pytest-dev/pytest/issues/2038 + 3.0.4 ===== diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py index 6b4c1f483..9136c3867 100644 --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -80,7 +80,12 @@ class AssertionRewritingHook(object): tp = desc[2] if tp == imp.PY_COMPILED: if hasattr(imp, "source_from_cache"): - fn = imp.source_from_cache(fn) + try: + fn = imp.source_from_cache(fn) + except ValueError: + # Python 3 doesn't like orphaned but still-importable + # .pyc files. + fn = fn[:-1] else: fn = fn[:-1] elif tp != imp.PY_SOURCE: diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index e72266a18..ded11cbb4 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1,7 +1,10 @@ +import glob import os +import py_compile import stat import sys import zipfile + import py import pytest @@ -480,6 +483,31 @@ def test_rewritten(): monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", "1") assert testdir.runpytest_subprocess().ret == 0 + def test_orphaned_pyc_file(self, testdir): + if sys.version_info < (3, 0) and hasattr(sys, 'pypy_version_info'): + pytest.skip("pypy2 doesn't run orphaned pyc files") + + testdir.makepyfile(""" + import orphan + def test_it(): + assert orphan.value == 17 + """) + testdir.makepyfile(orphan=""" + value = 17 + """) + py_compile.compile("orphan.py") + os.remove("orphan.py") + + # Python 3 puts the .pyc files in a __pycache__ directory, and will + # not import from there without source. It will import a .pyc from + # the source location though. + if not os.path.exists("orphan.pyc"): + pycs = glob.glob("__pycache__/orphan.*.pyc") + assert len(pycs) == 1 + os.rename(pycs[0], "orphan.pyc") + + assert testdir.runpytest().ret == 0 + @pytest.mark.skipif('"__pypy__" in sys.modules') def test_pyc_vs_pyo(self, testdir, monkeypatch): testdir.makepyfile(""" From 629d8e9fd62999ffbb80fcb8881c1c88e51d345f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 23 Nov 2016 09:47:36 -0200 Subject: [PATCH 002/106] Show an error if --confcutdir is not a valid directory Fixes #2078 --- CHANGELOG.rst | 6 +++++- _pytest/config.py | 6 +++++- testing/test_config.py | 9 +++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b87302e8c..eeb41a648 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,7 +3,10 @@ * -* +* An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding + subtle bugs (`#2078`_). + Thanks `@nicoddemus`_ for the PR. + * Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks `@nedbat`_. @@ -15,6 +18,7 @@ .. _@nedbat: https://github.com/nedbat .. _#2038: https://github.com/pytest-dev/pytest/issues/2038 +.. _#2078: https://github.com/pytest-dev/pytest/issues/2078 3.0.4 diff --git a/_pytest/config.py b/_pytest/config.py index ab5e1b994..61123f6ac 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -996,6 +996,7 @@ 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 @@ -1007,7 +1008,10 @@ class Config(object): self.pluginmanager.load_setuptools_entrypoints(entrypoint_name) self.pluginmanager.consider_env() self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy()) - if self.known_args_namespace.confcutdir is None and self.inifile: + 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: confcutdir = py.path.local(self.inifile).dirname self.known_args_namespace.confcutdir = confcutdir try: diff --git a/testing/test_config.py b/testing/test_config.py index 75a806c4a..1567dd27c 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -294,6 +294,15 @@ class TestConfigAPI: assert len(l) == 2 assert l == ["456", "123"] + def test_confcutdir_check_isdir(self, testdir): + """Give an error if --confcutdir is not a valid directory (#2078)""" + with pytest.raises(pytest.UsageError): + testdir.parseconfig('--confcutdir', testdir.tmpdir.join('file').ensure(file=1)) + with pytest.raises(pytest.UsageError): + testdir.parseconfig('--confcutdir', testdir.tmpdir.join('inexistant')) + config = testdir.parseconfig('--confcutdir', testdir.tmpdir.join('dir').ensure(dir=1)) + assert config.getoption('confcutdir') == str(testdir.tmpdir.join('dir')) + class TestConfigFromdictargs: def test_basic_behavior(self): From 33c0b06fdf989d8df63dc68ba5336ecad2eadd30 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 24 Nov 2016 15:27:38 -0200 Subject: [PATCH 003/106] Fix error in approx's repr with complex numbers Fix #2082 --- CHANGELOG.rst | 6 ++++++ _pytest/python.py | 3 +++ testing/python/approx.py | 1 + 3 files changed, 10 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index eeb41a648..f97ff3787 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,10 @@ 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. + +* * Cope gracefully with a .pyc file with no matching .py file (`#2038`_). Thanks `@nedbat`_. @@ -15,10 +19,12 @@ * +.. _@adler-j: https://github.com/adler-j .. _@nedbat: https://github.com/nedbat .. _#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 3.0.4 diff --git a/_pytest/python.py b/_pytest/python.py index 88c65b1ce..76cf4bd64 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1419,6 +1419,9 @@ class ApproxNonIterable(object): self.rel = rel def __repr__(self): + if isinstance(self.expected, complex): + return str(self.expected) + # Infinities aren't compared using tolerances, so don't show a # tolerance. if math.isinf(self.expected): diff --git a/testing/python/approx.py b/testing/python/approx.py index 2720c573f..d6bb1f9cf 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -28,6 +28,7 @@ class TestApprox: print(approx(inf)) print(approx(1.0, rel=nan)) print(approx(1.0, rel=inf)) + print(approx(1.0j, rel=inf)) def test_operator_overloading(self): assert 1 == approx(1, rel=1e-6, abs=1e-12) From 8763590eefe7d1e5e2668bcb4a057f726f5e4a0e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 24 Nov 2016 16:08:51 -0200 Subject: [PATCH 004/106] Only execute "coveralls" toxenv on master once Just noticed that the "coveralls" env was being execute after each env. This was introduced by mistake in #2056 --- appveyor.yml | 9 ++++----- scripts/call-tox.bat | 8 ++++++++ 2 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 scripts/call-tox.bat diff --git a/appveyor.yml b/appveyor.yml index 7192ec06f..a42aa16dc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,6 +6,8 @@ environment: # https://www.appveyor.com/docs/build-configuration#secure-variables matrix: + # coveralls is not in the default env list + - TOXENV: "coveralls" # note: please use "tox --listenvs" to populate the build matrix below - TOXENV: "linting" - TOXENV: "py26" @@ -29,14 +31,11 @@ install: - echo Installed Pythons - dir c:\Python* - - if "%TOXENV%" == "pypy" scripts\install-pypy.bat + - if "%TOXENV%" == "pypy" call scripts\install-pypy.bat - C:\Python35\python -m pip install tox build: false # Not a C# project, build stuff at the test step instead. test_script: - - C:\Python35\python -m tox - # coveralls is not in tox's envlist, plus for PRs the secure variable - # is not defined so we have to check for it - - if defined COVERALLS_REPO_TOKEN C:\Python35\python -m tox -e coveralls + - call scripts\call-tox.bat diff --git a/scripts/call-tox.bat b/scripts/call-tox.bat new file mode 100644 index 000000000..3ca9eb6d7 --- /dev/null +++ b/scripts/call-tox.bat @@ -0,0 +1,8 @@ +REM skip "coveralls" run in PRs or forks +if "%TOXENV%" == "coveralls" ( + if not defined COVERALLS_REPO_TOKEN ( + echo skipping coveralls run because COVERALLS_REPO_TOKEN is not defined + exit /b 0 + ) +) +C:\Python35\python -m tox From c1b83cdeea9763635bc182ab7f8c94aae3d4c4ad Mon Sep 17 00:00:00 2001 From: Duncan Betts Date: Sat, 26 Nov 2016 10:47:15 +0000 Subject: [PATCH 005/106] Add hint of Issue #478 to error text --- AUTHORS | 1 + CHANGELOG.rst | 4 +++- _pytest/main.py | 5 ++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/AUTHORS b/AUTHORS index 8cc6824cd..e966139be 100644 --- a/AUTHORS +++ b/AUTHORS @@ -44,6 +44,7 @@ David Mohr David Vierra Diego Russo Dmitry Dygalo +Duncan Betts Edison Gustavo Muenz Edoardo Batini Eduardo Schettino diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f97ff3787..40797c30c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,7 @@ 3.0.5.dev0 ========== -* +* Add hint to error message hinting possible missing __init__.py (`#478`_). Thanks `@DuncanBetts`_. * An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding subtle bugs (`#2078`_). @@ -20,8 +20,10 @@ * .. _@adler-j: https://github.com/adler-j +.. _@DuncanBetts: https://github.com/DuncanBetts .. _@nedbat: https://github.com/nedbat +.. _#478: https://github.com/pytest-dev/pytest/issues/478 .. _#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 diff --git a/_pytest/main.py b/_pytest/main.py index 5771a1699..dd0775501 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -704,10 +704,9 @@ class Session(FSCollector): path = self.config.invocation_dir.join(relpath, abs=True) if not path.check(): if self.config.option.pyargs: - msg = "file or package not found: " + raise pytest.UsageError("file or package not found: " + arg + " (missing __init__.py?)") else: - msg = "file not found: " - raise pytest.UsageError(msg + arg) + raise pytest.UsageError("file not found: " + arg) parts[0] = path return parts From 2e6a58ab6981ce5bed1becf5239951654166ccbb Mon Sep 17 00:00:00 2001 From: Ana Vojnovic Date: Sat, 26 Nov 2016 15:04:52 +0100 Subject: [PATCH 006/106] Clarify test discovery docs. --- doc/en/goodpractices.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/en/goodpractices.rst b/doc/en/goodpractices.rst index 2a5d4d7c8..d1e3e66fd 100644 --- a/doc/en/goodpractices.rst +++ b/doc/en/goodpractices.rst @@ -16,10 +16,12 @@ Conventions for Python test discovery * If no arguments are specified then collection starts from :confval:`testpaths` (if configured) or the current directory. Alternatively, command line arguments can be used in any combination of directories, file names or node ids. -* recurse into directories, unless they match :confval:`norecursedirs` -* ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_. -* ``Test`` prefixed test classes (without an ``__init__`` method) -* ``test_`` prefixed test functions or methods are test items +* Recurse into directories, unless they match :confval:`norecursedirs`. +* In those directories, search for ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_. +* From those files, collect test items: + + * ``test_`` prefixed test functions or methods outside of class + * ``test_`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method) For examples of how to customize your test discovery :doc:`example/pythoncollection`. From 61205701981d9d27e0bd0209f2bf577156eb01d5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 26 Nov 2016 14:49:31 -0200 Subject: [PATCH 007/106] Pin setuptools to < 29 because of AppVeyor failures Related to pypa/setuptools#861 Remove the pin when we have a new setuptools release --- tox.ini | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c2f866f26..f0c8e93d4 100644 --- a/tox.ini +++ b/tox.ini @@ -117,7 +117,10 @@ commands= basepython = python usedevelop=True skipsdist=True -deps=PyYAML +deps= + PyYAML + # pinning setuptools because of AppVeyor failures, see pypa/setuptools#861 + setuptools<29.0.0 commands= pytest -rfsxX doc/en pytest --doctest-modules {toxinidir}/_pytest From 1aa5bfea11e00ebc1e288f5ad818d937c03caef4 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 26 Nov 2016 12:25:42 +0100 Subject: [PATCH 008/106] Add `:ref:` targets to `recwarn.rst`. --- AUTHORS | 1 + CHANGELOG.rst | 5 +++++ doc/en/recwarn.rst | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/AUTHORS b/AUTHORS index e966139be..d8fb8f703 100644 --- a/AUTHORS +++ b/AUTHORS @@ -83,6 +83,7 @@ Kevin Cox Lee Kamentsky Lev Maximov Lukas Bednar +Luke Murphy Maciek Fijalkowski Maho Marc Schlaich diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 40797c30c..8fb7b1589 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,9 @@ * 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. + Thanks to `@dupuy`_ for the report and `@lwm`_ 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. @@ -19,6 +22,8 @@ * +.. _@dupuy: https://bitbucket.org/dupuy/ +.. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j .. _@DuncanBetts: https://github.com/DuncanBetts .. _@nedbat: https://github.com/nedbat diff --git a/doc/en/recwarn.rst b/doc/en/recwarn.rst index 735006016..7bb193c99 100644 --- a/doc/en/recwarn.rst +++ b/doc/en/recwarn.rst @@ -1,8 +1,12 @@ +.. _`asserting warnings`: + .. _assertwarnings: Asserting Warnings ===================================================== +.. _`asserting warnings with the warns function`: + .. _warns: Asserting warnings with the warns function @@ -46,6 +50,8 @@ Alternatively, you can examine raised warnings in detail using the ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated differently; see :ref:`ensuring_function_triggers`. +.. _`recording warnings`: + .. _recwarn: Recording warnings @@ -96,6 +102,8 @@ class of the warning. The ``message`` is the warning itself; calling ``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated differently; see :ref:`ensuring_function_triggers`. +.. _`ensuring a function triggers a deprecation warning`: + .. _ensuring_function_triggers: Ensuring a function triggers a deprecation warning From 6c5475660afadd66a8ab46c415e45e2839d3d581 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 26 Nov 2016 18:47:26 +0100 Subject: [PATCH 009/106] Add test case for #595. This new test proves that reports do not capture stdout by default when skipped. --- testing/test_junitxml.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 85e49e451..443b8111b 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -249,6 +249,18 @@ class TestPython: snode = tnode.find_first_by_tag("skipped") snode.assert_attr(type="pytest.skip", message="hello25", ) + def test_mark_skip_doesnt_capture_output(self, testdir): + testdir.makepyfile(""" + import pytest + @pytest.mark.skip(reason="foo") + def test_skip(): + print("bar!") + """) + result, dom = runandparse(testdir) + assert result.ret == 0 + node_xml = dom.find_first_by_tag("testsuite").toxml() + assert "bar!" not in node_xml + def test_classname_instance(self, testdir): testdir.makepyfile(""" class TestClass: From 0aa891543d4b3961e600f2f153f57bdff4f3963f Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 26 Nov 2016 18:57:51 +0100 Subject: [PATCH 010/106] Add documentation building note. --- CONTRIBUTING.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 19b31c7f4..71dc04d91 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -79,6 +79,16 @@ Pytest could always use more documentation. What exactly is needed? You can also edit documentation files directly in the GitHub web interface, without using a local copy. This can be convenient for small fixes. +.. note:: + Build the documentation locally with the following command: + + .. code:: bash + + $ tox -e docs + + The built documentation should be available in the ``doc/en/_build/``. + + Where 'en' refers to the documentation language. .. _submitplugin: From 5566b3ccb6949623137e693da570176fa56a8cf0 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 27 Nov 2016 03:26:35 -0200 Subject: [PATCH 011/106] Remove setuptools pin now that upstream has been fixed Related to pypa/setuptools#861 --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index f0c8e93d4..f3494e8be 100644 --- a/tox.ini +++ b/tox.ini @@ -119,8 +119,6 @@ usedevelop=True skipsdist=True deps= PyYAML - # pinning setuptools because of AppVeyor failures, see pypa/setuptools#861 - setuptools<29.0.0 commands= pytest -rfsxX doc/en pytest --doctest-modules {toxinidir}/_pytest From b38fad4b82123b392409fe78be01db2f39c7985b Mon Sep 17 00:00:00 2001 From: nmundar Date: Sat, 26 Nov 2016 12:22:58 +0100 Subject: [PATCH 012/106] Add compatproperty deprecation warning. --- _pytest/main.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_pytest/main.py b/_pytest/main.py index dd0775501..33d7ef432 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -190,7 +190,9 @@ class FSHookProxy: def compatproperty(name): def fget(self): - # deprecated - use pytest.name + import warnings + warnings.warn("compatproperty is deprecated. Use pytest.name", + PendingDeprecationWarning, stacklevel=2) return getattr(pytest, name) return property(fget) From 0e6ad8e59f7ee25860c2cf4626d26f2dabd37ef5 Mon Sep 17 00:00:00 2001 From: nmundar Date: Sat, 26 Nov 2016 12:36:32 +0100 Subject: [PATCH 013/106] update CHANGELOG and AUTHORS --- AUTHORS | 1 + CHANGELOG.rst | 3 +++ 2 files changed, 4 insertions(+) diff --git a/AUTHORS b/AUTHORS index d8fb8f703..8c7cb19ce 100644 --- a/AUTHORS +++ b/AUTHORS @@ -104,6 +104,7 @@ Michael Droettboom Michael Seifert Mike Lundy Ned Batchelder +Neven Mundar Nicolas Delaby Oleg Pidsadnyi Oliver Bestwalter diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8fb7b1589..1820e083a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,9 @@ * Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing. Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR. +* Using ``pytest.main.compatproperty`` is now issuing deprecation warning. + 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. From 0a30f072e65da60f284af399e55c2ec897afb9cd Mon Sep 17 00:00:00 2001 From: nmundar Date: Sat, 26 Nov 2016 21:37:43 +0100 Subject: [PATCH 014/106] Show name argment in compatproperty deprecation message --- _pytest/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/main.py b/_pytest/main.py index 33d7ef432..2b5b12875 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -191,7 +191,7 @@ class FSHookProxy: def compatproperty(name): def fget(self): import warnings - warnings.warn("compatproperty is deprecated. Use pytest.name", + warnings.warn("This usage is deprecated, please use pytest.{0} instead".format(name), PendingDeprecationWarning, stacklevel=2) return getattr(pytest, name) From 2d7197926a8a2bb1cb8aebbe1fcb86e99837cad8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 27 Nov 2016 14:19:29 -0200 Subject: [PATCH 015/106] Improve CHANGELOG entry for #2034 --- CHANGELOG.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1820e083a..77b67ddbb 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,13 +1,14 @@ 3.0.5.dev0 ========== -* Add hint to error message hinting possible missing __init__.py (`#478`_). Thanks `@DuncanBetts`_. +* 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. Thanks to `@dupuy`_ for the report and `@lwm`_ for the PR. -* Using ``pytest.main.compatproperty`` is now issuing deprecation warning. - Thanks `@nmundar` 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. * An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding subtle bugs (`#2078`_). @@ -30,8 +31,10 @@ .. _@adler-j: https://github.com/adler-j .. _@DuncanBetts: https://github.com/DuncanBetts .. _@nedbat: https://github.com/nedbat +.. _@nmundar: https://github.com/nmundar .. _#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 .. _#2078: https://github.com/pytest-dev/pytest/issues/2078 .. _#2082: https://github.com/pytest-dev/pytest/issues/2082 From 788e394c935ef9f24ce1ef9035dbc570c17fe0ed Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 27 Nov 2016 14:45:52 -0200 Subject: [PATCH 016/106] Use "inc" instead of "func" in the snipped on README and doc index "inc" reads better, also fixed the line separators so they have the same size --- README.rst | 16 ++++++++-------- doc/en/index.rst | 26 ++++++++++++-------------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/README.rst b/README.rst index 5b2d329e0..d5650af65 100644 --- a/README.rst +++ b/README.rst @@ -24,31 +24,31 @@ An example of a simple test: .. code-block:: python # content of test_sample.py - def func(x): + def inc(x): return x + 1 def test_answer(): - assert func(3) == 5 + assert inc(3) == 5 To execute it:: $ pytest - ======= test session starts ======== + ============================= test session starts ============================= collected 1 items test_sample.py F - ======= FAILURES ======== - _______ test_answer ________ + ================================== FAILURES =================================== + _________________________________ test_answer _________________________________ def test_answer(): - > assert func(3) == 5 + > assert inc(3) == 5 E assert 4 == 5 - E + where 4 = func(3) + E + where 4 = inc(3) test_sample.py:5: AssertionError - ======= 1 failed in 0.12 seconds ======== + ========================== 1 failed in 0.04 seconds =========================== Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See `getting-started `_ for more examples. diff --git a/doc/en/index.rst b/doc/en/index.rst index aadabf222..67b13d3e3 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -14,33 +14,31 @@ An example of a simple test: .. code-block:: python # content of test_sample.py - def func(x): + def inc(x): return x + 1 def test_answer(): - assert func(3) == 5 + assert inc(3) == 5 To execute it:: $ pytest - ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 - rootdir: $REGENDOC_TMPDIR, inifile: + ============================= test session starts ============================= collected 1 items - + test_sample.py F - - ======= FAILURES ======== - _______ test_answer ________ - + + ================================== FAILURES =================================== + _________________________________ test_answer _________________________________ + def test_answer(): - > assert func(3) == 5 + > assert inc(3) == 5 E assert 4 == 5 - E + where 4 = func(3) - + E + where 4 = inc(3) + test_sample.py:5: AssertionError - ======= 1 failed in 0.12 seconds ======== + ========================== 1 failed in 0.04 seconds =========================== Due to ``pytest``'s detailed assertion introspection, only plain ``assert`` statements are used. See :ref:`Getting Started ` for more examples. From 4e1609b12eb1a44b0fc8519de458362d7fd8cdf2 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Mon, 28 Nov 2016 00:55:49 +0100 Subject: [PATCH 017/106] 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 018/106] 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 019/106] 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 ed977513ec6af2e9015e6f6eee6e6b2a0b48e2c5 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Tue, 29 Nov 2016 11:51:56 +0100 Subject: [PATCH 020/106] Added a console option to specify the encoding to use for doctest files. Defaults to UTF-8. --- _pytest/doctest.py | 6 +++++- doc/en/doctest.rst | 11 +++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/_pytest/doctest.py b/_pytest/doctest.py index f4782dded..05acc7c59 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -43,6 +43,10 @@ def pytest_addoption(parser): action="store_true", default=False, help="ignore doctest ImportErrors", dest="doctest_ignore_import_errors") + group.addoption("--doctest-encoding", + type=str.lower, default="utf-8", + help="choose the encoding to use for doctest files", + dest="doctestencoding") def pytest_collect_file(path, parent): @@ -171,7 +175,7 @@ class DoctestTextfile(pytest.Module): # inspired by doctest.testfile; ideally we would use it directly, # but it doesn't support passing a custom checker - text = self.fspath.read() + text = self.fspath.read_text(self.config.getoption("doctestencoding")) filename = str(self.fspath) name = self.fspath.basename globs = {'__name__': '__main__'} diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 5a1122515..93d7c30c4 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -11,6 +11,13 @@ can change the pattern by issuing:: on the command line. Since version ``2.9``, ``--doctest-glob`` can be given multiple times in the command-line. +You can specify the encoding that will be used for those doctest files +using the ``--doctest-encoding`` command line option:: + + pytest --doctest-encoding='ascii' + +The default encoding is UTF-8. + You can also trigger running of doctests from docstrings in all python modules (including regular python test modules):: @@ -52,9 +59,9 @@ then you can just invoke ``pytest`` without command line options:: platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini collected 1 items - + mymodule.py . - + ======= 1 passed in 0.12 seconds ======== It is possible to use fixtures using the ``getfixture`` helper:: From d254c6b0aeb872a791889d5e3497fa3ca679c482 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Tue, 29 Nov 2016 12:18:41 +0100 Subject: [PATCH 021/106] Added some tests for --docstring-encoding option. Added option to specify encoding for internal testdir._makefile() for the tests. --- _pytest/pytester.py | 4 ++-- testing/test_doctest.py | 46 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/_pytest/pytester.py b/_pytest/pytester.py index d19ff1ec6..37348c26e 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -471,7 +471,7 @@ class Testdir: if not hasattr(self, '_olddir'): self._olddir = old - def _makefile(self, ext, args, kwargs): + def _makefile(self, ext, args, kwargs, encoding="utf-8"): items = list(kwargs.items()) if args: source = py.builtin._totext("\n").join( @@ -490,7 +490,7 @@ class Testdir: source_unicode = "\n".join([my_totext(line) for line in source.lines]) source = py.builtin._totext(source_unicode) - content = source.strip().encode("utf-8") # + "\n" + content = source.strip().encode(encoding) # + "\n" #content = content.rstrip() + "\n" p.write(content, "wb") if ret is None: diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 4ea2cc58e..4ecd5744b 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -129,6 +129,52 @@ class TestDoctests: '*1 passed*', ]) + def test_encoding_ascii(self, testdir): + """Test support for --doctest-encoding option. + """ + testdir._makefile(".txt", [""" + >>> 1 + 1 + """], {}, encoding='ascii') + + result = testdir.runpytest("--doctest-encoding=ascii") + + result.stdout.fnmatch_lines([ + '*1 passed*', + ]) + + def test_encoding_latin1(self, testdir): + """Test support for --doctest-encoding option. + """ + testdir._makefile(".txt", [""" + >>> 'üäö' + 'üäö' + """], {}, encoding='latin1') + + result = testdir.runpytest("--doctest-encoding=latin1") + + result.stdout.fnmatch_lines([ + '*1 passed*', + ]) + + def test_encoding_utf8(self, testdir): + """Test support for --doctest-encoding option. + """ + testdir.maketxtfile(""" + >>> 'üäö' + 'üäö' + """) + + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + '*1 passed*', + ]) + + result = testdir.runpytest("--doctest-encoding=utf-8") + result.stdout.fnmatch_lines([ + '*1 passed*', + ]) + def test_doctest_unexpected_exception(self, testdir): testdir.maketxtfile(""" >>> i = 0 From 929912de2920fdf82a2b5303e9585803368234cd Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Tue, 29 Nov 2016 14:51:17 +0100 Subject: [PATCH 022/106] Changed the tests to pass on python 2 as well. --- testing/test_doctest.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 4ecd5744b..d48e58042 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -146,9 +146,9 @@ class TestDoctests: def test_encoding_latin1(self, testdir): """Test support for --doctest-encoding option. """ - testdir._makefile(".txt", [""" - >>> 'üäö' - 'üäö' + testdir._makefile(".txt", [u""" + >>> len(u'üäö') + 3 """], {}, encoding='latin1') result = testdir.runpytest("--doctest-encoding=latin1") @@ -160,9 +160,9 @@ class TestDoctests: def test_encoding_utf8(self, testdir): """Test support for --doctest-encoding option. """ - testdir.maketxtfile(""" - >>> 'üäö' - 'üäö' + testdir.maketxtfile(u""" + >>> len(u'üäö') + 3 """) result = testdir.runpytest() From c043bbb8545eecf991cda9bfab95b78bae9ecd08 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Wed, 30 Nov 2016 11:43:33 +0100 Subject: [PATCH 023/106] Changed the doctest_encoding option to an ini option. Parametrized the tests for it. --- _pytest/doctest.py | 9 +++---- testing/test_doctest.py | 57 ++++++++++++++--------------------------- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/_pytest/doctest.py b/_pytest/doctest.py index 05acc7c59..4ee21b12d 100644 --- a/_pytest/doctest.py +++ b/_pytest/doctest.py @@ -25,6 +25,7 @@ DOCTEST_REPORT_CHOICES = ( def pytest_addoption(parser): parser.addini('doctest_optionflags', 'option flags for doctests', type="args", default=["ELLIPSIS"]) + parser.addini("doctest_encoding", 'encoding used for doctest files', default="utf-8") group = parser.getgroup("collect") group.addoption("--doctest-modules", action="store_true", default=False, @@ -43,10 +44,6 @@ def pytest_addoption(parser): action="store_true", default=False, help="ignore doctest ImportErrors", dest="doctest_ignore_import_errors") - group.addoption("--doctest-encoding", - type=str.lower, default="utf-8", - help="choose the encoding to use for doctest files", - dest="doctestencoding") def pytest_collect_file(path, parent): @@ -166,7 +163,6 @@ def get_optionflags(parent): flag_acc |= flag_lookup_table[flag] return flag_acc - class DoctestTextfile(pytest.Module): obj = None @@ -175,7 +171,8 @@ class DoctestTextfile(pytest.Module): # inspired by doctest.testfile; ideally we would use it directly, # but it doesn't support passing a custom checker - text = self.fspath.read_text(self.config.getoption("doctestencoding")) + encoding = self.config.getini("doctest_encoding") + text = self.fspath.read_text(encoding) filename = str(self.fspath) name = self.fspath.basename globs = {'__name__': '__main__'} diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d48e58042..02f4c3b26 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -129,48 +129,29 @@ class TestDoctests: '*1 passed*', ]) - def test_encoding_ascii(self, testdir): - """Test support for --doctest-encoding option. + @pytest.mark.parametrize( + ' test_string, encoding', + [ + (u'foo', 'ascii'), + (u'öäü', 'latin1'), + (u'öäü', 'utf-8') + ] + ) + def test_encoding(self, testdir, test_string, encoding): + """Test support for doctest_encoding ini option. """ - testdir._makefile(".txt", [""" - >>> 1 - 1 - """], {}, encoding='ascii') - - result = testdir.runpytest("--doctest-encoding=ascii") - - result.stdout.fnmatch_lines([ - '*1 passed*', - ]) - - def test_encoding_latin1(self, testdir): - """Test support for --doctest-encoding option. - """ - testdir._makefile(".txt", [u""" - >>> len(u'üäö') - 3 - """], {}, encoding='latin1') - - result = testdir.runpytest("--doctest-encoding=latin1") - - result.stdout.fnmatch_lines([ - '*1 passed*', - ]) - - def test_encoding_utf8(self, testdir): - """Test support for --doctest-encoding option. - """ - testdir.maketxtfile(u""" - >>> len(u'üäö') - 3 - """) + testdir.makeini(""" + [pytest] + doctest_encoding={0} + """.format(encoding)) + doctest = u""" + >>> u"{}" + {} + """.format(test_string, repr(test_string)) + testdir._makefile(".txt", [doctest], {}, encoding=encoding) result = testdir.runpytest() - result.stdout.fnmatch_lines([ - '*1 passed*', - ]) - result = testdir.runpytest("--doctest-encoding=utf-8") result.stdout.fnmatch_lines([ '*1 passed*', ]) From 1f62e5b5a0fd0ec8ab13e409eb2cd5e198ec88a0 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Wed, 30 Nov 2016 11:50:11 +0100 Subject: [PATCH 024/106] Added CHANGELOG entry and myself to AUTHORS. --- AUTHORS | 1 + CHANGELOG.rst | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 8b07e8bf2..609eb3c77 100644 --- a/AUTHORS +++ b/AUTHORS @@ -86,6 +86,7 @@ Lukas Bednar Luke Murphy Maciek Fijalkowski Maho +Manuel Krebber Marc Schlaich Marcin Bachry Mark Abramowitz diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dd5c68123..baecaf80e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,7 +5,8 @@ New Features ------------ -* +* Added an ini option ``doctest_encoding`` to specify which encoding to use for doctest files. + Thanks `@wheerd`_ for the PR (`#2101`_). * @@ -21,10 +22,10 @@ Changes assertion messages if verbosity < 2 (`#1512`_). Thanks `@mattduck`_ for the PR -* ``--pdbcls`` no longer implies ``--pdb``. This makes it possible to use +* ``--pdbcls`` no longer implies ``--pdb``. This makes it possible to use ``addopts=--pdbcls=module.SomeClass`` on ``pytest.ini``. Thanks `@davidszotten`_ for the PR (`#1952`_). -* Change exception raised by ``capture.DontReadFromInput.fileno()`` from ``ValueError`` +* Change exception raised by ``capture.DontReadFromInput.fileno()`` from ``ValueError`` to ``io.UnsupportedOperation``. Thanks `@vlad-dragos`_ for the PR. @@ -34,11 +35,13 @@ Changes .. _@davidszotten: https://github.com/davidszotten .. _@fushi: https://github.com/fushi .. _@mattduck: https://github.com/mattduck +.. _@wheerd: https://github.com/wheerd .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 .. _#1952: https://github.com/pytest-dev/pytest/pull/1952 .. _#2013: https://github.com/pytest-dev/pytest/issues/2013 +.. _#2101: https://github.com/pytest-dev/pytest/pull/2101 3.0.5.dev0 From b7fb9fac91069d2d193b78265567f0d3c5673669 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Wed, 30 Nov 2016 14:17:54 +0100 Subject: [PATCH 025/106] Fixed the documentation for doctest_encoding. --- doc/en/doctest.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 93d7c30c4..5967ba047 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -12,9 +12,13 @@ on the command line. Since version ``2.9``, ``--doctest-glob`` can be given multiple times in the command-line. You can specify the encoding that will be used for those doctest files -using the ``--doctest-encoding`` command line option:: +using the ``doctest_encoding`` ini option: - pytest --doctest-encoding='ascii' +.. code-block:: ini + + # content of pytest.ini + [pytest] + doctest_encoding = latin1 The default encoding is UTF-8. From f8fef07b4c1399ff84b41a3fa4d28d93cc578fc4 Mon Sep 17 00:00:00 2001 From: Manuel Krebber Date: Wed, 30 Nov 2016 14:19:07 +0100 Subject: [PATCH 026/106] Fixed the tests for python 2.6 --- testing/test_doctest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 02f4c3b26..72ba0a622 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -145,8 +145,8 @@ class TestDoctests: doctest_encoding={0} """.format(encoding)) doctest = u""" - >>> u"{}" - {} + >>> u"{0}" + {1} """.format(test_string, repr(test_string)) testdir._makefile(".txt", [doctest], {}, encoding=encoding) From f5afd8cb541549aaf595dbd7ea730becf23e3ee3 Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Wed, 30 Nov 2016 12:17:51 +0100 Subject: [PATCH 027/106] Add missing `__test__` check for test discovery. --- CHANGELOG.rst | 6 ++++++ _pytest/compat.py | 2 +- _pytest/python.py | 2 ++ testing/test_collection.py | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dd5c68123..7239cd662 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,10 @@ New Features Changes ------- +* It is now possible to skip test classes from being collected by setting a + ``__test__`` attribute to ``False`` in the class body (`#2007`_). Thanks + to `@syre`_ for the report and `@lwm`_ for the PR. + * Testcase reports with a ``url`` attribute will now properly write this to junitxml. Thanks `@fushi`_ for the PR (`#1874`_). @@ -71,6 +75,7 @@ Changes * +.. _@syre: https://github.com/syre .. _@dupuy: https://bitbucket.org/dupuy/ .. _@lwm: https://github.com/lwm .. _@adler-j: https://github.com/adler-j @@ -83,6 +88,7 @@ Changes .. _#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 +.. _#2007: https://github.com/pytest-dev/pytest/issues/2007 3.0.4 diff --git a/_pytest/compat.py b/_pytest/compat.py index d5fa7aa84..6bed9e92a 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -200,7 +200,7 @@ def safe_getattr(object, name, default): """ Like getattr but return default upon any Exception. Attribute access can potentially fail for 'evil' Python objects. - See issue214 + See issue #214. """ try: return getattr(object, name, default) diff --git a/_pytest/python.py b/_pytest/python.py index 3f01d22ad..0936a6b68 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -503,6 +503,8 @@ def _get_xunit_func(obj, name): class Class(PyCollector): """ Collector for test methods. """ def collect(self): + if not safe_getattr(self.obj, "__test__", True): + return [] if hasinit(self.obj): self.warn("C1", "cannot collect test class %r because it has a " "__init__ constructor" % self.obj.__name__) diff --git a/testing/test_collection.py b/testing/test_collection.py index 9cf4de895..4e44874e1 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -85,6 +85,22 @@ class TestCollector: assert len(nodes) == 1 assert isinstance(nodes[0], pytest.File) + def test_can_skip_class_with_test_attr(self, testdir): + """Assure test class is skipped when using `__test__=False` (See #2007).""" + testdir.makepyfile(""" + class TestFoo(): + __test__ = False + def __init__(self): + pass + def test_foo(): + assert True + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + 'collected 0 items', + '*no tests ran in*', + ]) + class TestCollectFS: def test_ignored_certain_directories(self, testdir): tmpdir = testdir.tmpdir From 2edfc805afefbbabdeccdb9b4e9fd6ab89335008 Mon Sep 17 00:00:00 2001 From: Wheerd Date: Wed, 30 Nov 2016 18:01:00 +0100 Subject: [PATCH 028/106] Added "versionadded" for doctest_encoding ini option to docs. --- doc/en/doctest.rst | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 5967ba047..a82e3ed9b 100644 --- a/doc/en/doctest.rst +++ b/doc/en/doctest.rst @@ -11,16 +11,18 @@ can change the pattern by issuing:: on the command line. Since version ``2.9``, ``--doctest-glob`` can be given multiple times in the command-line. -You can specify the encoding that will be used for those doctest files -using the ``doctest_encoding`` ini option: +.. versionadded:: 3.1 -.. code-block:: ini + You can specify the encoding that will be used for those doctest files + using the ``doctest_encoding`` ini option: - # content of pytest.ini - [pytest] - doctest_encoding = latin1 + .. code-block:: ini -The default encoding is UTF-8. + # content of pytest.ini + [pytest] + doctest_encoding = latin1 + + The default encoding is UTF-8. You can also trigger running of doctests from docstrings in all python modules (including regular From f8d195253e1d7a63c7783585e5f4412908455322 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 30 Nov 2016 22:23:02 -0200 Subject: [PATCH 029/106] 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 030/106] 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 031/106] 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 032/106] 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 033/106] 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 034/106] 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 035/106] 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 036/106] 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 037/106] 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 038/106] 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 039/106] 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 040/106] 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 041/106] 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 042/106] 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 9c285dfc1d1c79f71a532e8618a8eb9b443f9df8 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 6 Dec 2016 09:13:25 +0100 Subject: [PATCH 043/106] fix #2118 - rework Node._getcustomclass and Node compat properties --- CHANGELOG.rst | 4 +++- _pytest/main.py | 47 ++++++++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d49214e3f..ff6efb7ef 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,9 @@ 3.0.6.dev0 ========== -* +* fix issue #2118 - protect against internal deprecationerrors by changing the code path of Node._getcustomclass. + This also turns a internal deprecation into a real deprecation. + Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. * diff --git a/_pytest/main.py b/_pytest/main.py index 52876c12a..905b35d83 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -3,6 +3,8 @@ import functools import os import sys +import warnings + import _pytest import _pytest._code import py @@ -190,14 +192,21 @@ class FSHookProxy: self.__dict__[name] = x return x -def compatproperty(name): - def fget(self): - import warnings - warnings.warn("This usage is deprecated, please use pytest.{0} instead".format(name), - PendingDeprecationWarning, stacklevel=2) - return getattr(pytest, name) +class _CompatProperty(object): + def __init__(self, name): + self.name = name + + def __get__(self, obj, owner): + if obj is None: + return self + + warnings.warn( + "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( + name=self.name, owner=type(owner).__name__), + PendingDeprecationWarning, stacklevel=2) + return getattr(pytest, self.name) + - return property(fget) class NodeKeywords(MappingMixin): def __init__(self, node): @@ -269,19 +278,23 @@ class Node(object): """ fspath sensitive hook proxy used to call pytest hooks""" return self.session.gethookproxy(self.fspath) - Module = compatproperty("Module") - Class = compatproperty("Class") - Instance = compatproperty("Instance") - Function = compatproperty("Function") - File = compatproperty("File") - Item = compatproperty("Item") + Module = _CompatProperty("Module") + Class = _CompatProperty("Class") + Instance = _CompatProperty("Instance") + Function = _CompatProperty("Function") + File = _CompatProperty("File") + Item = _CompatProperty("Item") def _getcustomclass(self, name): - cls = getattr(self, name) - if cls != getattr(pytest, name): - py.log._apiwarn("2.0", "use of node.%s is deprecated, " + maybe_compatprop = getattr(type(self), name) + if isinstance(maybe_compatprop, _CompatProperty): + return getattr(pytest, name) + else: + cls = getattr(self, name) + + warnings.warn("use of node.%s is deprecated, " "use pytest_pycollect_makeitem(...) to create custom " - "collection nodes" % name) + "collection nodes" % name, category=DeprecationWarning) return cls def __repr__(self): 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 044/106] 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 045/106] 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 046/106] 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 047/106] 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 048/106] 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 049/106] 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 050/106] 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 051/106] 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 052/106] 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 053/106] 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 054/106] 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 055/106] 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 056/106] 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 057/106] 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 058/106] 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 059/106] 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) ================== From 03a7a2cd3ed855a8ee0af260aba236818bbcacaf Mon Sep 17 00:00:00 2001 From: Jakub Wilk Date: Sat, 31 Dec 2016 18:54:47 +0100 Subject: [PATCH 060/106] Fix typos --- CHANGELOG.rst | 50 ++++++++++++++--------------- doc/en/announce/release-2.0.2.rst | 4 +-- doc/en/announce/release-2.0.3.rst | 4 +-- doc/en/announce/release-2.2.1.rst | 2 +- doc/en/announce/release-2.2.4.rst | 2 +- doc/en/announce/release-2.3.0.rst | 4 +-- doc/en/announce/release-2.3.2.rst | 2 +- doc/en/announce/release-2.3.3.rst | 6 ++-- doc/en/announce/release-2.3.5.rst | 8 ++--- doc/en/announce/release-2.4.0.rst | 4 +-- doc/en/announce/release-2.5.0.rst | 4 +-- doc/en/announce/release-2.5.2.rst | 2 +- doc/en/announce/release-2.6.3.rst | 2 +- doc/en/announce/release-2.7.1.rst | 2 +- doc/en/announce/release-2.9.2.rst | 2 +- doc/en/cache.rst | 2 +- doc/en/conf.py | 2 +- doc/en/example/markers.rst | 4 +-- doc/en/example/pythoncollection.rst | 2 +- doc/en/example/simple.rst | 6 ++-- doc/en/funcarg_compare.rst | 2 +- doc/en/monkeypatch.rst | 4 +-- doc/en/projects.rst | 2 +- doc/en/skipping.rst | 2 +- doc/en/test/plugin/xdist.rst | 2 +- doc/en/usage.rst | 4 +-- doc/en/writing_plugins.rst | 4 +-- 27 files changed, 67 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9d0b80ecf..7c3df0327 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -690,7 +690,7 @@ time or change existing behaviors in order to make them less surprising/more use Thanks `@astraw38`_ for reporting the issue (`#1496`_) and `@tomviner`_ for PR the (`#1524`_). -* Fix win32 path issue when puttinging custom config file with absolute path +* Fix win32 path issue when putting custom config file with absolute path in ``pytest.main("-c your_absolute_path")``. * Fix maximum recursion depth detection when raised error class is not aware @@ -1022,7 +1022,7 @@ time or change existing behaviors in order to make them less surprising/more use - (experimental) adapt more SEMVER style versioning and change meaning of master branch in git repo: "master" branch now keeps the bugfixes, changes - aimed for micro releases. "features" branch will only be be released + aimed for micro releases. "features" branch will only be released with minor or major pytest releases. - Fix issue #766 by removing documentation references to distutils. @@ -1156,7 +1156,7 @@ time or change existing behaviors in order to make them less surprising/more use - new option ``--import-mode`` to allow to change test module importing behaviour to append to sys.path instead of prepending. This better allows - to run test modules against installated versions of a package even if the + to run test modules against installed versions of a package even if the package under test has the same import root. In this example:: testing/__init__.py @@ -1314,7 +1314,7 @@ time or change existing behaviors in order to make them less surprising/more use explanations. Thanks Carl Meyer for the report and test case. - fix issue553: properly handling inspect.getsourcelines failures in - FixtureLookupError which would lead to to an internal error, + FixtureLookupError which would lead to an internal error, obfuscating the original problem. Thanks talljosh for initial diagnose/patch and Bruno Oliveira for final patch. @@ -1457,7 +1457,7 @@ time or change existing behaviors in order to make them less surprising/more use - fix conftest related fixture visibility issue: when running with a CWD outside of a test package pytest would get fixture discovery wrong. - Thanks to Wolfgang Schnerring for figuring out a reproducable example. + Thanks to Wolfgang Schnerring for figuring out a reproducible example. - Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the timeout when interactively entering pdb). Thanks Wolfgang Schnerring. @@ -1656,7 +1656,7 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue429: comparing byte strings with non-ascii chars in assert expressions now work better. Thanks Floris Bruynooghe. -- make capfd/capsys.capture private, its unused and shouldnt be exposed +- make capfd/capsys.capture private, its unused and shouldn't be exposed 2.5.1 (2013-12-17) @@ -1713,7 +1713,7 @@ time or change existing behaviors in order to make them less surprising/more use to problems for more than >966 non-function scoped parameters). - fix issue290 - there is preliminary support now for parametrizing - with repeated same values (sometimes useful to to test if calling + with repeated same values (sometimes useful to test if calling a second time works as with the first time). - close issue240 - document precisely how pytest module importing @@ -1927,7 +1927,7 @@ new features: - fix issue322: tearDownClass is not run if setUpClass failed. Thanks Mathieu Agopian for the initial fix. Also make all of pytest/nose - finalizer mimick the same generic behaviour: if a setupX exists and + finalizer mimic the same generic behaviour: if a setupX exists and fails, don't run teardownX. This internally introduces a new method "node.addfinalizer()" helper which can only be called during the setup phase of a node. @@ -2046,11 +2046,11 @@ Bug fixes: (thanks Adam Goucher) - Issue 265 - integrate nose setup/teardown with setupstate - so it doesnt try to teardown if it did not setup + so it doesn't try to teardown if it did not setup -- issue 271 - dont write junitxml on slave nodes +- issue 271 - don't write junitxml on slave nodes -- Issue 274 - dont try to show full doctest example +- Issue 274 - don't try to show full doctest example when doctest does not know the example location - issue 280 - disable assertion rewriting on buggy CPython 2.6.0 @@ -2086,7 +2086,7 @@ Bug fixes: - allow to specify prefixes starting with "_" when customizing python_functions test discovery. (thanks Graham Horler) -- improve PYTEST_DEBUG tracing output by puting +- improve PYTEST_DEBUG tracing output by putting extra data on a new lines with additional indent - ensure OutcomeExceptions like skip/fail have initialized exception attributes @@ -2135,7 +2135,7 @@ Bug fixes: - fix issue209 - reintroduce python2.4 support by depending on newer pylib which re-introduced statement-finding for pre-AST interpreters -- nose support: only call setup if its a callable, thanks Andrew +- nose support: only call setup if it's a callable, thanks Andrew Taumoefolau - fix issue219 - add py2.4-3.3 classifiers to TROVE list @@ -2231,7 +2231,7 @@ Bug fixes: - fix issue128: show captured output when capsys/capfd are used -- fix issue179: propperly show the dependency chain of factories +- fix issue179: properly show the dependency chain of factories - pluginmanager.register(...) now raises ValueError if the plugin has been already registered or the name is taken @@ -2272,7 +2272,7 @@ Bug fixes: - don't show deselected reason line if there is none - - py.test -vv will show all of assert comparisations instead of truncating + - py.test -vv will show all of assert comparisons instead of truncating 2.2.4 (2012-05-22) ================== @@ -2283,7 +2283,7 @@ Bug fixes: - fix issue with unittest: now @unittest.expectedFailure markers should be processed correctly (you can also use @pytest.mark markers) - document integration with the extended distribute/setuptools test commands -- fix issue 140: propperly get the real functions +- fix issue 140: properly get the real functions of bound classmethods for setup/teardown_class - fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net - fix issue #143: call unconfigure/sessionfinish always when @@ -2294,7 +2294,7 @@ Bug fixes: 2.2.3 (2012-02-05) ================== -- fix uploaded package to only include neccesary files +- fix uploaded package to only include necessary files 2.2.2 (2012-02-05) ================== @@ -2435,7 +2435,7 @@ Bug fixes: - don't require zlib (and other libs) for genscript plugin without --genscript actually being used. -- speed up skips (by not doing a full traceback represenation +- speed up skips (by not doing a full traceback representation internally) - fix issue37: avoid invalid characters in junitxml's output @@ -2483,9 +2483,9 @@ Bug fixes: this. - fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular - thanks to Laura Creighton who also revieved parts of the documentation. + thanks to Laura Creighton who also reviewed parts of the documentation. -- fix slighly wrong output of verbose progress reporting for classes +- fix slightly wrong output of verbose progress reporting for classes (thanks Amaury) - more precise (avoiding of) deprecation warnings for node.Class|Function accesses @@ -2546,7 +2546,7 @@ Bug fixes: - pytest-2.0 is now its own package and depends on pylib-2.0 - new ability: python -m pytest / python -m pytest.main ability -- new python invcation: pytest.main(args, plugins) to load +- new python invocation: pytest.main(args, plugins) to load some custom plugins early. - try harder to run unittest test suites in a more compatible manner by deferring setup/teardown semantics to the unittest package. @@ -2785,7 +2785,7 @@ Bug fixes: - extend and refine xfail mechanism: ``@py.test.mark.xfail(run=False)`` do not run the decorated test ``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries - specifiying ``--runxfail`` on command line virtually ignores xfail markers + specifying ``--runxfail`` on command line virtually ignores xfail markers - expose (previously internal) commonly useful methods: py.io.get_terminal_with() -> return terminal width @@ -3010,7 +3010,7 @@ Bug fixes: * add the ability to specify a path for py.lookup to search in -* fix a funcarg cached_setup bug probably only occuring +* fix a funcarg cached_setup bug probably only occurring in distributed testing and "module" scope with teardown. * many fixes and changes for making the code base python3 compatible, @@ -3276,10 +3276,10 @@ serve as a reference for developers. * fixed issue with 2.5 type representations in py.test [45483, 45484] * made that internal reporting issues displaying is done atomically in py.test [45518] -* made that non-existing files are igored by the py.lookup script [45519] +* made that non-existing files are ignored by the py.lookup script [45519] * improved exception name creation in py.test [45535] * made that less threads are used in execnet [merge in 45539] -* removed lock required for atomical reporting issue displaying in py.test +* removed lock required for atomic reporting issue displaying in py.test [45545] * removed globals from execnet [45541, 45547] * refactored cleanup mechanics, made that setDaemon is set to 1 to make atexit diff --git a/doc/en/announce/release-2.0.2.rst b/doc/en/announce/release-2.0.2.rst index 733a9f7bd..f1f44f34f 100644 --- a/doc/en/announce/release-2.0.2.rst +++ b/doc/en/announce/release-2.0.2.rst @@ -63,9 +63,9 @@ Changes between 2.0.1 and 2.0.2 this. - fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular - thanks to Laura Creighton who also revieved parts of the documentation. + thanks to Laura Creighton who also reviewed parts of the documentation. -- fix slighly wrong output of verbose progress reporting for classes +- fix slightly wrong output of verbose progress reporting for classes (thanks Amaury) - more precise (avoiding of) deprecation warnings for node.Class|Function accesses diff --git a/doc/en/announce/release-2.0.3.rst b/doc/en/announce/release-2.0.3.rst index ed746e851..9bbfdaab3 100644 --- a/doc/en/announce/release-2.0.3.rst +++ b/doc/en/announce/release-2.0.3.rst @@ -13,7 +13,7 @@ If you want to install or upgrade pytest, just type one of:: easy_install -U pytest There also is a bugfix release 1.6 of pytest-xdist, the plugin -that enables seemless distributed and "looponfail" testing for Python. +that enables seamless distributed and "looponfail" testing for Python. best, holger krekel @@ -33,7 +33,7 @@ Changes between 2.0.2 and 2.0.3 - don't require zlib (and other libs) for genscript plugin without --genscript actually being used. -- speed up skips (by not doing a full traceback represenation +- speed up skips (by not doing a full traceback representation internally) - fix issue37: avoid invalid characters in junitxml's output diff --git a/doc/en/announce/release-2.2.1.rst b/doc/en/announce/release-2.2.1.rst index f9764634c..5d28bcb01 100644 --- a/doc/en/announce/release-2.2.1.rst +++ b/doc/en/announce/release-2.2.1.rst @@ -2,7 +2,7 @@ pytest-2.2.1: bug fixes, perfect teardowns =========================================================================== -pytest-2.2.1 is a minor backward-compatible release of the the py.test +pytest-2.2.1 is a minor backward-compatible release of the py.test testing tool. It contains bug fixes and little improvements, including documentation fixes. If you are using the distributed testing pluginmake sure to upgrade it to pytest-xdist-1.8. diff --git a/doc/en/announce/release-2.2.4.rst b/doc/en/announce/release-2.2.4.rst index 8720bdb28..67f0feb27 100644 --- a/doc/en/announce/release-2.2.4.rst +++ b/doc/en/announce/release-2.2.4.rst @@ -29,7 +29,7 @@ Changes between 2.2.3 and 2.2.4 - fix issue with unittest: now @unittest.expectedFailure markers should be processed correctly (you can also use @pytest.mark markers) - document integration with the extended distribute/setuptools test commands -- fix issue 140: propperly get the real functions +- fix issue 140: properly get the real functions of bound classmethods for setup/teardown_class - fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net - fix issue #143: call unconfigure/sessionfinish always when diff --git a/doc/en/announce/release-2.3.0.rst b/doc/en/announce/release-2.3.0.rst index 54fe3961f..f863aad0a 100644 --- a/doc/en/announce/release-2.3.0.rst +++ b/doc/en/announce/release-2.3.0.rst @@ -89,7 +89,7 @@ Changes between 2.2.4 and 2.3.0 - fix issue128: show captured output when capsys/capfd are used -- fix issue179: propperly show the dependency chain of factories +- fix issue179: properly show the dependency chain of factories - pluginmanager.register(...) now raises ValueError if the plugin has been already registered or the name is taken @@ -130,5 +130,5 @@ Changes between 2.2.4 and 2.3.0 - don't show deselected reason line if there is none - - py.test -vv will show all of assert comparisations instead of truncating + - py.test -vv will show all of assert comparisons instead of truncating diff --git a/doc/en/announce/release-2.3.2.rst b/doc/en/announce/release-2.3.2.rst index 948b374d4..75312b429 100644 --- a/doc/en/announce/release-2.3.2.rst +++ b/doc/en/announce/release-2.3.2.rst @@ -1,7 +1,7 @@ pytest-2.3.2: some fixes and more traceback-printing speed =========================================================================== -pytest-2.3.2 is a another stabilization release: +pytest-2.3.2 is another stabilization release: - issue 205: fixes a regression with conftest detection - issue 208/29: fixes traceback-printing speed in some bad cases diff --git a/doc/en/announce/release-2.3.3.rst b/doc/en/announce/release-2.3.3.rst index 1d7c7027b..3a48b6ac4 100644 --- a/doc/en/announce/release-2.3.3.rst +++ b/doc/en/announce/release-2.3.3.rst @@ -1,7 +1,7 @@ -pytest-2.3.3: integration fixes, py24 suport, ``*/**`` shown in traceback +pytest-2.3.3: integration fixes, py24 support, ``*/**`` shown in traceback =========================================================================== -pytest-2.3.3 is a another stabilization release of the py.test tool +pytest-2.3.3 is another stabilization release of the py.test tool which offers uebersimple assertions, scalable fixture mechanisms and deep customization for testing with Python. Particularly, this release provides: @@ -46,7 +46,7 @@ Changes between 2.3.2 and 2.3.3 - fix issue209 - reintroduce python2.4 support by depending on newer pylib which re-introduced statement-finding for pre-AST interpreters -- nose support: only call setup if its a callable, thanks Andrew +- nose support: only call setup if it's a callable, thanks Andrew Taumoefolau - fix issue219 - add py2.4-3.3 classifiers to TROVE list diff --git a/doc/en/announce/release-2.3.5.rst b/doc/en/announce/release-2.3.5.rst index c4e91e0e6..112399ef3 100644 --- a/doc/en/announce/release-2.3.5.rst +++ b/doc/en/announce/release-2.3.5.rst @@ -44,11 +44,11 @@ Changes between 2.3.4 and 2.3.5 (thanks Adam Goucher) - Issue 265 - integrate nose setup/teardown with setupstate - so it doesnt try to teardown if it did not setup + so it doesn't try to teardown if it did not setup -- issue 271 - dont write junitxml on slave nodes +- issue 271 - don't write junitxml on slave nodes -- Issue 274 - dont try to show full doctest example +- Issue 274 - don't try to show full doctest example when doctest does not know the example location - issue 280 - disable assertion rewriting on buggy CPython 2.6.0 @@ -84,7 +84,7 @@ Changes between 2.3.4 and 2.3.5 - allow to specify prefixes starting with "_" when customizing python_functions test discovery. (thanks Graham Horler) -- improve PYTEST_DEBUG tracing output by puting +- improve PYTEST_DEBUG tracing output by putting extra data on a new lines with additional indent - ensure OutcomeExceptions like skip/fail have initialized exception attributes diff --git a/doc/en/announce/release-2.4.0.rst b/doc/en/announce/release-2.4.0.rst index 88130c481..be3aaedb0 100644 --- a/doc/en/announce/release-2.4.0.rst +++ b/doc/en/announce/release-2.4.0.rst @@ -36,7 +36,7 @@ a full list of details. A few feature highlights: - reporting: color the last line red or green depending if failures/errors occurred or everything passed. -The documentation has been updated to accomodate the changes, +The documentation has been updated to accommodate the changes, see `http://pytest.org `_ To install or upgrade pytest:: @@ -118,7 +118,7 @@ new features: - fix issue322: tearDownClass is not run if setUpClass failed. Thanks Mathieu Agopian for the initial fix. Also make all of pytest/nose - finalizer mimick the same generic behaviour: if a setupX exists and + finalizer mimic the same generic behaviour: if a setupX exists and fails, don't run teardownX. This internally introduces a new method "node.addfinalizer()" helper which can only be called during the setup phase of a node. diff --git a/doc/en/announce/release-2.5.0.rst b/doc/en/announce/release-2.5.0.rst index b8f28d6fd..b04a825cd 100644 --- a/doc/en/announce/release-2.5.0.rst +++ b/doc/en/announce/release-2.5.0.rst @@ -70,7 +70,7 @@ holger krekel to problems for more than >966 non-function scoped parameters). - fix issue290 - there is preliminary support now for parametrizing - with repeated same values (sometimes useful to to test if calling + with repeated same values (sometimes useful to test if calling a second time works as with the first time). - close issue240 - document precisely how pytest module importing @@ -149,7 +149,7 @@ holger krekel would not work correctly because pytest assumes @pytest.mark.some gets a function to be decorated already. We now at least detect if this - arg is an lambda and thus the example will work. Thanks Alex Gaynor + arg is a lambda and thus the example will work. Thanks Alex Gaynor for bringing it up. - xfail a test on pypy that checks wrong encoding/ascii (pypy does diff --git a/doc/en/announce/release-2.5.2.rst b/doc/en/announce/release-2.5.2.rst index 9308ffdd6..d5cfca2db 100644 --- a/doc/en/announce/release-2.5.2.rst +++ b/doc/en/announce/release-2.5.2.rst @@ -60,5 +60,5 @@ holger krekel - fix issue429: comparing byte strings with non-ascii chars in assert expressions now work better. Thanks Floris Bruynooghe. -- make capfd/capsys.capture private, its unused and shouldnt be exposed +- make capfd/capsys.capture private, its unused and shouldn't be exposed diff --git a/doc/en/announce/release-2.6.3.rst b/doc/en/announce/release-2.6.3.rst index c1d0ad278..ee0d2692c 100644 --- a/doc/en/announce/release-2.6.3.rst +++ b/doc/en/announce/release-2.6.3.rst @@ -42,7 +42,7 @@ Changes 2.6.3 - fix conftest related fixture visibility issue: when running with a CWD outside of a test package pytest would get fixture discovery wrong. - Thanks to Wolfgang Schnerring for figuring out a reproducable example. + Thanks to Wolfgang Schnerring for figuring out a reproducible example. - Introduce pytest_enter_pdb hook (needed e.g. by pytest_timeout to cancel the timeout when interactively entering pdb). Thanks Wolfgang Schnerring. diff --git a/doc/en/announce/release-2.7.1.rst b/doc/en/announce/release-2.7.1.rst index cd37cad0c..fdc71eebb 100644 --- a/doc/en/announce/release-2.7.1.rst +++ b/doc/en/announce/release-2.7.1.rst @@ -32,7 +32,7 @@ The py.test Development Team explanations. Thanks Carl Meyer for the report and test case. - fix issue553: properly handling inspect.getsourcelines failures in - FixtureLookupError which would lead to to an internal error, + FixtureLookupError which would lead to an internal error, obfuscating the original problem. Thanks talljosh for initial diagnose/patch and Bruno Oliveira for final patch. diff --git a/doc/en/announce/release-2.9.2.rst b/doc/en/announce/release-2.9.2.rst index b71ae85dd..8f274cdf3 100644 --- a/doc/en/announce/release-2.9.2.rst +++ b/doc/en/announce/release-2.9.2.rst @@ -46,7 +46,7 @@ The py.test Development Team Thanks `@astraw38`_ for reporting the issue (`#1496`_) and `@tomviner`_ for PR the (`#1524`_). -* Fix win32 path issue when puttinging custom config file with absolute path +* Fix win32 path issue when putting custom config file with absolute path in ``pytest.main("-c your_absolute_path")``. * Fix maximum recursion depth detection when raised error class is not aware diff --git a/doc/en/cache.rst b/doc/en/cache.rst index dc1f91286..b1a7b3796 100644 --- a/doc/en/cache.rst +++ b/doc/en/cache.rst @@ -246,7 +246,7 @@ by adding the ``--cache-clear`` option like this:: pytest --cache-clear -This is recommended for invocations from Continous Integration +This is recommended for invocations from Continuous Integration servers where isolation and correctness is more important than speed. diff --git a/doc/en/conf.py b/doc/en/conf.py index f3b8d7d1e..40f1e4165 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -303,7 +303,7 @@ texinfo_documents = [ ('Holger Krekel@*Benjamin Peterson@*Ronny Pfannschmidt@*' 'Floris Bruynooghe@*others'), 'pytest', - 'simple powerful testing with Pytho', + 'simple powerful testing with Python', 'Programming', 1), ] diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 7e48e6f2e..99b09fa57 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -205,7 +205,7 @@ You can ask which markers exist for your test suite - the list includes our just @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. @@ -381,7 +381,7 @@ The ``--markers`` option always gives you a list of available markers:: @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 3fa8834bd..7dc531100 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -95,7 +95,7 @@ the :confval:`python_files`, :confval:`python_classes` and :confval:`python_functions` configuration options. Example:: # content of pytest.ini - # can also be defined in in tox.ini or setup.cfg file, although the section + # can also be defined in tox.ini or setup.cfg file, although the section # name in setup.cfg files should be "tool:pytest" [pytest] python_files=check_*.py diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 3dd6fe92e..623ff33cc 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -476,7 +476,7 @@ concept. It's however recommended to have explicit fixture references in your tests or test classes rather than relying on implicitly executing setup/teardown functions, especially if they are far away from the actual tests. -Here is a an example for making a ``db`` fixture available in a directory: +Here is an example for making a ``db`` fixture available in a directory: .. code-block:: python @@ -585,7 +585,7 @@ environment you can implement a hook that gets called when the test "report" object is about to be created. Here we write out all failing test calls and also access a fixture (if it was used by the test) in case you want to query/look at it during your post processing. In our -case we just write some informations out to a ``failures`` file: +case we just write some information out to a ``failures`` file: .. code-block:: python @@ -678,7 +678,7 @@ here is a little example implemented via a local plugin: outcome = yield rep = outcome.get_result() - # set an report attribute for each phase of a call, which can + # set a report attribute for each phase of a call, which can # be "setup", "call", "teardown" setattr(item, "rep_" + rep.when, rep) diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 88a34215f..3d121b944 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -97,7 +97,7 @@ sets. pytest-2.3 introduces a decorator for use on the factory itself:: ... # use request.param Here the factory will be invoked twice (with the respective "mysql" -and "pg" values set as ``request.param`` attributes) and and all of +and "pg" values set as ``request.param`` attributes) and all of the tests requiring "db" will run twice as well. The "mysql" and "pg" values will also be used for reporting the test-invocation variants. diff --git a/doc/en/monkeypatch.rst b/doc/en/monkeypatch.rst index 806e910bd..0c07b2f44 100644 --- a/doc/en/monkeypatch.rst +++ b/doc/en/monkeypatch.rst @@ -35,7 +35,7 @@ patch this function before calling into a function which uses it:: assert x == '/abc/.ssh' Here our test function monkeypatches ``os.path.expanduser`` and -then calls into an function that calls it. After the test function +then calls into a function that calls it. After the test function finishes the ``os.path.expanduser`` modification will be undone. example: preventing "requests" from remote operations @@ -60,7 +60,7 @@ so that any attempts within tests to create http requests will fail. Be advised that it is not recommended to patch builtin functions such as ``open``, ``compile``, etc., because it might break pytest's internals. If that's unavoidable, passing ``--tb=native``, ``--assert=plain`` and ``--capture=no`` might - help althought there's no guarantee. + help although there's no guarantee. Method reference of the monkeypatch fixture diff --git a/doc/en/projects.rst b/doc/en/projects.rst index fa7a2f29a..a2edbf68f 100644 --- a/doc/en/projects.rst +++ b/doc/en/projects.rst @@ -58,7 +58,7 @@ Here are some examples of projects using ``pytest`` (please send notes via :ref: * `katcp `_ Telescope communication protocol over Twisted * `kss plugin timer `_ * `pyudev `_ a pure Python binding to the Linux library libudev -* `pytest-localserver `_ a plugin for pytest that provides a httpserver and smtpserver +* `pytest-localserver `_ a plugin for pytest that provides an httpserver and smtpserver * `pytest-monkeyplus `_ a plugin that extends monkeypatch These projects help integrate ``pytest`` into other Python frameworks: diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index afa33444e..b142738c9 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -2,7 +2,7 @@ .. _skipping: -Skip and xfail: dealing with tests that can not succeed +Skip and xfail: dealing with tests that cannot succeed ===================================================================== If you have test functions that cannot be run on certain platforms diff --git a/doc/en/test/plugin/xdist.rst b/doc/en/test/plugin/xdist.rst index 79440998b..506d240ae 100644 --- a/doc/en/test/plugin/xdist.rst +++ b/doc/en/test/plugin/xdist.rst @@ -71,7 +71,7 @@ you can ad-hoc distribute your tests by typing:: pytest -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg This will synchronize your ``mypkg`` package directory -to an remote ssh account and then locally collect tests +to a remote ssh account and then locally collect tests and send them to remote places for execution. You can specify multiple ``--rsyncdir`` directories diff --git a/doc/en/usage.rst b/doc/en/usage.rst index 4f01081ce..15b3d71b0 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -49,7 +49,7 @@ Several test run options:: # will select TestMyClass.test_something # but not TestMyClass.test_method_simple pytest test_mod.py::test_func # only run tests that match the "node ID", - # e.g "test_mod.py::test_func" will select + # e.g. "test_mod.py::test_func" will select # only test_func in test_mod.py pytest test_mod.py::TestClass::test_method # run a single method in # a single class @@ -76,7 +76,7 @@ Examples for modifying traceback printing:: The ``--full-trace`` causes very long traces to be printed on error (longer than ``--tb=long``). It also ensures that a stack trace is printed on -**KeyboardInterrrupt** (Ctrl+C). +**KeyboardInterrupt** (Ctrl+C). This is very useful if the tests are taking too long and you interrupt them with Ctrl+C to find out where the tests are *hanging*. By default no output will be shown (because KeyboardInterrupt is caught by pytest). By using this diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index 8a46648cd..b4ff7f8eb 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -250,8 +250,8 @@ which will import the specified module as a ``pytest`` plugin. Plugins imported like this will automatically be marked to require assertion rewriting using the :func:`pytest.register_assert_rewrite` mechanism. However for this to have any effect the module must not be -imported already, it it was already imported at the time the -``pytest_plugins`` statement is processed a warning will result and +imported already; if it was already imported at the time the +``pytest_plugins`` statement is processed, a warning will result and assertions inside the plugin will not be re-written. To fix this you can either call :func:`pytest.register_assert_rewrite` yourself before the module is imported, or you can arrange the code to delay the From a9193a15310138981b2b56f7db69c1c2a6471ea1 Mon Sep 17 00:00:00 2001 From: Rafael Bertoldi Date: Fri, 30 Dec 2016 15:37:09 -0200 Subject: [PATCH 061/106] No longer silently ignore errors in parametrize callable ids --- CHANGELOG.rst | 3 ++ _pytest/python.py | 11 ++++++-- testing/python/metafunc.py | 58 ++++++++++++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0efd9c92e..aab0ae6e3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ New Features * Added an ini option ``doctest_encoding`` to specify which encoding to use for doctest files. Thanks `@wheerd`_ for the PR (`#2101`_). +* pytest now warns when a callable ids raises in a parametrized test. Thanks `@fogo`_ for the PR. + * @@ -39,6 +41,7 @@ Changes .. _@fushi: https://github.com/fushi .. _@mattduck: https://github.com/mattduck .. _@wheerd: https://github.com/wheerd +.. _@fogo: https://github.com/fogo .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 diff --git a/_pytest/python.py b/_pytest/python.py index 205ca472f..fee68251d 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -928,12 +928,17 @@ def _find_parametrized_scope(argnames, arg2fixturedefs, indirect): def _idval(val, argname, idx, idfn, config=None): if idfn: + s = None try: s = idfn(val) - if s: - return _escape_strings(s) except Exception: - pass + # See issue https://github.com/pytest-dev/pytest/issues/2169 + import warnings + msg = "Raised while trying to determine id of parameter %s at position %d." % (argname, idx) + msg += '\nUpdate your code as this will raise an error in pytest-4.0.' + warnings.warn(msg) + if s: + return _escape_strings(s) if config: hook_id = config.hook.pytest_make_parametrize_id(config=config, val=val) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index a7e1d5699..e88107d0b 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -296,18 +296,58 @@ class TestMetafunc: @pytest.mark.issue351 def test_idmaker_idfn_exception(self): from _pytest.python import idmaker + from _pytest.recwarn import WarningsRecorder + + class BadIdsException(Exception): + pass def ids(val): - raise Exception("bad code") + raise BadIdsException("ids raised") - result = idmaker(("a", "b"), [(10.0, IndexError()), - (20, KeyError()), - ("three", [1, 2, 3]), - ], idfn=ids) - assert result == ["10.0-b0", - "20-b1", - "three-b2", - ] + rec = WarningsRecorder() + with rec: + idmaker(("a", "b"), [(10.0, IndexError()), + (20, KeyError()), + ("three", [1, 2, 3]), + ], idfn=ids) + + assert [str(i.message) for i in rec.list] == [ + "Raised while trying to determine id of parameter a at position 0." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 0." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter a at position 1." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 1." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter a at position 2." + "\nUpdate your code as this will raise an error in pytest-4.0.", + "Raised while trying to determine id of parameter b at position 2." + "\nUpdate your code as this will raise an error in pytest-4.0.", + ] + + + def test_parametrize_ids_exception(self, testdir): + """ + :param testdir: the instance of Testdir class, a temporary + test directory. + """ + testdir.makepyfile(""" + import pytest + + def ids(arg): + raise Exception("bad ids") + + @pytest.mark.parametrize("arg", ["a", "b"], ids=ids) + def test_foo(arg): + pass + """) + result = testdir.runpytest("--collect-only") + result.stdout.fnmatch_lines([ + "", + " ", + " ", + ]) def test_idmaker_with_ids(self): from _pytest.python import idmaker From ef903460b1670a59db54cc47976a79b059062252 Mon Sep 17 00:00:00 2001 From: Peter Heatwole Date: Mon, 2 Jan 2017 14:07:41 -0800 Subject: [PATCH 062/106] Fix broken links --- doc/en/fixture.rst | 2 +- doc/en/goodpractices.rst | 2 +- doc/en/writing_plugins.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 9bc4f6084..201ad4863 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -11,7 +11,7 @@ pytest fixtures: explicit, modular, scalable .. _`xUnit`: http://en.wikipedia.org/wiki/XUnit .. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software -.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection#Definition +.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection The `purpose of test fixtures`_ is to provide a fixed baseline upon which tests can reliably and repeatedly execute. pytest fixtures diff --git a/doc/en/goodpractices.rst b/doc/en/goodpractices.rst index 43b15a077..48f80a9e2 100644 --- a/doc/en/goodpractices.rst +++ b/doc/en/goodpractices.rst @@ -147,7 +147,7 @@ dependencies are isolated from the system Python installation. If you frequently release code and want to make sure that your actual package passes all tests you may want to look into `tox`_, the virtualenv test automation tool and its `pytest support -`_. +`_. Tox helps you to setup virtualenv environments with pre-defined dependencies and then executing a pre-configured test command with options. It will run tests against the installed package and not diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index b4ff7f8eb..770f81e46 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -172,7 +172,7 @@ If a package is installed this way, ``pytest`` will load .. note:: Make sure to include ``Framework :: Pytest`` in your list of - `PyPI classifiers `_ + `PyPI classifiers `_ to make it easy for users to find your plugin. From 6fd0394c6317dc8acf2d1c58e2bad2379703214a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Tue, 20 Dec 2016 14:57:48 +0100 Subject: [PATCH 063/106] pytest.warns checks for subclass relationship rather than class equality. This makes it more similar to pytest.raises. --- CHANGELOG.rst | 9 +++++++-- _pytest/recwarn.py | 3 ++- testing/test_recwarn.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index aab0ae6e3..d0339aaed 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,7 +10,8 @@ New Features * pytest now warns when a callable ids raises in a parametrized test. Thanks `@fogo`_ for the PR. -* +* ``pytest.warns`` now checks for subclass relationship rather than + class equality. Thanks `@lesteve`_ for the PR (`#2166`_) Changes @@ -41,7 +42,11 @@ Changes .. _@fushi: https://github.com/fushi .. _@mattduck: https://github.com/mattduck .. _@wheerd: https://github.com/wheerd +<<<<<<< HEAD .. _@fogo: https://github.com/fogo +======= +.. _@lesteve: https://github.com/lesteve +>>>>>>> pytest.warns checks for subclass relationship .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 @@ -49,7 +54,7 @@ Changes .. _#2007: https://github.com/pytest-dev/pytest/issues/2007 .. _#2013: https://github.com/pytest-dev/pytest/issues/2013 .. _#2101: https://github.com/pytest-dev/pytest/pull/2101 - +.. _#2166: https://github.com/pytest-dev/pytest/pull/2166 3.0.6.dev0 (unreleased) ======================= diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index 342169693..4fd41fa8a 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -216,7 +216,8 @@ class WarningsChecker(WarningsRecorder): # only check if we're not currently handling an exception if all(a is None for a in exc_info): if self.expected_warning is not None: - if not any(r.category in self.expected_warning for r in self): + if not any(issubclass(r.category, exp_warning) for + exp_warning in self.expected_warning for r in self): __tracebackhide__ = True pytest.fail("DID NOT WARN. No warnings of type {0} was emitted. " "The list of emitted warnings is: {1}.".format( diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 6c4d73ff7..ef2ebd74c 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -238,6 +238,16 @@ class TestWarns(object): assert str(record[0].message) == "user" assert str(record[1].message) == "runtime" + def test_record_by_subclass(self): + with pytest.warns(Warning) as record: + warnings.warn("user", UserWarning) + warnings.warn("runtime", RuntimeWarning) + + assert len(record) == 2 + assert str(record[0].message) == "user" + assert str(record[1].message) == "runtime" + + def test_double_test(self, testdir): """If a test is run again, the warning should still be raised""" testdir.makepyfile(''' From 56d1858ea2915e6ba765d6bf337b1b19de832f25 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 28 Dec 2016 22:32:30 -0200 Subject: [PATCH 064/106] Remove duplicate '@lesteve' link from CHANGELOG --- CHANGELOG.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d0339aaed..68457f08c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -42,11 +42,8 @@ Changes .. _@fushi: https://github.com/fushi .. _@mattduck: https://github.com/mattduck .. _@wheerd: https://github.com/wheerd -<<<<<<< HEAD .. _@fogo: https://github.com/fogo -======= .. _@lesteve: https://github.com/lesteve ->>>>>>> pytest.warns checks for subclass relationship .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 From 0bd8159b608c57a1467ee1b67b6170335beb6b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Thu, 29 Dec 2016 09:34:21 +0100 Subject: [PATCH 065/106] Add a test when multiple classes are specified in warns --- testing/test_recwarn.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index ef2ebd74c..8a7edcddb 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -247,6 +247,17 @@ class TestWarns(object): assert str(record[0].message) == "user" assert str(record[1].message) == "runtime" + class MyUserWarning(UserWarning): pass + class MyRuntimeWarning(RuntimeWarning): pass + + with pytest.warns((UserWarning, RuntimeWarning)) as record: + warnings.warn("user", MyUserWarning) + warnings.warn("runtime", MyRuntimeWarning) + + assert len(record) == 2 + assert str(record[0].message) == "user" + assert str(record[1].message) == "runtime" + def test_double_test(self, testdir): """If a test is run again, the warning should still be raised""" From 7930a8373dbc520412a36203ca945e83e98b2a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Thu, 29 Dec 2016 10:18:33 +0100 Subject: [PATCH 066/106] Newline for flake8 --- testing/test_recwarn.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 8a7edcddb..40d11cd04 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -248,6 +248,7 @@ class TestWarns(object): assert str(record[1].message) == "runtime" class MyUserWarning(UserWarning): pass + class MyRuntimeWarning(RuntimeWarning): pass with pytest.warns((UserWarning, RuntimeWarning)) as record: From 9e9547a9e4436bd6e7af2590e6f5bf3b1b024ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Tue, 3 Jan 2017 12:03:26 +0100 Subject: [PATCH 067/106] Simplify condition --- _pytest/recwarn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index 4fd41fa8a..9031bdbda 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -216,8 +216,8 @@ class WarningsChecker(WarningsRecorder): # only check if we're not currently handling an exception if all(a is None for a in exc_info): if self.expected_warning is not None: - if not any(issubclass(r.category, exp_warning) for - exp_warning in self.expected_warning for r in self): + if not any(issubclass(r.category, self.expected_warning) + for r in self): __tracebackhide__ = True pytest.fail("DID NOT WARN. No warnings of type {0} was emitted. " "The list of emitted warnings is: {1}.".format( From 3494dd06fe3ad8978ecf67e7123969826c5fba08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Tue, 3 Jan 2017 12:49:13 +0100 Subject: [PATCH 068/106] Remove duplicate target in rst --- CHANGELOG.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 68457f08c..ad5a3c9f9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -71,7 +71,6 @@ Changes * -.. _@lesteve: https://github.com/lesteve .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme From 6d81c684ccdf502e5e76c04d63e3229e1e5188a2 Mon Sep 17 00:00:00 2001 From: Jeff Widman Date: Wed, 4 Jan 2017 05:31:44 -0800 Subject: [PATCH 069/106] Switch monkeypatch fixture to yield syntax --- AUTHORS | 1 + _pytest/monkeypatch.py | 6 +++--- testing/test_monkeypatch.py | 14 ++++---------- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/AUTHORS b/AUTHORS index 8c6fa1b5d..e3bbdc5d1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -71,6 +71,7 @@ Janne Vanhala Jason R. Coombs Javier Domingo Cansino Javier Romero +Jeff Widman John Towler Jon Sonesen Jordan Guymon diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py index 852e72bed..2651cf044 100644 --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -11,7 +11,7 @@ RE_IMPORT_ERROR_NAME = re.compile("^No module named (.*)$") @pytest.fixture -def monkeypatch(request): +def monkeypatch(): """The returned ``monkeypatch`` fixture provides these helper methods to modify objects, dictionaries or os.environ:: @@ -30,8 +30,8 @@ def monkeypatch(request): will be raised if the set/deletion operation has no target. """ mpatch = MonkeyPatch() - request.addfinalizer(mpatch.undo) - return mpatch + yield mpatch + mpatch.undo() def resolve(name): diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 3fcd20f32..9d02e2cc0 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -7,16 +7,12 @@ from _pytest.monkeypatch import MonkeyPatch @pytest.fixture -def mp(request): +def mp(): cwd = os.getcwd() sys_path = list(sys.path) - - def cleanup(): - sys.path[:] = sys_path - os.chdir(cwd) - - request.addfinalizer(cleanup) - return MonkeyPatch() + yield MonkeyPatch() + sys.path[:] = sys_path + os.chdir(cwd) def test_setattr(): @@ -329,5 +325,3 @@ def test_issue1338_name_resolving(): monkeypatch.delattr('requests.sessions.Session.request') finally: monkeypatch.undo() - - From 7559400183de8d1d8df2521193be36c80e23c164 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 5 Jan 2017 19:18:03 -0200 Subject: [PATCH 070/106] Add py36 to test on AppVeyor Fix #2134 --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index c82b81ce9..aa28e4db8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,6 +15,7 @@ environment: - TOXENV: "py33" - TOXENV: "py34" - TOXENV: "py35" + - TOXENV: "py36" - TOXENV: "pypy" - TOXENV: "py27-pexpect" - TOXENV: "py27-xdist" From d4afa1554b225d11565d5fb81136edea51c54b0d Mon Sep 17 00:00:00 2001 From: mandeep Date: Sun, 8 Jan 2017 22:52:42 -0600 Subject: [PATCH 071/106] Refactored old style classes to new style classes --- _pytest/_argcomplete.py | 2 +- _pytest/assertion/__init__.py | 2 +- _pytest/cacheprovider.py | 2 +- _pytest/capture.py | 12 ++++++------ _pytest/config.py | 10 +++++----- _pytest/debugging.py | 4 ++-- _pytest/fixtures.py | 12 ++++++------ _pytest/main.py | 2 +- _pytest/mark.py | 8 ++++---- _pytest/monkeypatch.py | 4 ++-- _pytest/pytester.py | 22 +++++++++++----------- _pytest/runner.py | 4 ++-- _pytest/skipping.py | 2 +- _pytest/terminal.py | 4 ++-- _pytest/tmpdir.py | 2 +- _pytest/vendored_packages/pluggy.py | 6 +++--- 16 files changed, 49 insertions(+), 49 deletions(-) diff --git a/_pytest/_argcomplete.py b/_pytest/_argcomplete.py index 3ab679d8b..8fbbf2660 100644 --- a/_pytest/_argcomplete.py +++ b/_pytest/_argcomplete.py @@ -62,7 +62,7 @@ import sys import os from glob import glob -class FastFilesCompleter: +class FastFilesCompleter(object): 'Fast file completer class' def __init__(self, directories=True): self.directories = directories diff --git a/_pytest/assertion/__init__.py b/_pytest/assertion/__init__.py index e0fb4284e..fe0653bb7 100644 --- a/_pytest/assertion/__init__.py +++ b/_pytest/assertion/__init__.py @@ -59,7 +59,7 @@ class DummyRewriteHook(object): pass -class AssertionState: +class AssertionState(object): """State for the assertion plugin.""" def __init__(self, config, mode): diff --git a/_pytest/cacheprovider.py b/_pytest/cacheprovider.py index 0657001f2..cd09f4a02 100755 --- a/_pytest/cacheprovider.py +++ b/_pytest/cacheprovider.py @@ -87,7 +87,7 @@ class Cache(object): json.dump(value, f, indent=2, sort_keys=True) -class LFPlugin: +class LFPlugin(object): """ Plugin which implements the --lf (run last-failing) option """ def __init__(self, config): self.config = config diff --git a/_pytest/capture.py b/_pytest/capture.py index a90e308ce..3fe1816d8 100644 --- a/_pytest/capture.py +++ b/_pytest/capture.py @@ -57,7 +57,7 @@ def pytest_load_initial_conftests(early_config, parser, args): sys.stderr.write(err) -class CaptureManager: +class CaptureManager(object): def __init__(self, method): self._method = method @@ -182,7 +182,7 @@ def capfd(request): return c -class CaptureFixture: +class CaptureFixture(object): def __init__(self, captureclass, request): self.captureclass = captureclass self.request = request @@ -315,10 +315,10 @@ class MultiCapture(object): return (self.out.snap() if self.out is not None else "", self.err.snap() if self.err is not None else "") -class NoCapture: +class NoCapture(object): __init__ = start = done = suspend = resume = lambda *args: None -class FDCapture: +class FDCapture(object): """ Capture IO to/from a given os-level filedescriptor. """ def __init__(self, targetfd, tmpfile=None): @@ -394,7 +394,7 @@ class FDCapture: os.write(self.targetfd_save, data) -class SysCapture: +class SysCapture(object): def __init__(self, fd, tmpfile=None): name = patchsysdict[fd] self._old = getattr(sys, name) @@ -432,7 +432,7 @@ class SysCapture: self._old.flush() -class DontReadFromInput: +class DontReadFromInput(object): """Temporary stub class. Ideally when stdin is accessed, the capturing should be turned off, with possibly all data captured so far sent to the screen. This should be configurable, though, diff --git a/_pytest/config.py b/_pytest/config.py index 55326447e..1db281539 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -62,7 +62,7 @@ def main(args=None, plugins=None): sys.stderr.write("ERROR: %s\n" %(msg,)) return 4 -class cmdline: # compatibility namespace +class cmdline(object): # compatibility namespace main = staticmethod(main) @@ -447,7 +447,7 @@ class PytestPluginManager(PluginManager): self.consider_module(mod) -class Parser: +class Parser(object): """ Parser for command line arguments and ini-file values. :ivar extra_info: dict of generic param -> value to display in case @@ -582,7 +582,7 @@ class ArgumentError(Exception): return self.msg -class Argument: +class Argument(object): """class that mimics the necessary behaviour of optparse.Option its currently a least effort implementation @@ -712,7 +712,7 @@ class Argument: return 'Argument({0})'.format(', '.join(args)) -class OptionGroup: +class OptionGroup(object): def __init__(self, name, description="", parser=None): self.name = name self.description = description @@ -838,7 +838,7 @@ class CmdOptions(object): def copy(self): return CmdOptions(self.__dict__) -class Notset: +class Notset(object): def __repr__(self): return "" diff --git a/_pytest/debugging.py b/_pytest/debugging.py index c8d00ad79..c21e0977d 100644 --- a/_pytest/debugging.py +++ b/_pytest/debugging.py @@ -43,7 +43,7 @@ def pytest_configure(config): pytestPDB._pdb_cls = pdb_cls config._cleanup.append(fin) -class pytestPDB: +class pytestPDB(object): """ Pseudo PDB that defers to the real pdb. """ _pluginmanager = None _config = None @@ -64,7 +64,7 @@ class pytestPDB: self._pdb_cls().set_trace(frame) -class PdbInvoke: +class PdbInvoke(object): def pytest_exception_interact(self, node, call, report): capman = node.config.pluginmanager.getplugin("capturemanager") if capman: diff --git a/_pytest/fixtures.py b/_pytest/fixtures.py index 28bcd4d8d..f675217f8 100644 --- a/_pytest/fixtures.py +++ b/_pytest/fixtures.py @@ -222,7 +222,7 @@ def slice_items(items, ignore, scoped_argkeys_cache): -class FuncargnamesCompatAttr: +class FuncargnamesCompatAttr(object): """ helper class so that Metafunc, Function and FixtureRequest don't need to each define the "funcargnames" compatibility attribute. """ @@ -258,7 +258,7 @@ def fillfixtures(function): def get_direct_param_fixture_func(request): return request.param -class FuncFixtureInfo: +class FuncFixtureInfo(object): def __init__(self, argnames, names_closure, name2fixturedefs): self.argnames = argnames self.names_closure = names_closure @@ -456,7 +456,7 @@ class FixtureRequest(FuncargnamesCompatAttr): fixturedef = self._getnextfixturedef(argname) except FixtureLookupError: if argname == "request": - class PseudoFixtureDef: + class PseudoFixtureDef(object): cached_result = (self, [0], None) scope = "function" return PseudoFixtureDef @@ -723,7 +723,7 @@ def call_fixture_func(fixturefunc, request, kwargs): return res -class FixtureDef: +class FixtureDef(object): """ A container for a factory definition. """ def __init__(self, fixturemanager, baseid, argname, func, scope, params, unittest=False, ids=None): @@ -822,7 +822,7 @@ def pytest_fixture_setup(fixturedef, request): return result -class FixtureFunctionMarker: +class FixtureFunctionMarker(object): def __init__(self, scope, params, autouse=False, ids=None, name=None): self.scope = scope self.params = params @@ -909,7 +909,7 @@ def pytestconfig(request): return request.config -class FixtureManager: +class FixtureManager(object): """ pytest fixtures definitions and information is stored and managed from this class. diff --git a/_pytest/main.py b/_pytest/main.py index a2a53cced..3d2d455d1 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -179,7 +179,7 @@ def pytest_ignore_collect(path, config): return False -class FSHookProxy: +class FSHookProxy(object): def __init__(self, fspath, pm, remove_mods): self.fspath = fspath self.pm = pm diff --git a/_pytest/mark.py b/_pytest/mark.py index 5a6926ea0..ef9a94ad9 100644 --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -99,7 +99,7 @@ def pytest_collection_modifyitems(items, config): items[:] = remaining -class MarkMapping: +class MarkMapping(object): """Provides a local mapping for markers where item access resolves to True if the marker is present. """ def __init__(self, keywords): @@ -113,7 +113,7 @@ class MarkMapping: return name in self._mymarks -class KeywordMapping: +class KeywordMapping(object): """Provides a local mapping for keywords. Given a list of names, map any substring of one of these names to True. """ @@ -173,7 +173,7 @@ def pytest_configure(config): pytest.mark._config = config -class MarkGenerator: +class MarkGenerator(object): """ Factory for :class:`MarkDecorator` objects - exposed as a ``pytest.mark`` singleton instance. Example:: @@ -210,7 +210,7 @@ def istestfunc(func): return hasattr(func, "__call__") and \ getattr(func, "__name__", "") != "" -class MarkDecorator: +class MarkDecorator(object): """ A decorator for test functions and test classes. When applied it will create :class:`MarkInfo` objects which may be :ref:`retrieved by hooks as item keywords `. diff --git a/_pytest/monkeypatch.py b/_pytest/monkeypatch.py index 852e72bed..313ed89be 100644 --- a/_pytest/monkeypatch.py +++ b/_pytest/monkeypatch.py @@ -88,7 +88,7 @@ def derive_importpath(import_path, raising): return attr, target -class Notset: +class Notset(object): def __repr__(self): return "" @@ -96,7 +96,7 @@ class Notset: notset = Notset() -class MonkeyPatch: +class MonkeyPatch(object): """ Object returned by the ``monkeypatch`` fixture keeping a record of setattr/item/env/syspath changes. """ diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 8b86fc3db..6748fdef4 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -165,7 +165,7 @@ def _pytest(request): """ return PytestArg(request) -class PytestArg: +class PytestArg(object): def __init__(self, request): self.request = request @@ -180,7 +180,7 @@ def get_public_names(l): return [x for x in l if x[0] != "_"] -class ParsedCall: +class ParsedCall(object): def __init__(self, name, kwargs): self.__dict__.update(kwargs) self._name = name @@ -191,7 +191,7 @@ class ParsedCall: return "" %(self._name, d) -class HookRecorder: +class HookRecorder(object): """Record all hooks called in a plugin manager. This wraps all the hook calls in the plugin manager, recording @@ -335,7 +335,7 @@ def testdir(request, tmpdir_factory): rex_outcome = re.compile("(\d+) ([\w-]+)") -class RunResult: +class RunResult(object): """The result of running a command. Attributes: @@ -380,7 +380,7 @@ class RunResult: -class Testdir: +class Testdir(object): """Temporary test directory with tools to test/run pytest itself. This is based on the ``tmpdir`` fixture but provides a number of @@ -707,7 +707,7 @@ class Testdir: rec = [] - class Collect: + class Collect(object): def pytest_configure(x, config): rec.append(self.make_hook_recorder(config.pluginmanager)) @@ -718,7 +718,7 @@ class Testdir: if len(rec) == 1: reprec = rec.pop() else: - class reprec: + class reprec(object): pass reprec.ret = ret @@ -742,13 +742,13 @@ class Testdir: reprec = self.inline_run(*args, **kwargs) except SystemExit as e: - class reprec: + class reprec(object): ret = e.args[0] except Exception: traceback.print_exc() - class reprec: + class reprec(object): ret = 3 finally: out, err = capture.reset() @@ -1033,7 +1033,7 @@ def getdecoded(out): py.io.saferepr(out),) -class LineComp: +class LineComp(object): def __init__(self): self.stringio = py.io.TextIO() @@ -1049,7 +1049,7 @@ class LineComp: return LineMatcher(lines1).fnmatch_lines(lines2) -class LineMatcher: +class LineMatcher(object): """Flexible matching of text. This is a convenience class to test large texts like the output of diff --git a/_pytest/runner.py b/_pytest/runner.py index 89635a839..f17155dae 100644 --- a/_pytest/runner.py +++ b/_pytest/runner.py @@ -55,7 +55,7 @@ def pytest_sessionstart(session): def pytest_sessionfinish(session): session._setupstate.teardown_all() -class NodeInfo: +class NodeInfo(object): def __init__(self, location): self.location = location @@ -150,7 +150,7 @@ def call_runtest_hook(item, when, **kwds): ihook = getattr(item.ihook, hookname) return CallInfo(lambda: ihook(item=item, **kwds), when=when) -class CallInfo: +class CallInfo(object): """ Result/Exception info a function invocation. """ #: None or ExceptionInfo object. excinfo = None diff --git a/_pytest/skipping.py b/_pytest/skipping.py index c10fb18c3..cc92012a0 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -72,7 +72,7 @@ def xfail(reason=""): xfail.Exception = XFailed -class MarkEvaluator: +class MarkEvaluator(object): def __init__(self, item, name): self.item = item self.name = name diff --git a/_pytest/terminal.py b/_pytest/terminal.py index 16bf75733..f509283cb 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -80,7 +80,7 @@ def pytest_report_teststatus(report): letter = "f" return report.outcome, letter, report.outcome.upper() -class WarningReport: +class WarningReport(object): def __init__(self, code, message, nodeid=None, fslocation=None): self.code = code self.message = message @@ -88,7 +88,7 @@ class WarningReport: self.fslocation = fslocation -class TerminalReporter: +class TerminalReporter(object): def __init__(self, config, file=None): import _pytest.config self.config = config diff --git a/_pytest/tmpdir.py b/_pytest/tmpdir.py index 28a6b0636..565c35cf9 100644 --- a/_pytest/tmpdir.py +++ b/_pytest/tmpdir.py @@ -6,7 +6,7 @@ import py from _pytest.monkeypatch import MonkeyPatch -class TempdirFactory: +class TempdirFactory(object): """Factory for temporary directories under the common base temp directory. The base directory can be configured using the ``--basetemp`` option. diff --git a/_pytest/vendored_packages/pluggy.py b/_pytest/vendored_packages/pluggy.py index 9c13932b3..a300053a1 100644 --- a/_pytest/vendored_packages/pluggy.py +++ b/_pytest/vendored_packages/pluggy.py @@ -75,7 +75,7 @@ __all__ = ["PluginManager", "PluginValidationError", "HookCallError", _py3 = sys.version_info > (3, 0) -class HookspecMarker: +class HookspecMarker(object): """ Decorator helper class for marking functions as hook specifications. You can instantiate it with a project_name to get a decorator. @@ -113,7 +113,7 @@ class HookspecMarker: return setattr_hookspec_opts -class HookimplMarker: +class HookimplMarker(object): """ Decorator helper class for marking functions as hook implementations. You can instantiate with a project_name to get a decorator. @@ -770,7 +770,7 @@ class _HookCaller(object): proc(res[0]) -class HookImpl: +class HookImpl(object): def __init__(self, plugin, plugin_name, function, hook_impl_opts): self.function = function self.argnames = varnames(self.function) From e412ea1d5a245ecb5f06b17a6ae0f6abdc391418 Mon Sep 17 00:00:00 2001 From: mandeep Date: Tue, 10 Jan 2017 07:58:22 -0600 Subject: [PATCH 072/106] Added name to AUTHORS and change to CHANGELOG --- AUTHORS | 1 + CHANGELOG.rst | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/AUTHORS b/AUTHORS index 1d7cb65ab..30132759b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,6 +87,7 @@ Lukas Bednar Luke Murphy Maciek Fijalkowski Maho +Mandeep Bhutani Manuel Krebber Marc Schlaich Marcin Bachry diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ad5a3c9f9..41d316dd5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,6 +17,9 @@ New Features Changes ------- +* Old-style classes have been changed to new-style classes in order to improve + compatability with Python 2. Thanks to `@mandeep`_ for the PR (`#2147`_). + * It is now possible to skip test classes from being collected by setting a ``__test__`` attribute to ``False`` in the class body (`#2007`_). Thanks to `@syre`_ for the report and `@lwm`_ for the PR. @@ -44,6 +47,7 @@ Changes .. _@wheerd: https://github.com/wheerd .. _@fogo: https://github.com/fogo .. _@lesteve: https://github.com/lesteve +.. _@mandeep: https://github.com/mandeep .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 @@ -52,6 +56,7 @@ Changes .. _#2013: https://github.com/pytest-dev/pytest/issues/2013 .. _#2101: https://github.com/pytest-dev/pytest/pull/2101 .. _#2166: https://github.com/pytest-dev/pytest/pull/2166 +.. _#2147: https://github.com/pytest-dev/pytest/issues/2147 3.0.6.dev0 (unreleased) ======================= From aa82db9fe286ef709645151f11df8ec451a21c18 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 10 Jan 2017 19:25:57 +0100 Subject: [PATCH 073/106] Ensure the LICENSE is included in built wheels Otherwise it is not included by default as wheels do not honor the MANIFEST.in Signed-off-by: Philippe Ombredanne --- setup.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.cfg b/setup.cfg index 1ab4fd059..f3299af5b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,5 +9,8 @@ upload-dir = doc/en/build/html [bdist_wheel] universal = 1 +[metadata] +license_file = LICENSE + [devpi:upload] formats = sdist.tgz,bdist_wheel From e18b2a427a803a3e89b4dc88e6c904e32f20eb09 Mon Sep 17 00:00:00 2001 From: Eli Boyarski Date: Wed, 11 Jan 2017 16:49:09 +0200 Subject: [PATCH 074/106] Fail assert_outcomes() on missing terminal report Currently if the terminal report of testdir.runpytest() is missing, assert_outcomes() on its output fails because parseoutcomes() returns an unexpected value (None). It's better to fail parseoutcomes() directly. --- AUTHORS | 1 + CHANGELOG.rst | 4 ++++ _pytest/pytester.py | 1 + testing/test_pytester.py | 7 +++++++ 4 files changed, 13 insertions(+) diff --git a/AUTHORS b/AUTHORS index e3bbdc5d1..acf715cde 100644 --- a/AUTHORS +++ b/AUTHORS @@ -141,3 +141,4 @@ Tyler Goodlet Vasily Kuznetsov Wouter van Ackooy Xuecong Liao +Eli Boyarski diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7c3df0327..f2248ca20 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,11 +14,15 @@ subdirectories with ini configuration files now uses the correct ini file (`#2148`_). Thanks `@pelme`_. +* Fail ``testdir.runpytest().assert_outcomes()`` explicitly if the pytest + terminal output it relies on is missing. Thanks to `@eli-b`_ for the PR. + * .. _@lesteve: https://github.com/lesteve .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme +.. _@eli-b: https://github.com/eli-b .. _#2129: https://github.com/pytest-dev/pytest/issues/2129 .. _#2148: https://github.com/pytest-dev/pytest/issues/2148 diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 17ff529a6..de7899173 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -367,6 +367,7 @@ class RunResult: for num, cat in outcomes: d[cat] = int(num) return d + raise ValueError("Pytest terminal report not found") def assert_outcomes(self, passed=0, skipped=0, failed=0): """ assert that the specified outcomes appear with the respective diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 14548808c..49cf43a3e 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -124,3 +124,10 @@ def test_inline_run_clean_modules(testdir): test_mod.write("def test_foo(): assert False") result2 = testdir.inline_run(str(test_mod)) assert result2.ret == EXIT_TESTSFAILED + +def test_assert_outcomes_after_pytest_erro(testdir): + testdir.makepyfile("def test_foo(): assert True") + + result = testdir.runpytest('--unexpected-argument') + with pytest.raises(ValueError, message="Pytest terminal report not found"): + result.assert_outcomes(passed=0) From 043aadeaf2467d7b4c263ba339fe1daea3ac8ae5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 11 Jan 2017 17:11:56 -0200 Subject: [PATCH 075/106] Consider plugins loaded by PYTEST_PLUGINS for assertion rewrite Fix #2185 --- CHANGELOG.rst | 5 +++++ _pytest/config.py | 7 +++++-- testing/test_assertrewrite.py | 18 +++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7c3df0327..bb5c5e6a6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,10 @@ * pytest no longer recognizes coroutine functions as yield tests (`#2129`_). Thanks to `@malinoff`_ for the PR. +* Plugins loaded by the ``PYTEST_PLUGINS`` environment variable are now automatically + considered for assertion rewriting (`#2185`_). + Thanks `@nicoddemus`_ for the PR. + * 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. @@ -23,6 +27,7 @@ .. _#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 +.. _#2185: https://github.com/pytest-dev/pytest/issues/2185 3.0.5 (2016-12-05) diff --git a/_pytest/config.py b/_pytest/config.py index 55326447e..9aa465954 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -399,13 +399,15 @@ class PytestPluginManager(PluginManager): self.consider_module(conftestmodule) def consider_env(self): - self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS")) + specs = os.environ.get("PYTEST_PLUGINS") + if specs: + plugins = specs.split(',') + self._import_plugin_specs(plugins) def consider_module(self, mod): plugins = getattr(mod, 'pytest_plugins', []) if isinstance(plugins, str): plugins = [plugins] - self.rewrite_hook.mark_rewrite(*plugins) self._import_plugin_specs(plugins) def _import_plugin_specs(self, spec): @@ -427,6 +429,7 @@ class PytestPluginManager(PluginManager): importspec = "_pytest." + modname else: importspec = modname + self.rewrite_hook.mark_rewrite(modname) try: __import__(importspec) except ImportError as e: diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 8e26cdb1b..fdf674f25 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -682,7 +682,7 @@ def test_rewritten(): hook.mark_rewrite('test_remember_rewritten_modules') assert warnings == [] - def test_rewrite_warning_using_pytest_plugins(self, testdir, monkeypatch): + def test_rewrite_warning_using_pytest_plugins(self, testdir): testdir.makepyfile(**{ 'conftest.py': "pytest_plugins = ['core', 'gui', 'sci']", 'core.py': "", @@ -695,6 +695,22 @@ def test_rewritten(): result.stdout.fnmatch_lines(['*= 1 passed in *=*']) assert 'pytest-warning summary' not in result.stdout.str() + def test_rewrite_warning_using_pytest_plugins_env_var(self, testdir, monkeypatch): + monkeypatch.setenv('PYTEST_PLUGINS', 'plugin') + testdir.makepyfile(**{ + 'plugin.py': "", + 'test_rewrite_warning_using_pytest_plugins_env_var.py': """ + import plugin + pytest_plugins = ['plugin'] + 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 7cd7c283ddde7c45ad1b97372948ff6ba2f0aaa4 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 12 Jan 2017 14:23:09 -0200 Subject: [PATCH 076/106] Refactor plugin specs handling into an isolated function --- _pytest/config.py | 38 ++++++++++++++++++++++++-------------- testing/test_config.py | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/_pytest/config.py b/_pytest/config.py index 9aa465954..8578e8aaa 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -399,30 +399,22 @@ class PytestPluginManager(PluginManager): self.consider_module(conftestmodule) def consider_env(self): - specs = os.environ.get("PYTEST_PLUGINS") - if specs: - plugins = specs.split(',') - self._import_plugin_specs(plugins) + self._import_plugin_specs(os.environ.get("PYTEST_PLUGINS")) def consider_module(self, mod): - plugins = getattr(mod, 'pytest_plugins', []) - if isinstance(plugins, str): - plugins = [plugins] - self._import_plugin_specs(plugins) + self._import_plugin_specs(getattr(mod, 'pytest_plugins', [])) def _import_plugin_specs(self, spec): - if spec: - if isinstance(spec, str): - spec = spec.split(",") - for import_spec in spec: - self.import_plugin(import_spec) + plugins = _get_plugin_specs_as_list(spec) + for import_spec in plugins: + self.import_plugin(import_spec) def import_plugin(self, modname): # most often modname refers to builtin modules, e.g. "pytester", # "terminal" or "capture". Those plugins are registered under their # basename for historic purposes but must be imported with the # _pytest prefix. - assert isinstance(modname, str) + assert isinstance(modname, str), "module name as string required, got %r" % modname if self.get_plugin(modname) is not None: return if modname in builtin_plugins: @@ -450,6 +442,24 @@ class PytestPluginManager(PluginManager): self.consider_module(mod) +def _get_plugin_specs_as_list(specs): + """ + Parses a list of "plugin specs" and returns a list of plugin names. + + Plugin specs can be given as a list of strings separated by "," or already as a list/tuple in + which case it is returned as a list. Specs can also be `None` in which case an + empty list is returned. + """ + if specs is not None: + if isinstance(specs, str): + specs = specs.split(',') if specs else [] + if not isinstance(specs, (list, tuple)): + raise UsageError("Plugin specs must be a ','-separated string or a " + "list/tuple of strings for plugin names. Given: %r" % specs) + return list(specs) + return [] + + class Parser: """ Parser for command line arguments and ini-file values. diff --git a/testing/test_config.py b/testing/test_config.py index 6bc867737..e6aa423e8 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -587,6 +587,21 @@ def test_load_initial_conftest_last_ordering(testdir): assert [x.function.__module__ for x in l] == expected +def test_get_plugin_specs_as_list(): + from _pytest.config import _get_plugin_specs_as_list + with pytest.raises(pytest.UsageError): + _get_plugin_specs_as_list(set(['foo'])) + with pytest.raises(pytest.UsageError): + _get_plugin_specs_as_list(dict()) + + assert _get_plugin_specs_as_list(None) == [] + assert _get_plugin_specs_as_list('') == [] + assert _get_plugin_specs_as_list('foo') == ['foo'] + assert _get_plugin_specs_as_list('foo,bar') == ['foo', 'bar'] + assert _get_plugin_specs_as_list(['foo', 'bar']) == ['foo', 'bar'] + assert _get_plugin_specs_as_list(('foo', 'bar')) == ['foo', 'bar'] + + class TestWarning: def test_warn_config(self, testdir): testdir.makeconftest(""" From 46a9861d29b1af89caa239b978d6a4717bddce19 Mon Sep 17 00:00:00 2001 From: Rutger Prins Date: Fri, 13 Jan 2017 16:52:02 +0100 Subject: [PATCH 077/106] Remove mention of --assert=reinterp in documentation Related to #1940 --- doc/en/assert.rst | 49 ++++++++++------------------------------------- doc/en/faq.rst | 8 -------- 2 files changed, 10 insertions(+), 47 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index f898391df..b682897e1 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -262,50 +262,20 @@ Advanced assertion introspection .. versionadded:: 2.1 -Reporting details about a failing assertion is achieved either by rewriting -assert statements before they are run or re-evaluating the assert expression and -recording the intermediate values. Which technique is used depends on the -location of the assert, ``pytest`` configuration, and Python version being used -to run ``pytest``. - -By default, ``pytest`` rewrites assert statements in test modules. -Rewritten assert statements put introspection information into the assertion failure message. -``pytest`` only rewrites test modules directly discovered by its test collection process, so -asserts in supporting modules which are not themselves test modules will not be -rewritten. +Reporting details about a failing assertion is achieved by rewriting assert +statements before they are run. Rewritten assert statements put introspection +information into the assertion failure message. ``pytest`` only rewrites test +modules directly discovered by its test collection process, so asserts in +supporting modules which are not themselves test modules will not be rewritten. .. note:: ``pytest`` rewrites test modules on import. It does this by using an import - hook to write a new pyc files. Most of the time this works transparently. + hook to write new pyc files. Most of the time this works transparently. However, if you are messing with import yourself, the import hook may - interfere. If this is the case, simply use ``--assert=reinterp`` or - ``--assert=plain``. Additionally, rewriting will fail silently if it cannot - write new pycs, i.e. in a read-only filesystem or a zipfile. - -If an assert statement has not been rewritten or the Python version is less than -2.6, ``pytest`` falls back on assert reinterpretation. In assert -reinterpretation, ``pytest`` walks the frame of the function containing the -assert statement to discover sub-expression results of the failing assert -statement. You can force ``pytest`` to always use assertion reinterpretation by -passing the ``--assert=reinterp`` option. - -Assert reinterpretation has a caveat not present with assert rewriting: If -evaluating the assert expression has side effects you may get a warning that the -intermediate values could not be determined safely. A common example of this -issue is an assertion which reads from a file:: - - assert f.read() != '...' - -If this assertion fails then the re-evaluation will probably succeed! -This is because ``f.read()`` will return an empty string when it is -called the second time during the re-evaluation. However, it is -easy to rewrite the assertion and avoid any trouble:: - - content = f.read() - assert content != '...' - -All assert introspection can be turned off by passing ``--assert=plain``. + interfere. If this is the case, use ``--assert=plain``. Additionally, + rewriting will fail silently if it cannot write new pycs, i.e. in a read-only + filesystem or a zipfile. For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting `_. @@ -318,3 +288,4 @@ For further information, Benjamin Peterson wrote up `Behind the scenes of pytest .. versionchanged:: 3.0 Removes the ``--no-assert`` and``--nomagic`` options. + Removes the ``--assert=reinterp`` option. diff --git a/doc/en/faq.rst b/doc/en/faq.rst index 774998b14..27d74e114 100644 --- a/doc/en/faq.rst +++ b/doc/en/faq.rst @@ -66,14 +66,6 @@ This completely avoids previous issues of confusing assertion-reporting. It also means, that you can use Python's ``-O`` optimization without losing assertions in test modules. -``pytest`` contains a second, mostly obsolete, assert debugging technique -invoked via ``--assert=reinterpret``: When an ``assert`` statement fails, ``pytest`` re-interprets -the expression part to show intermediate values. This technique suffers -from a caveat that the rewriting does not: If your expression has side -effects (better to avoid them anyway!) the intermediate values may not -be the same, confusing the reinterpreter and obfuscating the initial -error (this is also explained at the command line if it happens). - You can also turn off all assertion interaction using the ``--assert=plain`` option. From 61fa91f3d013aad4fae4d2e54a3c04100317307f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 17 Jan 2017 21:09:04 -0200 Subject: [PATCH 078/106] Fix marker example on "linux" platform I cheated a little and updated the example output by hand. :grin: Fix #2200 --- doc/en/example/markers.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 99b09fa57..b0825ce6e 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -450,7 +450,7 @@ for your particular platform, you could use the following plugin:: import sys import pytest - ALL = set("darwin linux2 win32".split()) + ALL = set("darwin linux win32".split()) def pytest_runtest_setup(item): if isinstance(item, item.Function): @@ -470,7 +470,7 @@ Let's do a little test file to show how this looks like:: def test_if_apple_is_evil(): pass - @pytest.mark.linux2 + @pytest.mark.linux def test_if_linux_works(): pass @@ -481,7 +481,7 @@ Let's do a little test file to show how this looks like:: def test_runs_everywhere(): pass -then you will see two test skipped and two executed tests as expected:: +then you will see two tests skipped and two executed tests as expected:: $ pytest -rs # this option reports skip reasons ======= test session starts ======== @@ -489,15 +489,15 @@ then you will see two test skipped and two executed tests as expected:: rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - test_plat.py sss. + test_plat.py s.s. ======= short test summary info ======== - SKIP [3] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux + SKIP [2] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux - ======= 1 passed, 3 skipped in 0.12 seconds ======== + ======= 2 passed, 2 skipped in 0.12 seconds ======== Note that if you specify a platform via the marker-command line option like this:: - $ pytest -m linux2 + $ pytest -m linux ======= 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: @@ -506,7 +506,7 @@ Note that if you specify a platform via the marker-command line option like this test_plat.py s ======= 3 tests deselected ======== - ======= 1 skipped, 3 deselected in 0.12 seconds ======== + ======= 1 passed, 3 deselected in 0.12 seconds ======== then the unmarked-tests will not be run. It is thus a way to restrict the run to the specific tests. From 123289a88ee01cfc3083fee22e0161cf4c9e4087 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 19 Jan 2017 11:38:15 +0100 Subject: [PATCH 079/106] fixes #2208 by introducing a iteration limit --- CHANGELOG.rst | 5 +++++ _pytest/compat.py | 12 ++++++++++-- testing/test_compat.py | 33 +++++++++++++++++++++++++++++---- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 41d316dd5..3d78d3273 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -41,6 +41,10 @@ Changes * fix `#2013`_: turn RecordedWarning into namedtupe, to give it a comprehensible repr while preventing unwarranted modification +* fix `#2208`_: ensure a iteration limit for _pytest.compat.get_real_func. + Thanks `@RonnyPfannschmidt`_ for the Report and PR + + .. _@davidszotten: https://github.com/davidszotten .. _@fushi: https://github.com/fushi .. _@mattduck: https://github.com/mattduck @@ -57,6 +61,7 @@ Changes .. _#2101: https://github.com/pytest-dev/pytest/pull/2101 .. _#2166: https://github.com/pytest-dev/pytest/pull/2166 .. _#2147: https://github.com/pytest-dev/pytest/issues/2147 +.. _#2208: https://github.com/pytest-dev/pytest/issues/2208 3.0.6.dev0 (unreleased) ======================= diff --git a/_pytest/compat.py b/_pytest/compat.py index 2f5e75cf1..09f681c86 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -180,8 +180,16 @@ def get_real_func(obj): """ gets the real function object of the (possibly) wrapped object by functools.wraps or functools.partial. """ - while hasattr(obj, "__wrapped__"): - obj = obj.__wrapped__ + start_obj = obj + for i in range(100): + new_obj = getattr(obj, '__wrapped__', None) + if new_obj is None: + break + obj = new_obj + else: + raise ValueError( + ("could not find real function of {start}" + "\nstopped at {current}").format(start=start_obj, current=obj)) if isinstance(obj, functools.partial): obj = obj.func return obj diff --git a/testing/test_compat.py b/testing/test_compat.py index 1fdd07e29..1736e8e2a 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,7 +1,7 @@ import sys import pytest -from _pytest.compat import is_generator +from _pytest.compat import is_generator, get_real_func def test_is_generator(): @@ -15,7 +15,30 @@ 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_real_func_loop_limit(): + + class Evil(object): + def __init__(self): + self.left = 1000 + + def __repr__(self): + return "".format(left=self.left) + + def __getattr__(self, attr): + if not self.left: + raise RuntimeError('its over') + self.left -= 1 + return self + + evil = Evil() + + with pytest.raises(ValueError): + res = get_real_func(evil) + print(res) + + +@pytest.mark.skipif(sys.version_info < (3, 4), + reason='asyncio available in Python 3.4+') def test_is_generator_asyncio(testdir): testdir.makepyfile(""" from _pytest.compat import is_generator @@ -27,12 +50,14 @@ def test_is_generator_asyncio(testdir): def test_is_generator_asyncio(): assert not is_generator(baz) """) - # avoid importing asyncio into pytest's own process, which in turn imports logging (#8) + # avoid importing asyncio into pytest's own process, + # which in turn imports logging (#8) result = testdir.runpytest_subprocess() result.stdout.fnmatch_lines(['*1 passed*']) -@pytest.mark.skipif(sys.version_info < (3, 5), reason='async syntax available in Python 3.5+') +@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 From 250597d468149121fd6d8ae8f867fbe8faf843a2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 19 Jan 2017 13:05:58 +0100 Subject: [PATCH 080/106] get_real_func: use saferepr when formatting the error message --- _pytest/compat.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_pytest/compat.py b/_pytest/compat.py index 09f681c86..e097dee51 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -189,7 +189,9 @@ def get_real_func(obj): else: raise ValueError( ("could not find real function of {start}" - "\nstopped at {current}").format(start=start_obj, current=obj)) + "\nstopped at {current}").format( + start=py.io.saferepr(start_obj), + current=py.io.saferepr(obj))) if isinstance(obj, functools.partial): obj = obj.func return obj From 2574da8d32197d2c82889bd809c931c641c24105 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 19 Jan 2017 20:47:45 -0200 Subject: [PATCH 081/106] Fix pytester internal plugin to work correctly with latest versions of zope.interface Fix #1989 --- .travis.yml | 4 ---- CHANGELOG.rst | 4 ++++ _pytest/pytester.py | 6 +++--- appveyor.yml | 6 ------ 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8f127b1a..b2d356e19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,10 +29,6 @@ env: - TESTENV=docs matrix: - allow_failures: - # see #1989 - - env: TESTENV=py27-trial - - env: TESTENV=py35-trial include: - env: TESTENV=py36 python: '3.6-dev' diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bb5c5e6a6..173347d7b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,9 @@ expected warnings and the list of caught warnings is added to the error message. Thanks `@lesteve`_ for the PR. +* Fix ``pytester`` internal plugin to work correctly with latest versions of + ``zope.interface`` (`#1989`_). Thanks `@nicoddemus`_ 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`_. @@ -24,6 +27,7 @@ .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme +.. _#1989: https://github.com/pytest-dev/pytest/issues/1989 .. _#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 diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 17ff529a6..b401c4f23 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -446,9 +446,9 @@ class Testdir: the module is re-imported. """ for name in set(sys.modules).difference(self._savemodulekeys): - # it seems zope.interfaces is keeping some state - # (used by twisted related tests) - if name != "zope.interface": + # zope.interface (used by twisted-related tests) keeps internal + # state and can't be deleted + if not name.startswith("zope.interface"): del sys.modules[name] def make_hook_recorder(self, pluginmanager): diff --git a/appveyor.yml b/appveyor.yml index aa28e4db8..cc72b4b70 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,12 +28,6 @@ environment: - TOXENV: "freeze" - TOXENV: "docs" -matrix: - allow_failures: - # see #1989 - - TOXENV: "py27-trial" - - TOXENV: "py35-trial" - install: - echo Installed Pythons - dir c:\Python* From c477f09177cabaaa1dbddd9d754f44ec9eba7b2a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 19 Jan 2017 21:33:51 -0200 Subject: [PATCH 082/106] Assert statements of the pytester plugin again benefit from assertion rewriting Fix #1920 --- CHANGELOG.rst | 4 ++++ _pytest/config.py | 2 +- testing/test_assertion.py | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bb5c5e6a6..452d50b76 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,9 @@ expected warnings and the list of caught warnings is added to the error message. Thanks `@lesteve`_ for the PR. +* Assert statements of the ``pytester`` plugin again benefit from assertion rewriting (`#1920`_). + Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ 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`_. @@ -24,6 +27,7 @@ .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme +.. _#1920: https://github.com/pytest-dev/pytest/issues/1920 .. _#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 diff --git a/_pytest/config.py b/_pytest/config.py index 8578e8aaa..42d1a118a 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -421,7 +421,7 @@ class PytestPluginManager(PluginManager): importspec = "_pytest." + modname else: importspec = modname - self.rewrite_hook.mark_rewrite(modname) + self.rewrite_hook.mark_rewrite(importspec) try: __import__(importspec) except ImportError as e: diff --git a/testing/test_assertion.py b/testing/test_assertion.py index c63f26b9c..9115d25e2 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -58,6 +58,23 @@ class TestImportHookInstallation: assert 0 result.stdout.fnmatch_lines([expected]) + def test_rewrite_assertions_pytester_plugin(self, testdir): + """ + Assertions in the pytester plugin must also benefit from assertion + rewriting (#1920). + """ + testdir.makepyfile(""" + pytest_plugins = ['pytester'] + def test_dummy_failure(testdir): # how meta! + testdir.makepyfile('def test(): assert 0') + r = testdir.inline_run() + r.assertoutcome(passed=1) + """) + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines([ + '*assert 1 == 0*', + ]) + @pytest.mark.parametrize('mode', ['plain', 'rewrite']) def test_pytest_plugins_rewrite(self, testdir, mode): contents = { From 4082f4024a1ea9333e55a5af3954733e2c200c00 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 11:25:48 +0100 Subject: [PATCH 083/106] comment out compatproperty deprecations todo: reenable in the features branch --- _pytest/main.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/_pytest/main.py b/_pytest/main.py index 905b35d83..0aa97da64 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -200,10 +200,11 @@ class _CompatProperty(object): if obj is None: return self - warnings.warn( - "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( - name=self.name, owner=type(owner).__name__), - PendingDeprecationWarning, stacklevel=2) + # TODO: reenable in the features branch + # warnings.warn( + # "usage of {owner!r}.{name} is deprecated, please use pytest.{name} instead".format( + # name=self.name, owner=type(owner).__name__), + # PendingDeprecationWarning, stacklevel=2) return getattr(pytest, self.name) @@ -291,10 +292,10 @@ class Node(object): return getattr(pytest, name) else: cls = getattr(self, name) - - warnings.warn("use of node.%s is deprecated, " - "use pytest_pycollect_makeitem(...) to create custom " - "collection nodes" % name, category=DeprecationWarning) + # TODO: reenable in the features branch + # warnings.warn("use of node.%s is deprecated, " + # "use pytest_pycollect_makeitem(...) to create custom " + # "collection nodes" % name, category=DeprecationWarning) return cls def __repr__(self): From 7b4afd89465596d5d003bb250b5e0531d0e5f172 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 12:09:49 +0100 Subject: [PATCH 084/106] remove unused import --- _pytest/main.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/_pytest/main.py b/_pytest/main.py index 0aa97da64..a32352793 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -3,8 +3,6 @@ import functools import os import sys -import warnings - import _pytest import _pytest._code import py From 6a96b464abf6b3c808f918e6c5cc9c795d2416c8 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 15:26:59 +0100 Subject: [PATCH 085/106] update changelog as suggested --- CHANGELOG.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index ff6efb7ef..fae302fd3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,11 @@ 3.0.6.dev0 ========== -* fix issue #2118 - protect against internal deprecationerrors by changing the code path of Node._getcustomclass. - This also turns a internal deprecation into a real deprecation. +* pytest no longer generates ``PendingDeprecationWarning`` from its own operations, which was introduced by mistake in version ``3.0.5`` (`#2118`_). Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. + + * * @@ -14,6 +15,7 @@ * +.. _#2118: https://github.com/pytest-dev/pytest/issues/2118 3.0.5 ===== From c848d0a771c41b25a3bd8ff8e29cc5493b116a25 Mon Sep 17 00:00:00 2001 From: Ravi Chandra Date: Mon, 16 Jan 2017 16:09:46 +1300 Subject: [PATCH 086/106] Pass parameter name to `make_parametrize_id` hook function --- AUTHORS | 1 + CHANGELOG.rst | 5 +++++ _pytest/hookspec.py | 3 ++- _pytest/python.py | 5 +++-- testing/python/metafunc.py | 23 +++++++++++++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index 30132759b..34189d61a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -120,6 +120,7 @@ Quentin Pradet Ralf Schmitt Raphael Pierzina Raquel Alegre +Ravi Chandra Roberto Polli Romain Dorgueil Roman Bolshakov diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3d78d3273..e4c5f2a79 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -79,10 +79,15 @@ Changes subdirectories with ini configuration files now uses the correct ini file (`#2148`_). Thanks `@pelme`_. +* Modify ``pytest_make_parametrize_id()`` hook to accept ``argname`` as an + additional parameter. + Thanks `@unsignedint`_ for the PR. + * .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme +.. _@unsignedint: https://github.com/unsignedint .. _#2129: https://github.com/pytest-dev/pytest/issues/2129 .. _#2148: https://github.com/pytest-dev/pytest/issues/2148 diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py index b5f51eccf..989cb0c0b 100644 --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -157,9 +157,10 @@ def pytest_generate_tests(metafunc): """ generate (multiple) parametrized calls to a test function.""" @hookspec(firstresult=True) -def pytest_make_parametrize_id(config, val): +def pytest_make_parametrize_id(config, val, argname=None): """Return a user-friendly string representation of the given ``val`` that will be used by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``. + The parameter name is available as ``argname``, if required. """ # ------------------------------------------------------------------------- diff --git a/_pytest/python.py b/_pytest/python.py index fee68251d..18da7ac23 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -197,7 +197,7 @@ def pytest_pycollect_makeitem(collector, name, obj): res = list(collector._genfunctions(name, obj)) outcome.force_result(res) -def pytest_make_parametrize_id(config, val): +def pytest_make_parametrize_id(config, val, argname=None): return None @@ -941,7 +941,8 @@ def _idval(val, argname, idx, idfn, config=None): return _escape_strings(s) if config: - hook_id = config.hook.pytest_make_parametrize_id(config=config, val=val) + hook_id = config.hook.pytest_make_parametrize_id( + config=config, val=val, argname=argname) if hook_id: return hook_id diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e88107d0b..9eea699bf 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1455,3 +1455,26 @@ class TestMarkersWithParametrization: "*test_func*0*PASS*", "*test_func*2*PASS*", ]) + + def test_pytest_make_parametrize_id_with_argname(self, testdir): + testdir.makeconftest(""" + def pytest_make_parametrize_id(config, val, argname): + return str(val * 2 if argname == 'x' else val * 10) + """) + testdir.makepyfile(""" + import pytest + + @pytest.mark.parametrize("x", range(2)) + def test_func(x): + pass + + @pytest.mark.parametrize("y", [1]) + def test_func2(y): + pass + """) + result = testdir.runpytest("-v") + result.stdout.fnmatch_lines([ + "*test_func*0*PASS*", + "*test_func*2*PASS*", + "*test_func2*10*PASS*", + ]) From 0e58c3fa80465a009c9c4d5b4500e73dd32ca80f Mon Sep 17 00:00:00 2001 From: Ravi Chandra Date: Sat, 21 Jan 2017 16:40:42 +1300 Subject: [PATCH 087/106] updates for PR review #2198 --- CHANGELOG.rst | 10 +++++----- _pytest/hookspec.py | 2 +- testing/python/metafunc.py | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4c5f2a79..fc2a2de23 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -44,6 +44,10 @@ Changes * fix `#2208`_: ensure a iteration limit for _pytest.compat.get_real_func. Thanks `@RonnyPfannschmidt`_ for the Report and PR +* Modify ``pytest_make_parametrize_id()`` hook to accept ``argname`` as an + additional parameter. + Thanks `@unsignedint`_ for the PR. + .. _@davidszotten: https://github.com/davidszotten .. _@fushi: https://github.com/fushi @@ -52,6 +56,7 @@ Changes .. _@fogo: https://github.com/fogo .. _@lesteve: https://github.com/lesteve .. _@mandeep: https://github.com/mandeep +.. _@unsignedint: https://github.com/unsignedint .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 @@ -79,15 +84,10 @@ Changes subdirectories with ini configuration files now uses the correct ini file (`#2148`_). Thanks `@pelme`_. -* Modify ``pytest_make_parametrize_id()`` hook to accept ``argname`` as an - additional parameter. - Thanks `@unsignedint`_ for the PR. - * .. _@malinoff: https://github.com/malinoff .. _@pelme: https://github.com/pelme -.. _@unsignedint: https://github.com/unsignedint .. _#2129: https://github.com/pytest-dev/pytest/issues/2129 .. _#2148: https://github.com/pytest-dev/pytest/issues/2148 diff --git a/_pytest/hookspec.py b/_pytest/hookspec.py index 989cb0c0b..bb382a597 100644 --- a/_pytest/hookspec.py +++ b/_pytest/hookspec.py @@ -157,7 +157,7 @@ def pytest_generate_tests(metafunc): """ generate (multiple) parametrized calls to a test function.""" @hookspec(firstresult=True) -def pytest_make_parametrize_id(config, val, argname=None): +def pytest_make_parametrize_id(config, val, argname): """Return a user-friendly string representation of the given ``val`` that will be used by @pytest.mark.parametrize calls. Return None if the hook doesn't know about ``val``. The parameter name is available as ``argname``, if required. diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 9eea699bf..372794a65 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1465,16 +1465,16 @@ class TestMarkersWithParametrization: import pytest @pytest.mark.parametrize("x", range(2)) - def test_func(x): + def test_func_a(x): pass @pytest.mark.parametrize("y", [1]) - def test_func2(y): + def test_func_b(y): pass """) result = testdir.runpytest("-v") result.stdout.fnmatch_lines([ - "*test_func*0*PASS*", - "*test_func*2*PASS*", - "*test_func2*10*PASS*", + "*test_func_a*0*PASS*", + "*test_func_a*2*PASS*", + "*test_func_b*10*PASS*", ]) From 403122281a3a7157e68db27e4778efb5bf848afb Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sun, 22 Jan 2017 11:48:05 +0100 Subject: [PATCH 088/106] fix devpi test for doctesting env due to a devpi bug, we always get a sdist install which in turn triggers the pytest issue #2042 / #726 going for pyargs and a changed folder, it should no longer happen (and will be tested firther after rebasing the release branch) --- tox.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index a5dec3fdc..4be692fc7 100644 --- a/tox.ini +++ b/tox.ini @@ -118,11 +118,13 @@ commands= basepython = python usedevelop=True skipsdist=True +# ensure the given pyargs cant mean anytrhing else +changedir=doc/ deps= PyYAML commands= - pytest -rfsxX doc/en - pytest --doctest-modules {toxinidir}/_pytest + pytest -rfsxX en + pytest --doctest-modules --pyargs _pytest [testenv:regen] changedir=doc/en From 55f21bd2b9f07c55072c1017637587b2fd3bd24e Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 17:55:16 +0100 Subject: [PATCH 089/106] bump version --- CHANGELOG.rst | 4 +--- _pytest/__init__.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6c1161ba7..bf297971d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,11 +1,10 @@ -3.0.6.dev0 (unreleased) +3.0.6 (2017-01-29) ======================= * pytest no longer generates ``PendingDeprecationWarning`` from its own operations, which was introduced by mistake in version ``3.0.5`` (`#2118`_). Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. - * pytest no longer recognizes coroutine functions as yield tests (`#2129`_). Thanks to `@malinoff`_ for the PR. @@ -30,7 +29,6 @@ * Fail ``testdir.runpytest().assert_outcomes()`` explicitly if the pytest terminal output it relies on is missing. Thanks to `@eli-b`_ for the PR. -* .. _@lesteve: https://github.com/lesteve .. _@malinoff: https://github.com/malinoff diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 8546ff02b..a4739a613 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.6.dev0' +__version__ = '3.0.6' From 4d0c635252273fa95f9b7aaa70506a1e8f727c8e Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 17:55:35 +0100 Subject: [PATCH 090/106] regendoc --- 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 | 34 +++++++++--------- doc/en/example/nonpython.rst | 54 ++++++++++++++--------------- doc/en/example/parametrize.rst | 20 ++++++----- 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 | 2 +- doc/en/parametrize.rst | 4 +-- doc/en/skipping.rst | 2 +- doc/en/tmpdir.rst | 2 +- doc/en/unittest.rst | 2 +- 17 files changed, 91 insertions(+), 89 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index b682897e1..d93da178d 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/cache.rst b/doc/en/cache.rst index b1a7b3796..3b4703bf5 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 7ee73b992..201006637 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items diff --git a/doc/en/doctest.rst b/doc/en/doctest.rst index 513d9aed9..4cbf92b13 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 b0825ce6e..afa66960b 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items @@ -205,7 +205,7 @@ You can ask which markers exist for your test suite - the list includes our just @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. @@ -352,7 +352,7 @@ the test needs:: $ pytest -E stage2 ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -381,7 +381,7 @@ The ``--markers`` option always gives you a list of available markers:: @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. @@ -485,7 +485,7 @@ then you will see two tests 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items @@ -499,11 +499,11 @@ Note that if you specify a platform via the marker-command line option like this $ pytest -m linux ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 4 items - test_plat.py s + test_plat.py . ======= 3 tests deselected ======== ======= 1 passed, 3 deselected in 0.12 seconds ======== @@ -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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 817e5693f..09daa3808 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -27,18 +27,17 @@ now execute the test specification:: nonpython $ pytest test_simple.yml ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collected 2 items + collected 0 items / 1 errors - test_simple.yml F. - - ======= FAILURES ======== - _______ usecase: hello ________ - usecase execution failed - spec failed: 'some': 'other' - no further details known at this point. - ======= 1 failed, 1 passed in 0.12 seconds ======== + ======= ERRORS ======== + _______ ERROR collecting test_simple.yml ________ + conftest.py:11: in collect + import yaml # we need a yaml parser, e.g. PyYAML + E ImportError: No module named 'yaml' + !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! + ======= 1 error in 0.12 seconds ======== .. regendoc:wipe @@ -59,20 +58,18 @@ consulted when reporting in ``verbose`` mode:: nonpython $ pytest -v ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m cachedir: .cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collecting ... collected 2 items + collecting ... collected 0 items / 1 errors - test_simple.yml::hello FAILED - test_simple.yml::ok PASSED - - ======= FAILURES ======== - _______ usecase: hello ________ - usecase execution failed - spec failed: 'some': 'other' - no further details known at this point. - ======= 1 failed, 1 passed in 0.12 seconds ======== + ======= ERRORS ======== + _______ ERROR collecting test_simple.yml ________ + conftest.py:11: in collect + import yaml # we need a yaml parser, e.g. PyYAML + E ImportError: No module named 'yaml' + !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! + ======= 1 error in 0.12 seconds ======== .. regendoc:wipe @@ -81,11 +78,14 @@ interesting to just look at the collection tree:: nonpython $ pytest --collect-only ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collected 2 items - - - + collected 0 items / 1 errors - ======= no tests ran in 0.12 seconds ======== + ======= ERRORS ======== + _______ ERROR collecting test_simple.yml ________ + conftest.py:11: in collect + import yaml # we need a yaml parser, e.g. PyYAML + E ImportError: No module named 'yaml' + !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! + ======= 1 error in 0.12 seconds ======== diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index dac070c84..cd1b05b86 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items @@ -397,10 +397,12 @@ is to be run with different sets of arguments for its three arguments: Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize):: . $ pytest -rs -q multipython.py - sssssssssssssss.........sss.........sss......... + sssssssssssssssssssssssssssssssssssssssssssss... ======= short test summary info ======== - SKIP [21] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.6' not found - 27 passed, 21 skipped in 0.12 seconds + SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python3.4' not found + SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.6' not found + SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.7' not found + 3 passed, 45 skipped in 0.12 seconds Indirect parametrization of optional implementations/imports -------------------------------------------------------------------- @@ -447,7 +449,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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 7dc531100..0d53b0593 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 0817458ad..c586bc250 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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:1207>:1: ValueError + <0-codegen /home/ronny/Projects/pytest-dev/pytest/_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 623ff33cc..d4b3fba43 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 201ad4863..0a9000611 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -520,7 +520,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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 11 items @@ -573,7 +573,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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -642,7 +642,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.5, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m 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 e398e4db5..f19f4d0c0 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.5, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py + This is pytest version 3.0.6, imported from /home/ronny/Projects/pytest-dev/pytest/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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/index.rst b/doc/en/index.rst index ce1618e66..32671ddb2 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -25,7 +25,7 @@ To execute it:: $ pytest ======= test session starts ======== - platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index 052d0e72e..a3499ea3b 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 3 items diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index b142738c9..0a2e18208 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, 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 56e4190c5..7a23c84de 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 179347eb9..430d5ca55 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.5, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items From 01eaf9db51bc1d7982eb5414902799c365a6909d Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 18:03:06 +0100 Subject: [PATCH 091/106] fix the xfail docstring typo at the actual docstring + regendoc --- _pytest/skipping.py | 2 +- doc/en/example/markers.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index a8eaea98a..91a34169f 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -46,7 +46,7 @@ def pytest_configure(config): ) config.addinivalue_line("markers", "xfail(condition, reason=None, run=True, raises=None, strict=False): " - "mark the the test function as an expected failure if eval(condition) " + "mark the test function as an expected failure if eval(condition) " "has a True value. Optionally specify a reason for better reporting " "and run=False if you don't even want to execute the test function. " "If only specific exception(s) are expected, you can list them in " diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index afa66960b..7dd5c8359 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -205,7 +205,7 @@ You can ask which markers exist for your test suite - the list includes our just @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. @@ -381,7 +381,7 @@ The ``--markers`` option always gives you a list of available markers:: @pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html - @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html + @pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html @pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples. From 34b898b47e322afc564906574aa9f3bf0956262b Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 18:06:28 +0100 Subject: [PATCH 092/106] generate the release announcement --- doc/en/announce/index.rst | 1 + doc/en/announce/release-3.0.6.rst | 33 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 doc/en/announce/release-3.0.6.rst diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 44b29cae1..5cf8b4dcb 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.0.6 release-3.0.5 release-3.0.4 release-3.0.3 diff --git a/doc/en/announce/release-3.0.6.rst b/doc/en/announce/release-3.0.6.rst new file mode 100644 index 000000000..81b893141 --- /dev/null +++ b/doc/en/announce/release-3.0.6.rst @@ -0,0 +1,33 @@ +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 full changelog is available at http://doc.pytest.org/en/latest/changelog.html. + + +Thanks to all who contributed to this release, among them: + +* Andreas Pelme +* Bruno Oliveira +* Dmitry Malinovsky +* Eli Boyarski +* Jakub Wilk +* Jeff Widman +* Loïc Estève +* Luke Murphy +* Miro Hrončok +* Oscar Hellström +* Peter Heatwole +* Philippe Ombredanne +* Ronny Pfannschmidt +* Rutger Prins +* Stefan Scherfke + + +Happy testing, +The pytest Development Team From 449b88c6407f3da139f2b02a3263ac5166af312e Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 18:17:27 +0100 Subject: [PATCH 093/106] rerun regendoc with correct install --- doc/en/example/nonpython.rst | 48 ++++++++++++++++---------------- doc/en/example/parametrize.rst | 2 +- doc/en/example/reportingdemo.rst | 2 +- doc/en/getting-started.rst | 2 +- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index 09daa3808..6510c861c 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -29,15 +29,16 @@ now execute the test specification:: ======= test session starts ======== platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collected 0 items / 1 errors + collected 2 items - ======= ERRORS ======== - _______ ERROR collecting test_simple.yml ________ - conftest.py:11: in collect - import yaml # we need a yaml parser, e.g. PyYAML - E ImportError: No module named 'yaml' - !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! - ======= 1 error in 0.12 seconds ======== + test_simple.yml F. + + ======= FAILURES ======== + _______ usecase: hello ________ + usecase execution failed + spec failed: 'some': 'other' + no further details known at this point. + ======= 1 failed, 1 passed in 0.12 seconds ======== .. regendoc:wipe @@ -61,15 +62,17 @@ consulted when reporting in ``verbose`` mode:: platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5m cachedir: .cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collecting ... collected 0 items / 1 errors + collecting ... collected 2 items - ======= ERRORS ======== - _______ ERROR collecting test_simple.yml ________ - conftest.py:11: in collect - import yaml # we need a yaml parser, e.g. PyYAML - E ImportError: No module named 'yaml' - !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! - ======= 1 error in 0.12 seconds ======== + test_simple.yml::hello FAILED + test_simple.yml::ok PASSED + + ======= FAILURES ======== + _______ usecase: hello ________ + usecase execution failed + spec failed: 'some': 'other' + no further details known at this point. + ======= 1 failed, 1 passed in 0.12 seconds ======== .. regendoc:wipe @@ -80,12 +83,9 @@ interesting to just look at the collection tree:: ======= test session starts ======== platform linux -- Python 3.5.2, pytest-3.0.6, py-1.4.33, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR/nonpython, inifile: - collected 0 items / 1 errors + collected 2 items + + + - ======= ERRORS ======== - _______ ERROR collecting test_simple.yml ________ - conftest.py:11: in collect - import yaml # we need a yaml parser, e.g. PyYAML - E ImportError: No module named 'yaml' - !!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!! - ======= 1 error in 0.12 seconds ======== + ======= no tests ran in 0.12 seconds ======== diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index cd1b05b86..609158590 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -399,8 +399,8 @@ Running it results in some skips if we don't have all the python interpreters in . $ pytest -rs -q multipython.py sssssssssssssssssssssssssssssssssssssssssssss... ======= short test summary info ======== - SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python3.4' not found SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.6' not found + SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python3.4' not found SKIP [15] $REGENDOC_TMPDIR/CWD/multipython.py:23: 'python2.7' not found 3 passed, 45 skipped in 0.12 seconds diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index c586bc250..141208321 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -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 /home/ronny/Projects/pytest-dev/pytest/_pytest/python.py:1207>: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/getting-started.rst b/doc/en/getting-started.rst index f19f4d0c0..557e8245d 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.6, imported from /home/ronny/Projects/pytest-dev/pytest/pytest.py + This is pytest version 3.0.6, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py .. _`simpletest`: From 22da561ae5bcfe57f78889153d3fa3057b56204a Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 20 Jan 2017 21:56:08 +0100 Subject: [PATCH 094/106] fix copy+paste error, its supposed to be 3.0.6 --- doc/en/announce/release-3.0.6.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/announce/release-3.0.6.rst b/doc/en/announce/release-3.0.6.rst index 81b893141..2988b9cb3 100644 --- a/doc/en/announce/release-3.0.6.rst +++ b/doc/en/announce/release-3.0.6.rst @@ -1,7 +1,7 @@ -pytest-3.0.5 +pytest-3.0.6 ============ -pytest 3.0.5 has just been released to PyPI. +pytest 3.0.6 has just been released to PyPI. This is a bug-fix release, being a drop-in replacement. To upgrade:: From 0e64cd045c8477cc81014490ed5e38e5b690a1ea Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sun, 22 Jan 2017 22:14:54 +0100 Subject: [PATCH 095/106] take off author_email after pypi rejects --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index f03ab9c40..d602b7979 100644 --- a/setup.py +++ b/setup.py @@ -68,7 +68,6 @@ def main(): license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], author='Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others', - author_email='holger at merlinux.eu', entry_points={'console_scripts': ['pytest=pytest:main', 'py.test=pytest:main']}, classifiers=classifiers, From c9f327dc876d190c0e4fed6e7a1b24fdc5b63a89 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sun, 22 Jan 2017 22:21:08 +0100 Subject: [PATCH 096/106] bump version to next dev --- CHANGELOG.rst | 12 ++++++++++++ _pytest/__init__.py | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bf297971d..223e96f9e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,15 @@ +3.0.7 (unreleased) +======================= + +* + +* + +* + +* + + 3.0.6 (2017-01-29) ======================= diff --git a/_pytest/__init__.py b/_pytest/__init__.py index a4739a613..16616ffb0 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.6' +__version__ = '3.0.7.dev0' From 839aa963a12c38e258c2e7e8d0068d639110f3e7 Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sun, 22 Jan 2017 16:34:51 -0700 Subject: [PATCH 097/106] Add py36 identifier and order AUTHORS --- AUTHORS | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index acf715cde..c2400f508 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,6 +48,7 @@ Duncan Betts Edison Gustavo Muenz Edoardo Batini Eduardo Schettino +Eli Boyarski Elizaveta Shashkova Endre Galaczi Eric Hunsberger @@ -139,6 +140,6 @@ Tom Viner Trevor Bekolay Tyler Goodlet Vasily Kuznetsov +Victor Uriarte Wouter van Ackooy Xuecong Liao -Eli Boyarski diff --git a/setup.py b/setup.py index d602b7979..1d0630cd2 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ classifiers = ['Development Status :: 6 - Mature', 'Topic :: Software Development :: Libraries', 'Topic :: Utilities'] + [ ('Programming Language :: Python :: %s' % x) for x in - '2 2.6 2.7 3 3.3 3.4 3.5'.split()] + '2 2.6 2.7 3 3.3 3.4 3.5 3.6'.split()] with open('README.rst') as fd: long_description = fd.read() From 902fd2ff6a4b5081cf2efea810e080d0cf893f7d Mon Sep 17 00:00:00 2001 From: Victor Uriarte Date: Sun, 22 Jan 2017 17:20:15 -0700 Subject: [PATCH 098/106] Add py37-nightly to travis --- .travis.yml | 2 ++ tox.ini | 1 + 2 files changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index b2d356e19..f701302d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,6 +32,8 @@ matrix: include: - env: TESTENV=py36 python: '3.6-dev' + - env: TESTENV=py37 + python: 'nightly' script: tox --recreate -e $TESTENV diff --git a/tox.ini b/tox.ini index 4be692fc7..e57fabd4b 100644 --- a/tox.ini +++ b/tox.ini @@ -10,6 +10,7 @@ envlist= py34 py35 py36 + py37 pypy {py27,py35}-{pexpect,xdist,trial} py27-nobyte From beb77c1a381ed559e67711bae14cb8528dab13bf Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 23 Jan 2017 13:51:12 -0200 Subject: [PATCH 099/106] Fix release date for 3.0.6 --- CHANGELOG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 223e96f9e..006c0ed0f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,8 +10,8 @@ * -3.0.6 (2017-01-29) -======================= +3.0.6 (2017-01-22) +================== * pytest no longer generates ``PendingDeprecationWarning`` from its own operations, which was introduced by mistake in version ``3.0.5`` (`#2118`_). Thanks to `@nicoddemus`_ for the report and `@RonnyPfannschmidt`_ for the PR. From d98d122e81324f22938a5791860820be993a29f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 25 Jan 2017 14:20:38 +0200 Subject: [PATCH 100/106] Discourage users from using this all the time. --- doc/en/unittest.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 430d5ca55..43b6526c7 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -17,6 +17,14 @@ run using ``pytest``. We assume here that you are familiar with writing ``unittest.TestCase`` style tests and rather focus on integration aspects. +Note that this is meant as a provisional way of running your test code +until you fully convert to pytest-style tests. To fully take advantage of +:ref:`fixtures `, :ref:`parametrization ` and +:ref:`hooks ` you should convert (tools like `unittest2pytest +`__ are helpful). +Also, not all 3rd party pluging are expected to work best with +``unittest.TestCase`` style tests. + Usage ------------------------------------------------------------------- @@ -191,12 +199,3 @@ was executed ahead of the ``test_method``. pytest fixtures into unittest suites. And of course you can also start to selectively leave away the ``unittest.TestCase`` subclassing, use plain asserts and get the unlimited pytest feature set. - - -Converting from unittest to pytest ---------------------------------------- - -If you want to convert your unittest testcases to pytest, there are -some helpers like `unittest2pytest -`__, which uses lib2to3 -and introspection for the transformation. From c8032a9bbb18cdbcf7d01303a2a846fbc048b76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionel=20Cristian=20M=C4=83rie=C8=99?= Date: Wed, 25 Jan 2017 14:44:07 +0200 Subject: [PATCH 101/106] Fix reference. --- doc/en/unittest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 43b6526c7..1bee0e146 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -20,7 +20,7 @@ integration aspects. Note that this is meant as a provisional way of running your test code until you fully convert to pytest-style tests. To fully take advantage of :ref:`fixtures `, :ref:`parametrization ` and -:ref:`hooks ` you should convert (tools like `unittest2pytest +:ref:`hooks ` you should convert (tools like `unittest2pytest `__ are helpful). Also, not all 3rd party pluging are expected to work best with ``unittest.TestCase`` style tests. From 3f30c228944f1a7ee93c80162954ca7fdc3dd896 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 26 Jan 2017 13:03:29 +0100 Subject: [PATCH 102/106] fix changelog merge mistake --- CHANGELOG.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5e5af8a2c..c8582f40a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -46,7 +46,6 @@ Changes .. _@mattduck: https://github.com/mattduck .. _@wheerd: https://github.com/wheerd .. _@fogo: https://github.com/fogo -.. _@lesteve: https://github.com/lesteve .. _@mandeep: https://github.com/mandeep .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 From 43662ce789cdc87c478ff3c1a8314c7b51efa3bc Mon Sep 17 00:00:00 2001 From: Thomas Kriechbaumer Date: Wed, 1 Feb 2017 13:37:13 +0100 Subject: [PATCH 103/106] allow error message matching in pytest.raises --- CHANGELOG.rst | 4 ++++ _pytest/python.py | 24 ++++++++++++++++++++---- testing/python/raises.py | 15 +++++++++++++++ testing/test_recwarn.py | 3 +-- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fbbefc1e6..816d3eb5b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,9 @@ New Features * ``pytest.warns`` now checks for subclass relationship rather than class equality. Thanks `@lesteve`_ for the PR (`#2166`_) +* ``pytest.raises`` now asserts that the error message matches a text or regex + with the ``match`` keyword argument. Thanks `@Kriechi`_ for the PR. + Changes ------- @@ -56,6 +59,7 @@ Changes .. _@fogo: https://github.com/fogo .. _@mandeep: https://github.com/mandeep .. _@unsignedint: https://github.com/unsignedint +.. _@Kriechi: https://github.com/Kriechi .. _#1512: https://github.com/pytest-dev/pytest/issues/1512 .. _#1874: https://github.com/pytest-dev/pytest/pull/1874 diff --git a/_pytest/python.py b/_pytest/python.py index 18da7ac23..ff4edff5b 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1134,7 +1134,7 @@ def raises(expected_exception, *args, **kwargs): >>> with raises(ValueError) as exc_info: ... if value > 10: ... raise ValueError("value must be <= 10") - ... assert str(exc_info.value) == "value must be <= 10" # this will not execute + ... assert exc_info.type == ValueError # this will not execute Instead, the following approach must be taken (note the difference in scope):: @@ -1143,7 +1143,16 @@ def raises(expected_exception, *args, **kwargs): ... if value > 10: ... raise ValueError("value must be <= 10") ... - >>> assert str(exc_info.value) == "value must be <= 10" + >>> assert exc_info.type == ValueError + + Or you can use the keyword argument ``match`` to assert that the + exception matches a text or regex:: + + >>> with raises(ValueError, match='must be 0 or None'): + ... raise ValueError("value must be 0 or None") + + >>> with raises(ValueError, match=r'must be \d+$'): + ... raise ValueError("value must be 42") Or you can specify a callable by passing a to-be-called lambda:: @@ -1194,11 +1203,15 @@ def raises(expected_exception, *args, **kwargs): raise TypeError(msg % type(expected_exception)) message = "DID NOT RAISE {0}".format(expected_exception) + match_expr = None if not args: if "message" in kwargs: message = kwargs.pop("message") - return RaisesContext(expected_exception, message) + if "match" in kwargs: + match_expr = kwargs.pop("match") + message += " matching '{0}'".format(match_expr) + return RaisesContext(expected_exception, message, match_expr) elif isinstance(args[0], str): code, = args assert isinstance(code, str) @@ -1222,9 +1235,10 @@ def raises(expected_exception, *args, **kwargs): pytest.fail(message) class RaisesContext(object): - def __init__(self, expected_exception, message): + def __init__(self, expected_exception, message, match_expr): self.expected_exception = expected_exception self.message = message + self.match_expr = match_expr self.excinfo = None def __enter__(self): @@ -1246,6 +1260,8 @@ class RaisesContext(object): suppress_exception = issubclass(self.excinfo.type, self.expected_exception) if sys.version_info[0] == 2 and suppress_exception: sys.exc_clear() + if self.match_expr: + self.excinfo.match(self.match_expr) return suppress_exception diff --git a/testing/python/raises.py b/testing/python/raises.py index 08edd5c6a..58d6db244 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -118,3 +118,18 @@ class TestRaises: for o in gc.get_objects(): assert type(o) is not T + + def test_raises_match(self): + msg = r"with base \d+" + with pytest.raises(ValueError, match=msg): + int('asdf') + + msg = "with base 10" + with pytest.raises(ValueError, match=msg): + int('asdf') + + msg = "with base 16" + expr = r"Pattern '{}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg) + with pytest.raises(AssertionError, match=expr): + with pytest.raises(ValueError, match=msg): + int('asdf', base=10) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 40d11cd04..231ef028e 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -112,10 +112,9 @@ class TestDeprecatedCall(object): pytest.deprecated_call(self.dep_explicit, 0) def test_deprecated_call_as_context_manager_no_warning(self): - with pytest.raises(pytest.fail.Exception) as ex: + with pytest.raises(pytest.fail.Exception, matches='^DID NOT WARN'): with pytest.deprecated_call(): self.dep(1) - assert str(ex.value).startswith("DID NOT WARN") def test_deprecated_call_as_context_manager(self): with pytest.deprecated_call(): From abbff681babdfc788871b77cc7126bf0a63e9f6b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 2 Feb 2017 18:01:44 -0200 Subject: [PATCH 104/106] Fix '{0}' format for py26 --- testing/python/raises.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/python/raises.py b/testing/python/raises.py index 58d6db244..8170ec793 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -129,7 +129,7 @@ class TestRaises: int('asdf') msg = "with base 16" - expr = r"Pattern '{}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg) + expr = r"Pattern '{0}' not found in 'invalid literal for int\(\) with base 10: 'asdf''".format(msg) with pytest.raises(AssertionError, match=expr): with pytest.raises(ValueError, match=msg): int('asdf', base=10) From 91c6bef77a674d5cd79af464e5c19745427b5510 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 15 Feb 2017 14:55:12 +0100 Subject: [PATCH 105/106] Add venv to the default norecursedirs venv (without a dot) is commonly used as a name for a virtualenv directory, and we don't want to collect that. --- CHANGELOG.rst | 3 +++ _pytest/main.py | 2 +- doc/en/customize.rst | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 816d3eb5b..4abc183d0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -51,6 +51,9 @@ Changes additional parameter. Thanks `@unsignedint`_ for the PR. +* Add ``venv`` to the default ``norecursedirs`` setting. + Thanks `@The-Compiler`_ for the PR. + .. _@davidszotten: https://github.com/davidszotten .. _@fushi: https://github.com/fushi diff --git a/_pytest/main.py b/_pytest/main.py index 41a48cda2..73858e099 100644 --- a/_pytest/main.py +++ b/_pytest/main.py @@ -27,7 +27,7 @@ EXIT_NOTESTSCOLLECTED = 5 def pytest_addoption(parser): parser.addini("norecursedirs", "directory patterns to avoid for recursion", - type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg']) + type="args", default=['.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv']) parser.addini("testpaths", "directories to search for tests when no files or directories are given in the command line.", type="args", default=[]) #parser.addini("dirpatterns", diff --git a/doc/en/customize.rst b/doc/en/customize.rst index d12a49037..c6d3eb473 100644 --- a/doc/en/customize.rst +++ b/doc/en/customize.rst @@ -158,7 +158,7 @@ Builtin configuration file options [seq] matches any character in seq [!seq] matches any char not in seq - Default patterns are ``'.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg'``. + Default patterns are ``'.*', 'build', 'dist', 'CVS', '_darcs', '{arch}', '*.egg', 'venv'``. Setting a ``norecursedirs`` replaces the default. Here is an example of how to avoid certain directories: From fb0b90646ec86ced32d146ee42e25f4cd72d2229 Mon Sep 17 00:00:00 2001 From: Michal Wajszczuk Date: Thu, 16 Feb 2017 19:41:51 +0100 Subject: [PATCH 106/106] New-style classes implemented for python 2.7 - #2147 --- AUTHORS | 1 + CHANGELOG.rst | 3 +- _pytest/vendored_packages/pluggy.py | 12 +-- doc/en/assert.rst | 2 +- doc/en/example/assertion/failure_demo.py | 12 +-- .../assertion/test_setup_flow_example.py | 2 +- doc/en/example/attic.rst | 4 +- doc/en/example/costlysetup/conftest.py | 2 +- doc/en/example/markers.rst | 10 +- doc/en/example/multipython.py | 2 +- doc/en/example/parametrize.rst | 8 +- doc/en/example/pythoncollection.py | 2 +- doc/en/example/pythoncollection.rst | 2 +- doc/en/example/reportingdemo.rst | 6 +- doc/en/example/simple.rst | 4 +- doc/en/example/special.rst | 4 +- doc/en/fixture.rst | 10 +- doc/en/funcarg_compare.rst | 2 +- doc/en/genapi.py | 2 +- doc/en/getting-started.rst | 2 +- doc/en/skipping.rst | 2 +- doc/en/test/attic.rst | 2 +- doc/en/unittest.rst | 2 +- doc/en/usage.rst | 4 +- testing/acceptance_test.py | 10 +- testing/code/test_code.py | 6 +- testing/code/test_excinfo.py | 8 +- testing/code/test_source.py | 22 ++--- testing/deprecated_test.py | 2 +- testing/python/approx.py | 2 +- testing/python/collect.py | 48 ++++----- testing/python/fixture.py | 98 +++++++++---------- testing/python/integration.py | 18 ++-- testing/python/metafunc.py | 32 +++--- testing/python/raises.py | 4 +- testing/test_argcomplete.py | 2 +- testing/test_assertion.py | 16 +-- testing/test_assertrewrite.py | 10 +- testing/test_cache.py | 4 +- testing/test_capture.py | 16 +-- testing/test_collection.py | 38 +++---- testing/test_config.py | 32 +++--- testing/test_conftest.py | 8 +- testing/test_doctest.py | 18 ++-- testing/test_junitxml.py | 12 +-- testing/test_mark.py | 30 +++--- testing/test_monkeypatch.py | 8 +- testing/test_nose.py | 10 +- testing/test_parseopt.py | 4 +- testing/test_pastebin.py | 6 +- testing/test_pdb.py | 6 +- testing/test_pluginmanager.py | 20 ++-- testing/test_pytester.py | 6 +- testing/test_resultlog.py | 2 +- testing/test_runner.py | 18 ++-- testing/test_runner_xunit.py | 16 +-- testing/test_session.py | 12 +-- testing/test_skipping.py | 20 ++-- testing/test_terminal.py | 26 ++--- testing/test_tmpdir.py | 4 +- testing/test_unittest.py | 4 +- 61 files changed, 351 insertions(+), 349 deletions(-) diff --git a/AUTHORS b/AUTHORS index 43c7d3156..e9e7f7c82 100644 --- a/AUTHORS +++ b/AUTHORS @@ -108,6 +108,7 @@ Michael Aquilina Michael Birtwell Michael Droettboom Michael Seifert +Michal Wajszczuk Mike Lundy Ned Batchelder Neven Mundar diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4abc183d0..23b87b18c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -21,7 +21,7 @@ Changes ------- * Old-style classes have been changed to new-style classes in order to improve - compatability with Python 2. Thanks to `@mandeep`_ for the PR (`#2147`_). + compatibility with Python 2. Thanks to `@MichalTHEDUDE`_ and `@mandeep`_ for the PR (`#2147`_). * It is now possible to skip test classes from being collected by setting a ``__test__`` attribute to ``False`` in the class body (`#2007`_). Thanks @@ -61,6 +61,7 @@ Changes .. _@wheerd: https://github.com/wheerd .. _@fogo: https://github.com/fogo .. _@mandeep: https://github.com/mandeep +.. _@MichalTHEDUDE: https://github.com/MichalTHEDUDE .. _@unsignedint: https://github.com/unsignedint .. _@Kriechi: https://github.com/Kriechi diff --git a/_pytest/vendored_packages/pluggy.py b/_pytest/vendored_packages/pluggy.py index a300053a1..11658c3b1 100644 --- a/_pytest/vendored_packages/pluggy.py +++ b/_pytest/vendored_packages/pluggy.py @@ -167,7 +167,7 @@ def normalize_hookimpl_opts(opts): opts.setdefault("optionalhook", False) -class _TagTracer: +class _TagTracer(object): def __init__(self): self._tag2proc = {} self.writer = None @@ -214,7 +214,7 @@ class _TagTracer: self._tag2proc[tags] = processor -class _TagTracerSub: +class _TagTracerSub(object): def __init__(self, root, tags): self.root = root self.tags = tags @@ -254,7 +254,7 @@ def _wrapped_call(wrap_controller, func): return call_outcome.get_result() -class _CallOutcome: +class _CallOutcome(object): """ Outcome of a function call, either an exception or a proper result. Calling the ``get_result`` method will return the result or reraise the exception raised when the function was called. """ @@ -286,7 +286,7 @@ def _reraise(cls, val, tb): """) -class _TracedHookExecution: +class _TracedHookExecution(object): def __init__(self, pluginmanager, before, after): self.pluginmanager = pluginmanager self.before = before @@ -580,7 +580,7 @@ class PluginManager(object): return orig -class _MultiCall: +class _MultiCall(object): """ execute a call into multiple python functions/methods. """ # XXX note that the __multicall__ argument is supported only @@ -673,7 +673,7 @@ def varnames(func, startindex=None): return x -class _HookRelay: +class _HookRelay(object): """ hook holder object for performing 1:N hook calls where N is the number of registered plugins. diff --git a/doc/en/assert.rst b/doc/en/assert.rst index d93da178d..5ec07a78e 100644 --- a/doc/en/assert.rst +++ b/doc/en/assert.rst @@ -223,7 +223,7 @@ provides an alternative explanation for ``Foo`` objects:: now, given this test module:: # content of test_foocompare.py - class Foo: + class Foo(object): def __init__(self, val): self.val = val diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index a4ff758b1..d31fba2ad 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -128,7 +128,7 @@ def test_attribute_multiple(): def globf(x): return x+1 -class TestRaises: +class TestRaises(object): def test_raises(self): s = 'qwe' raises(TypeError, "int(s)") @@ -167,7 +167,7 @@ def test_dynamic_compile_shows_nicely(): -class TestMoreErrors: +class TestMoreErrors(object): def test_complex_error(self): def f(): return 44 @@ -213,23 +213,23 @@ class TestMoreErrors: x = 0 -class TestCustomAssertMsg: +class TestCustomAssertMsg(object): def test_single_line(self): - class A: + class A(object): a = 1 b = 2 assert A.a == b, "A.a appears not to be b" def test_multiline(self): - class A: + class A(object): a = 1 b = 2 assert A.a == b, "A.a appears not to be b\n" \ "or does not appear to be b\none of those" def test_custom_repr(self): - class JSON: + class JSON(object): a = 1 def __repr__(self): return "This is JSON\n{\n 'foo': 'bar'\n}" diff --git a/doc/en/example/assertion/test_setup_flow_example.py b/doc/en/example/assertion/test_setup_flow_example.py index 512330cb4..100effa49 100644 --- a/doc/en/example/assertion/test_setup_flow_example.py +++ b/doc/en/example/assertion/test_setup_flow_example.py @@ -1,7 +1,7 @@ def setup_module(module): module.TestStateFullThing.classcount = 0 -class TestStateFullThing: +class TestStateFullThing(object): def setup_class(cls): cls.classcount += 1 diff --git a/doc/en/example/attic.rst b/doc/en/example/attic.rst index 1bc32b283..6004ebb8f 100644 --- a/doc/en/example/attic.rst +++ b/doc/en/example/attic.rst @@ -15,7 +15,7 @@ example: specifying and selecting acceptance tests def pytest_funcarg__accept(request): return AcceptFixture(request) - class AcceptFixture: + class AcceptFixture(object): def __init__(self, request): if not request.config.option.acceptance: pytest.skip("specify -A to run acceptance tests") @@ -61,7 +61,7 @@ extend the `accept example`_ by putting this in our test module: arg.tmpdir.mkdir("special") return arg - class TestSpecialAcceptance: + class TestSpecialAcceptance(object): def test_sometest(self, accept): assert accept.tmpdir.join("special").check() diff --git a/doc/en/example/costlysetup/conftest.py b/doc/en/example/costlysetup/conftest.py index c8b9a257e..ea3c1cffb 100644 --- a/doc/en/example/costlysetup/conftest.py +++ b/doc/en/example/costlysetup/conftest.py @@ -7,7 +7,7 @@ def setup(request): yield setup setup.finalize() -class CostlySetup: +class CostlySetup(object): def __init__(self): import time print ("performing costly setup") diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 7dd5c8359..ab5c03f17 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -21,7 +21,7 @@ You can "mark" a test function with custom metadata like this:: pass def test_another(): pass - class TestClass: + class TestClass(object): def test_method(self): pass @@ -242,7 +242,7 @@ its test methods:: # content of test_mark_classlevel.py import pytest @pytest.mark.webtest - class TestClass: + class TestClass(object): def test_startup(self): pass def test_startup_and_more(self): @@ -256,14 +256,14 @@ To remain backward-compatible with Python 2.4 you can also set a import pytest - class TestClass: + class TestClass(object): pytestmark = pytest.mark.webtest or if you need to use multiple markers you can use a list:: import pytest - class TestClass: + class TestClass(object): pytestmark = [pytest.mark.webtest, pytest.mark.slowtest] You can also set a module level marker:: @@ -407,7 +407,7 @@ code you can read over all such settings. Example:: pytestmark = pytest.mark.glob("module", x=1) @pytest.mark.glob("class", x=2) - class TestClass: + class TestClass(object): @pytest.mark.glob("function", x=3) def test_something(self): pass diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 1f5e976ef..586f44184 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -16,7 +16,7 @@ def python1(request, tmpdir): def python2(request, python1): return Python(request.param, python1.picklefile) -class Python: +class Python(object): def __init__(self, version, picklefile): self.pythonpath = py.path.local.sysfind(version) if not self.pythonpath: diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 609158590..f0572e9a1 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -168,7 +168,7 @@ only have to work a bit to construct the correct arguments for pytest's scenario1 = ('basic', {'attribute': 'value'}) scenario2 = ('advanced', {'attribute': 'value2'}) - class TestSampleWithScenarios: + class TestSampleWithScenarios(object): scenarios = [scenario1, scenario2] def test_demo1(self, attribute): @@ -241,9 +241,9 @@ creates a database object for the actual test invocations:: if 'db' in metafunc.fixturenames: metafunc.parametrize("db", ['d1', 'd2'], indirect=True) - class DB1: + class DB1(object): "one database object" - class DB2: + class DB2(object): "alternative database object" @pytest.fixture @@ -350,7 +350,7 @@ parametrizer`_ but in a lot less code:: metafunc.parametrize(argnames, [[funcargs[name] for name in argnames] for funcargs in funcarglist]) - class TestClass: + class TestClass(object): # a map specifying multiple argument sets for a test method params = { 'test_equals': [dict(a=1, b=2), dict(a=3, b=3), ], diff --git a/doc/en/example/pythoncollection.py b/doc/en/example/pythoncollection.py index 0b9e35df4..9c4bd31ce 100644 --- a/doc/en/example/pythoncollection.py +++ b/doc/en/example/pythoncollection.py @@ -4,7 +4,7 @@ def test_function(): pass -class TestClass: +class TestClass(object): def test_method(self): pass def test_anothermethod(self): diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 0d53b0593..e3ab5f0cd 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -107,7 +107,7 @@ This would make ``pytest`` look for tests in files that match the ``check_* that match ``*_check``. For example, if we have:: # content of check_myapp.py - class CheckMyApp: + class CheckMyApp(object): def simple_check(self): pass def complex_check(self): diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 141208321..44d2f15a4 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -550,7 +550,7 @@ get on the terminal - we are working on that):: self = def test_single_line(self): - class A: + class A(object): a = 1 b = 2 > assert A.a == b, "A.a appears not to be b" @@ -564,7 +564,7 @@ get on the terminal - we are working on that):: self = def test_multiline(self): - class A: + class A(object): a = 1 b = 2 > assert A.a == b, "A.a appears not to be b\n" \ @@ -581,7 +581,7 @@ get on the terminal - we are working on that):: self = def test_custom_repr(self): - class JSON: + class JSON(object): a = 1 def __repr__(self): return "This is JSON\n{\n 'foo': 'bar'\n}" diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index d4b3fba43..c4935e2c5 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -425,7 +425,7 @@ tests in a class. Here is a test module example: import pytest @pytest.mark.incremental - class TestUserHandling: + class TestUserHandling(object): def test_login(self): pass def test_modification(self): @@ -483,7 +483,7 @@ Here is an example for making a ``db`` fixture available in a directory: # content of a/conftest.py import pytest - class DB: + class DB(object): pass @pytest.fixture(scope="session") diff --git a/doc/en/example/special.rst b/doc/en/example/special.rst index fdffef089..1fc32f6c8 100644 --- a/doc/en/example/special.rst +++ b/doc/en/example/special.rst @@ -28,7 +28,7 @@ will be called ahead of running any tests:: # content of test_module.py - class TestHello: + class TestHello(object): @classmethod def callme(cls): print ("callme called!") @@ -39,7 +39,7 @@ will be called ahead of running any tests:: def test_method2(self): print ("test_method1 called") - class TestOther: + class TestOther(object): @classmethod def callme(cls): print ("callme other called") diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 0a9000611..6f88aad73 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -557,7 +557,7 @@ and instantiate an object ``app`` where we stick the already defined import pytest - class App: + class App(object): def __init__(self, smtp): self.smtp = smtp @@ -728,7 +728,7 @@ and declare its use in a test module via a ``usefixtures`` marker:: import pytest @pytest.mark.usefixtures("cleandir") - class TestDirectoryInit: + class TestDirectoryInit(object): def test_cwd_starts_empty(self): assert os.listdir(os.getcwd()) == [] with open("myfile", "w") as f: @@ -791,7 +791,7 @@ self-contained implementation of this idea:: import pytest - class DB: + class DB(object): def __init__(self): self.intransaction = [] def begin(self, name): @@ -803,7 +803,7 @@ self-contained implementation of this idea:: def db(): return DB() - class TestClass: + class TestClass(object): @pytest.fixture(autouse=True) def transact(self, request, db): db.begin(request.function.__name__) @@ -861,7 +861,7 @@ into a conftest.py file **without** using ``autouse``:: and then e.g. have a TestClass using it by declaring the need:: @pytest.mark.usefixtures("transact") - class TestClass: + class TestClass(object): def test_method1(self): ... diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 3d121b944..b857a014d 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -24,7 +24,7 @@ resources. Here is a basic example how we could implement a per-session Database object:: # content of conftest.py - class Database: + class Database(object): def __init__(self): print ("database instance created") def destroy(self): diff --git a/doc/en/genapi.py b/doc/en/genapi.py index 89ddc8731..0ede44fa2 100644 --- a/doc/en/genapi.py +++ b/doc/en/genapi.py @@ -1,7 +1,7 @@ import textwrap import inspect -class Writer: +class Writer(object): def __init__(self, clsname): self.clsname = clsname diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 557e8245d..488ac301f 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -111,7 +111,7 @@ to group tests logically, in classes and modules. Let's write a class containing two tests:: # content of test_class.py - class TestClass: + class TestClass(object): def test_one(self): x = "this" assert 'h' in x diff --git a/doc/en/skipping.rst b/doc/en/skipping.rst index 0a2e18208..cdcb56c2c 100644 --- a/doc/en/skipping.rst +++ b/doc/en/skipping.rst @@ -98,7 +98,7 @@ You can use the ``skipif`` decorator (and any other marker) on classes:: @pytest.mark.skipif(sys.platform == 'win32', reason="does not run on windows") - class TestPosixCalls: + class TestPosixCalls(object): def test_function(self): "will not be setup or run under 'win32' platform" diff --git a/doc/en/test/attic.rst b/doc/en/test/attic.rst index 11140db2c..06944661c 100644 --- a/doc/en/test/attic.rst +++ b/doc/en/test/attic.rst @@ -110,7 +110,7 @@ If you want to disable a complete test class you can set the class-level attribute ``disabled``. For example, in order to avoid running some tests on Win32:: - class TestPosixOnly: + class TestPosixOnly(object): disabled = sys.platform == 'win32' def test_xxx(self): diff --git a/doc/en/unittest.rst b/doc/en/unittest.rst index 1bee0e146..78aac427a 100644 --- a/doc/en/unittest.rst +++ b/doc/en/unittest.rst @@ -71,7 +71,7 @@ it from a unittest-style test:: @pytest.fixture(scope="class") def db_class(request): - class DummyDB: + class DummyDB(object): pass # set a class attribute on the invoking test context request.cls.db = DummyDB() diff --git a/doc/en/usage.rst b/doc/en/usage.rst index 15b3d71b0..d5d35993e 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -226,7 +226,7 @@ to all testcases you can use ``LogXML.add_global_properties`` def start_and_prepare_env(): pass - class TestMe: + class TestMe(object): def test_foo(self): assert True @@ -314,7 +314,7 @@ You can specify additional plugins to ``pytest.main``:: # content of myinvoke.py import pytest - class MyPlugin: + class MyPlugin(object): def pytest_sessionfinish(self): print("*** test run reporting finishing") diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 88e3fa449..0d3fc1016 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -8,7 +8,7 @@ import pytest from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR -class TestGeneralUsage: +class TestGeneralUsage(object): def test_config_error(self, testdir): testdir.makeconftest(""" def pytest_configure(config): @@ -410,7 +410,7 @@ class TestGeneralUsage: ]) -class TestInvocationVariants: +class TestInvocationVariants(object): def test_earlyinit(self, testdir): p = testdir.makepyfile(""" import pytest @@ -502,7 +502,7 @@ class TestInvocationVariants: out, err = capsys.readouterr() def test_invoke_plugin_api(self, testdir, capsys): - class MyPlugin: + class MyPlugin(object): def pytest_addoption(self, parser): parser.addoption("--myopt") @@ -670,7 +670,7 @@ class TestInvocationVariants: assert request.config.pluginmanager.hasplugin('python') -class TestDurations: +class TestDurations(object): source = """ import time frag = 0.002 @@ -741,7 +741,7 @@ class TestDurations: assert result.ret == 0 -class TestDurationWithFixture: +class TestDurationWithFixture(object): source = """ import time frag = 0.001 diff --git a/testing/code/test_code.py b/testing/code/test_code.py index ad9db6d2e..a1f31b4a9 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -20,7 +20,7 @@ def test_code_gives_back_name_for_not_existing_file(): assert code.fullsource is None def test_code_with_class(): - class A: + class A(object): pass pytest.raises(TypeError, "_pytest._code.Code(A)") @@ -136,7 +136,7 @@ def test_frame_getargs(): ('z', {'c': 'd'})] -class TestExceptionInfo: +class TestExceptionInfo(object): def test_bad_getsource(self): try: @@ -147,7 +147,7 @@ class TestExceptionInfo: assert exci.getrepr() -class TestTracebackEntry: +class TestTracebackEntry(object): def test_getsource(self): try: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 23b0a985e..e2354ff5d 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -25,7 +25,7 @@ else: import pytest pytest_version_info = tuple(map(int, pytest.__version__.split(".")[:3])) -class TWMock: +class TWMock(object): WRITE = object() def __init__(self): @@ -89,7 +89,7 @@ def h(): g() # -class TestTraceback_f_g_h: +class TestTraceback_f_g_h(object): def setup_method(self, method): try: h() @@ -386,7 +386,7 @@ def test_match_raises_error(testdir): "*AssertionError*Pattern*[123]*not found*", ]) -class TestFormattedExcinfo: +class TestFormattedExcinfo(object): @pytest.fixture def importasmod(self, request): @@ -472,7 +472,7 @@ raise ValueError() pr = FormattedExcinfo() class FakeCode(object): - class raw: + class raw(object): co_filename = '?' path = '?' diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 13bfccd54..c161f75f8 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -49,7 +49,7 @@ def test_source_from_function(): assert str(source).startswith('def test_source_str_function():') def test_source_from_method(): - class TestClass: + class TestClass(object): def test_method(self): pass source = _pytest._code.Source(TestClass().test_method) @@ -119,7 +119,7 @@ def test_isparseable(): assert not Source(" \nif 1:\npass").isparseable() assert not Source(chr(0)).isparseable() -class TestAccesses: +class TestAccesses(object): source = Source("""\ def f(x): pass @@ -143,7 +143,7 @@ class TestAccesses: l = [x for x in self.source] assert len(l) == 4 -class TestSourceParsingAndCompiling: +class TestSourceParsingAndCompiling(object): source = Source("""\ def f(x): assert (x == @@ -307,7 +307,7 @@ class TestSourceParsingAndCompiling: pytest.raises(SyntaxError, _pytest._code.compile, "lambda a,a: 0", mode='eval') def test_getstartingblock_singleline(): - class A: + class A(object): def __init__(self, *args): frame = sys._getframe(1) self.source = _pytest._code.Frame(frame).statement @@ -318,7 +318,7 @@ def test_getstartingblock_singleline(): assert len(l) == 1 def test_getstartingblock_multiline(): - class A: + class A(object): def __init__(self, *args): frame = sys._getframe(1) self.source = _pytest._code.Frame(frame).statement @@ -461,16 +461,16 @@ def test_getfslineno(): assert lineno == A_lineno assert getfslineno(3) == ("", -1) - class B: + class B(object): pass B.__name__ = "B2" assert getfslineno(B)[1] == -1 def test_code_of_object_instance_with_call(): - class A: + class A(object): pass pytest.raises(TypeError, lambda: _pytest._code.Source(A())) - class WithCall: + class WithCall(object): def __call__(self): pass @@ -559,7 +559,7 @@ x = 3 """) assert str(source) == "raise ValueError(\n 23\n)" -class TestTry: +class TestTry(object): pytestmark = astonly source = """\ try: @@ -586,7 +586,7 @@ else: source = getstatement(5, self.source) assert str(source) == " raise KeyError()" -class TestTryFinally: +class TestTryFinally(object): source = """\ try: raise ValueError @@ -604,7 +604,7 @@ finally: -class TestIf: +class TestIf(object): pytestmark = astonly source = """\ if 1: diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index e610458e0..6473989e6 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -48,7 +48,7 @@ def test_str_args_deprecated(tmpdir, testdir): from _pytest.main import EXIT_NOTESTSCOLLECTED warnings = [] - class Collect: + class Collect(object): def pytest_logwarning(self, message): warnings.append(message) diff --git a/testing/python/approx.py b/testing/python/approx.py index fc1cbf9ab..d7063e215 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -20,7 +20,7 @@ class MyDocTestRunner(doctest.DocTestRunner): example.source.strip(), got.strip(), example.want.strip())) -class TestApprox: +class TestApprox(object): def test_repr_string(self): # for some reason in Python 2.6 it is not displaying the tolerance representation correctly diff --git a/testing/python/collect.py b/testing/python/collect.py index 1e69f2da9..5511b3d75 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -12,7 +12,7 @@ from _pytest.main import ( ) -class TestModule: +class TestModule(object): def test_failing_import(self, testdir): modcol = testdir.getmodulecol("import alksdjalskdjalkjals") pytest.raises(Collector.CollectError, modcol.collect) @@ -105,10 +105,10 @@ class TestModule: assert name not in stdout -class TestClass: +class TestClass(object): def test_class_with_init_warning(self, testdir): testdir.makepyfile(""" - class TestClass1: + class TestClass1(object): def __init__(self): pass """) @@ -129,7 +129,7 @@ class TestClass: def test_setup_teardown_class_as_classmethod(self, testdir): testdir.makepyfile(test_mod1=""" - class TestClassMethod: + class TestClassMethod(object): @classmethod def setup_class(cls): pass @@ -167,7 +167,7 @@ class TestClass: ) -class TestGenerator: +class TestGenerator(object): def test_generative_functions(self, testdir): modcol = testdir.getmodulecol(""" def func1(arg, arg2): @@ -192,7 +192,7 @@ class TestGenerator: modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 - class TestGenMethods: + class TestGenMethods(object): def test_gen(self): yield func1, 17, 3*5 yield func1, 42, 6*7 @@ -246,7 +246,7 @@ class TestGenerator: modcol = testdir.getmodulecol(""" def func1(arg, arg2): assert arg == arg2 - class TestGenMethods: + class TestGenMethods(object): def test_gen(self): yield "m1", func1, 17, 3*5 yield "m2", func1, 42, 6*7 @@ -326,7 +326,7 @@ class TestGenerator: # has been used during collection. o = testdir.makepyfile(""" setuplist = [] - class TestClass: + class TestClass(object): def setup_method(self, func): #print "setup_method", self, func setuplist.append(self) @@ -360,7 +360,7 @@ class TestGenerator: assert not skipped and not failed -class TestFunction: +class TestFunction(object): def test_getmodulecollector(self, testdir): item = testdir.getitem("def test_func(): pass") modcol = item.getparent(pytest.Module) @@ -369,7 +369,7 @@ class TestFunction: def test_function_as_object_instance_ignored(self, testdir): testdir.makepyfile(""" - class A: + class A(object): def __call__(self, tmpdir): 0/0 @@ -420,7 +420,7 @@ class TestFunction: def test_issue213_parametrize_value_no_equal(self, testdir): testdir.makepyfile(""" import pytest - class A: + class A(object): def __eq__(self, other): raise ValueError("not possible") @pytest.mark.parametrize('arg', [A()]) @@ -551,11 +551,11 @@ class TestFunction: item = testdir.getitem("def test_func(): raise ValueError") config = item.config - class MyPlugin1: + class MyPlugin1(object): def pytest_pyfunc_call(self, pyfuncitem): raise ValueError - class MyPlugin2: + class MyPlugin2(object): def pytest_pyfunc_call(self, pyfuncitem): return True @@ -683,7 +683,7 @@ class TestFunction: assert [x.originalname for x in items] == ['test_func', 'test_func'] -class TestSorting: +class TestSorting(object): def test_check_equality(self, testdir): modcol = testdir.getmodulecol(""" def test_pass(): pass @@ -733,7 +733,7 @@ class TestSorting: assert [item.name for item in colitems] == ['test_b', 'test_a'] -class TestConftestCustomization: +class TestConftestCustomization(object): def test_pytest_pycollect_module(self, testdir): testdir.makeconftest(""" import pytest @@ -847,7 +847,7 @@ def test_modulecol_roundtrip(testdir): assert modcol.name == newcol.name -class TestTracebackCutting: +class TestTracebackCutting(object): def test_skip_simple(self): excinfo = pytest.raises(pytest.skip.Exception, 'pytest.skip("xxx")') assert excinfo.traceback[-1].frame.code.name == "skip" @@ -973,7 +973,7 @@ class TestTracebackCutting: assert filter_traceback(tb[-1]) -class TestReportInfo: +class TestReportInfo(object): def test_itemreport_reportinfo(self, testdir, linecomp): testdir.makeconftest(""" import pytest @@ -998,7 +998,7 @@ class TestReportInfo: def test_class_reportinfo(self, testdir): modcol = testdir.getmodulecol(""" # lineno 0 - class TestClass: + class TestClass(object): def test_hello(self): pass """) classcol = testdir.collect_by_name(modcol, "TestClass") @@ -1033,7 +1033,7 @@ class TestReportInfo: def check(x): pass yield check, 3 - class TestClass: + class TestClass(object): def test_method(self): pass """ @@ -1042,7 +1042,7 @@ class TestReportInfo: # https://github.com/pytest-dev/pytest/issues/1204 modcol = testdir.getmodulecol(""" # lineno 0 - class TestClass: + class TestClass(object): def __getattr__(self, name): return "this is not an int" @@ -1064,7 +1064,7 @@ def test_customized_python_discovery(testdir): p = testdir.makepyfile(""" def check_simple(): pass - class CheckMyApp: + class CheckMyApp(object): def check_meth(self): pass """) @@ -1139,7 +1139,7 @@ def test_customize_through_attributes(testdir): return MyClass(name, parent=collector) """) testdir.makepyfile(""" - class MyTestClass: + class MyTestClass(object): def test_hello(self): pass """) @@ -1153,11 +1153,11 @@ def test_customize_through_attributes(testdir): def test_unorderable_types(testdir): testdir.makepyfile(""" - class TestJoinEmpty: + class TestJoinEmpty(object): pass def make_test(): - class Test: + class Test(object): pass Test.__name__ = "TestFoo" return Test diff --git a/testing/python/fixture.py b/testing/python/fixture.py index be99ed833..269d2c68a 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -20,7 +20,7 @@ def test_getfuncargnames(): def h(arg1, arg2, arg3="hello"): pass assert fixtures.getfuncargnames(h) == ('arg1', 'arg2') - class A: + class A(object): def f(self, arg1, arg2="hello"): pass @@ -28,7 +28,7 @@ def test_getfuncargnames(): if sys.version_info < (3,0): assert fixtures.getfuncargnames(A.f) == ('arg1',) -class TestFillFixtures: +class TestFillFixtures(object): def test_fillfuncargs_exposed(self): # used by oejskit, kept for compatibility assert pytest._fillfuncargs == fixtures.fillfixtures @@ -79,7 +79,7 @@ class TestFillFixtures: def something(request): return request.function.__name__ - class TestClass: + class TestClass(object): def test_method(self, something): assert something == "test_method" def test_func(something): @@ -91,7 +91,7 @@ class TestFillFixtures: def test_funcarg_lookup_classlevel(self, testdir): p = testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): @pytest.fixture def something(self, request): @@ -134,7 +134,7 @@ class TestFillFixtures: def spam(): return 'spam' - class TestSpam: + class TestSpam(object): @pytest.fixture def spam(self, spam): @@ -463,7 +463,7 @@ class TestFillFixtures: assert result.ret == 0 -class TestRequestBasic: +class TestRequestBasic(object): def test_request_attributes(self, testdir): item = testdir.getitem(""" import pytest @@ -484,7 +484,7 @@ class TestRequestBasic: def test_request_attributes_method(self, testdir): item, = testdir.getitems(""" import pytest - class TestB: + class TestB(object): @pytest.fixture def something(self, request): @@ -502,7 +502,7 @@ class TestRequestBasic: @pytest.fixture def something(request): pass - class TestClass: + class TestClass(object): def test_method(self, something): pass """) @@ -704,7 +704,7 @@ class TestRequestBasic: def test_func(): pass - class TestClass: + class TestClass(object): @pytest.fixture(scope="class", autouse=True) def setup_class(self): l.append("class") @@ -771,7 +771,7 @@ class TestRequestBasic: reprec = testdir.inline_run() reprec.assertoutcome(passed=2) -class TestRequestMarking: +class TestRequestMarking(object): def test_applymarker(self, testdir): item1,item2 = testdir.getitems(""" import pytest @@ -779,7 +779,7 @@ class TestRequestMarking: @pytest.fixture def something(request): pass - class TestClass: + class TestClass(object): def test_func1(self, something): pass def test_func2(self, something): @@ -831,7 +831,7 @@ class TestRequestMarking: reprec = testdir.inline_run() reprec.assertoutcome(passed=2) -class TestRequestCachedSetup: +class TestRequestCachedSetup(object): def test_request_cachedsetup_defaultmodule(self, testdir): reprec = testdir.inline_runsource(""" mysetup = ["hello",].pop @@ -844,7 +844,7 @@ class TestRequestCachedSetup: def test_func1(something): assert something == "hello" - class TestClass: + class TestClass(object): def test_func1a(self, something): assert something == "hello" """) @@ -862,7 +862,7 @@ class TestRequestCachedSetup: assert something == "hello3" def test_func2(something): assert something == "hello2" - class TestClass: + class TestClass(object): def test_func1a(self, something): assert something == "hello" def test_func2b(self, something): @@ -996,7 +996,7 @@ class TestRequestCachedSetup: "*ZeroDivisionError*", ]) -class TestFixtureUsages: +class TestFixtureUsages(object): def test_noargfixturedec(self, testdir): testdir.makepyfile(""" import pytest @@ -1138,7 +1138,7 @@ class TestFixtureUsages: def test_factory_setup_as_classes_fails(self, testdir): testdir.makepyfile(""" import pytest - class arg1: + class arg1(object): def __init__(self, request): self.x = 1 arg1 = pytest.fixture()(arg1) @@ -1172,7 +1172,7 @@ class TestFixtureUsages: request.cls.hello = "world" l.append(1) - class TestClass: + class TestClass(object): def test_one(self): assert self.hello == "world" assert len(l) == 1 @@ -1198,7 +1198,7 @@ class TestFixtureUsages: """) testdir.makepyfile(""" - class TestClass: + class TestClass(object): def test_one(self): assert self.hello == "world" def test_two(self): @@ -1217,7 +1217,7 @@ class TestFixtureUsages: testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): @pytest.fixture def setup1(self, request): assert self == request.instance @@ -1256,7 +1256,7 @@ class TestFixtureUsages: assert l == [1,2, 10,20] -class TestFixtureManagerParseFactories: +class TestFixtureManagerParseFactories(object): @pytest.fixture def testdir(self, request): @@ -1280,7 +1280,7 @@ class TestFixtureManagerParseFactories: def test_parsefactories_evil_objects_issue214(self, testdir): testdir.makepyfile(""" - class A: + class A(object): def __call__(self): pass def __getattr__(self, name): @@ -1311,7 +1311,7 @@ class TestFixtureManagerParseFactories: @pytest.fixture def hello(request): return "module" - class TestClass: + class TestClass(object): @pytest.fixture def hello(self, request): return "class" @@ -1360,7 +1360,7 @@ class TestFixtureManagerParseFactories: reprec.assertoutcome(passed=2) -class TestAutouseDiscovery: +class TestAutouseDiscovery(object): @pytest.fixture def testdir(self, testdir): @@ -1402,14 +1402,14 @@ class TestAutouseDiscovery: def test_two_classes_separated_autouse(self, testdir): testdir.makepyfile(""" import pytest - class TestA: + class TestA(object): l = [] @pytest.fixture(autouse=True) def setup1(self): self.l.append(1) def test_setup1(self): assert self.l == [1] - class TestB: + class TestB(object): l = [] @pytest.fixture(autouse=True) def setup2(self): @@ -1423,7 +1423,7 @@ class TestAutouseDiscovery: def test_setup_at_classlevel(self, testdir): testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): @pytest.fixture(autouse=True) def permethod(self, request): request.instance.funcname = request.function.__name__ @@ -1505,13 +1505,13 @@ class TestAutouseDiscovery: def test_x(): assert l == ["module"] - class TestA: + class TestA(object): @pytest.fixture(autouse=True) def append2(self): l.append("A") def test_hello(self): assert l == ["module", "module", "A"], l - class TestA2: + class TestA2(object): def test_world(self): assert l == ["module", "module", "A", "module"], l """) @@ -1519,7 +1519,7 @@ class TestAutouseDiscovery: reprec.assertoutcome(passed=3) -class TestAutouseManagement: +class TestAutouseManagement(object): def test_autouse_conftest_mid_directory(self, testdir): pkgdir = testdir.mkpydir("xyz123") pkgdir.join("conftest.py").write(_pytest._code.Source(""" @@ -1654,10 +1654,10 @@ class TestAutouseManagement: testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): def test_1(self): pass - class TestClass2: + class TestClass2(object): def test_2(self): pass """) @@ -1682,7 +1682,7 @@ class TestAutouseManagement: def mappend(): l.append(1) - class TestHallo: + class TestHallo(object): def test_method(self): assert l == [1,3,2] """) @@ -1696,7 +1696,7 @@ class TestAutouseManagement: def pytest_generate_tests(metafunc): if metafunc.cls is not None: metafunc.parametrize("item", [1,2], scope="class") - class TestClass: + class TestClass(object): @pytest.fixture(scope="class", autouse=True) def addteardown(self, item, request): l.append("setup-%d" % item) @@ -1756,7 +1756,7 @@ class TestAutouseManagement: reprec.assertoutcome(passed=2) -class TestFixtureMarker: +class TestFixtureMarker(object): def test_parametrize(self, testdir): testdir.makepyfile(""" import pytest @@ -1822,7 +1822,7 @@ class TestFixtureMarker: def test_2(arg): assert arg == 1 assert len(l) == 1 - class TestClass: + class TestClass(object): def test3(self, arg): assert arg == 1 assert len(l) == 1 @@ -1916,7 +1916,7 @@ class TestFixtureMarker: def test_2(arg): assert arg == 1 assert len(l) == 1 - class TestClass: + class TestClass(object): def test3(self, arg): assert arg == 1 assert len(l) == 1 @@ -2135,12 +2135,12 @@ class TestFixtureMarker: testdir.makepyfile(""" import pytest - class TestClass2: + class TestClass2(object): def test_1(self): pass def test_2(self): pass - class TestClass: + class TestClass(object): def test_3(self): pass """) @@ -2213,7 +2213,7 @@ class TestFixtureMarker: l = [] - class TestClass: + class TestClass(object): @classmethod @pytest.fixture(scope="class", autouse=True) def setup1(self, request, param1): @@ -2273,7 +2273,7 @@ class TestFixtureMarker: testpath = testdir.makepyfile(""" import pytest - class Box: + class Box(object): value = 0 @pytest.fixture(scope='class') @@ -2284,11 +2284,11 @@ class TestFixtureMarker: def test_a(a): assert a == 1 - class Test1: + class Test1(object): def test_b(self, a): assert a == 2 - class Test2: + class Test2(object): def test_c(self, a): assert a == 3""") reprec = testdir.inline_run(testpath) @@ -2402,11 +2402,11 @@ class TestFixtureMarker: request.addfinalizer(lambda: l.append("fin %s" % request.param)) return request.param - class TestGreetings: + class TestGreetings(object): def test_hello(self, human): l.append("test_hello") - class TestMetrics: + class TestMetrics(object): def test_name(self, human): l.append("test_name") @@ -2499,7 +2499,7 @@ class TestFixtureMarker: '*test_foo*beta*']) -class TestRequestScopeAccess: +class TestRequestScopeAccess(object): pytestmark = pytest.mark.parametrize(("scope", "ok", "error"),[ ["session", "", "fspath class function module"], ["module", "module fspath", "cls function"], @@ -2543,7 +2543,7 @@ class TestRequestScopeAccess: reprec = testdir.inline_run() reprec.assertoutcome(passed=1) -class TestErrors: +class TestErrors(object): def test_subfactory_missing_funcarg(self, testdir): testdir.makepyfile(""" import pytest @@ -2607,7 +2607,7 @@ class TestErrors: "*1 error*", ]) -class TestShowFixtures: +class TestShowFixtures(object): def test_funcarg_compat(self, testdir): config = testdir.parseconfigure("--funcargs") assert config.option.showfixtures @@ -2770,7 +2770,7 @@ class TestShowFixtures: @pytest.mark.parametrize('flavor', ['fixture', 'yield_fixture']) -class TestContextManagerFixtureFuncs: +class TestContextManagerFixtureFuncs(object): def test_simple(self, testdir, flavor): testdir.makepyfile(""" @@ -2877,7 +2877,7 @@ class TestContextManagerFixtureFuncs: result = testdir.runpytest("-s") result.stdout.fnmatch_lines("*mew*") -class TestParameterizedSubRequest: +class TestParameterizedSubRequest(object): def test_call_from_fixture(self, testdir): testfile = testdir.makepyfile(""" import pytest diff --git a/testing/python/integration.py b/testing/python/integration.py index 6697342ea..4f888276b 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -3,7 +3,7 @@ from _pytest import python from _pytest import runner -class TestOEJSKITSpecials: +class TestOEJSKITSpecials(object): def test_funcarg_non_pycollectobj(self, testdir): # rough jstests usage testdir.makeconftest(""" import pytest @@ -19,7 +19,7 @@ class TestOEJSKITSpecials: @pytest.fixture def arg1(request): return 42 - class MyClass: + class MyClass(object): pass """) # this hook finds funcarg factories @@ -48,7 +48,7 @@ class TestOEJSKITSpecials: @pytest.fixture def arg1(request): return 42 - class MyClass: + class MyClass(object): pass """) # this hook finds funcarg factories @@ -76,7 +76,7 @@ def test_wrapped_getfslineno(): fs2, lineno2 = python.getfslineno(wrap) assert lineno > lineno2, "getfslineno does not unwrap correctly" -class TestMockDecoration: +class TestMockDecoration(object): def test_wrapped_getfuncargnames(self): from _pytest.compat import getfuncargnames @@ -207,7 +207,7 @@ class TestMockDecoration: @patch('os.getcwd') @patch('os.path') @mark.slow - class TestSimple: + class TestSimple(object): def test_simple_thing(self, mock_path, mock_getcwd): pass """) @@ -215,7 +215,7 @@ class TestMockDecoration: reprec.assertoutcome(passed=1) -class TestReRunTests: +class TestReRunTests(object): def test_rerun(self, testdir): testdir.makeconftest(""" from _pytest.runner import runtestprotocol @@ -251,7 +251,7 @@ def test_pytestconfig_is_session_scoped(): assert pytestconfig._pytestfixturefunction.scope == "session" -class TestNoselikeTestAttribute: +class TestNoselikeTestAttribute(object): def test_module_with_global_test(self, testdir): testdir.makepyfile(""" __test__ = False @@ -270,7 +270,7 @@ class TestNoselikeTestAttribute: pass test_func.__test__ = False - class TestSome: + class TestSome(object): __test__ = False def test_method(self): pass @@ -328,7 +328,7 @@ class TestNoselikeTestAttribute: @pytest.mark.issue351 -class TestParameterize: +class TestParameterize(object): def test_idfn_marker(self, testdir): testdir.makepyfile(""" diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 372794a65..949b265a3 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -13,12 +13,12 @@ from hypothesis import strategies PY3 = sys.version_info >= (3, 0) -class TestMetafunc: +class TestMetafunc(object): def Metafunc(self, func): # the unit tests of this class check if things work correctly # on the funcarg level, so we don't need a full blown # initiliazation - class FixtureInfo: + class FixtureInfo(object): name2fixturedefs = None def __init__(self, names): @@ -68,7 +68,7 @@ class TestMetafunc: def func(arg1): pass metafunc = self.Metafunc(func) - class obj: pass + class obj(object): pass metafunc.addcall(param=obj) metafunc.addcall(param=obj) @@ -83,7 +83,7 @@ class TestMetafunc: metafunc = self.Metafunc(func) - class obj: pass + class obj(object): pass metafunc.addcall(funcargs={"x": 2}) metafunc.addcall(funcargs={"x": 3}) @@ -150,7 +150,7 @@ class TestMetafunc: def func(x, y): pass metafunc = self.Metafunc(func) - class A: + class A(object): pass metafunc.parametrize("x", [A(), A()]) @@ -601,7 +601,7 @@ class TestMetafunc: pytestmark = pytest.mark.parametrize("x", [1,2]) def test_func(x): assert 0, x - class TestClass: + class TestClass(object): pytestmark = pytest.mark.parametrize("y", [3,4]) def test_meth(self, x, y): assert 0, x @@ -672,7 +672,7 @@ class TestMetafunc: assert fixtures._format_args(function4) == "(arg1, *args, **kwargs)" -class TestMetafuncFunctional: +class TestMetafuncFunctional(object): def test_attributes(self, testdir): p = testdir.makepyfile(""" # assumes that generate/provide runs in the same process @@ -691,7 +691,7 @@ class TestMetafuncFunctional: assert metafunc.function == test_function assert metafunc.cls is None - class TestClass: + class TestClass(object): def test_method(self, metafunc, pytestconfig): assert metafunc.config == pytestconfig assert metafunc.module.__name__ == __name__ @@ -716,7 +716,7 @@ class TestMetafuncFunctional: def pytest_generate_tests(metafunc): metafunc.addcall(funcargs=dict(arg1=1, arg2=1)) - class TestClass: + class TestClass(object): def test_myfunc(self, arg1, arg2): assert arg1 == arg2 """) @@ -756,7 +756,7 @@ class TestMetafuncFunctional: def pytest_generate_tests(metafunc): assert 'xyz' not in metafunc.fixturenames - class TestHello: + class TestHello(object): def test_hello(xyz): pass """) @@ -782,7 +782,7 @@ class TestMetafuncFunctional: def arg2(request): return request.param[1] - class TestClass: + class TestClass(object): def test_myfunc(self, arg1, arg2): assert arg1 == arg2 """) @@ -795,7 +795,7 @@ class TestMetafuncFunctional: def test_generate_tests_in_class(self, testdir): p = testdir.makepyfile(""" - class TestClass: + class TestClass(object): def pytest_generate_tests(self, metafunc): metafunc.addcall(funcargs={'hello': 'world'}, id="hello") @@ -814,7 +814,7 @@ class TestMetafuncFunctional: metafunc.addcall({'arg1': 10}) metafunc.addcall({'arg1': 20}) - class TestClass: + class TestClass(object): def test_func(self, arg1): assert not hasattr(self, 'x') self.x = 1 @@ -831,7 +831,7 @@ class TestMetafuncFunctional: def pytest_generate_tests(metafunc): metafunc.addcall({'arg1': 1}) - class TestClass: + class TestClass(object): def test_method(self, arg1): assert arg1 == self.val def setup_method(self, func): @@ -1117,7 +1117,7 @@ class TestMetafuncFunctional: assert expectederror in failures[0].longrepr.reprcrash.message -class TestMetafuncFunctionalAuto: +class TestMetafuncFunctionalAuto(object): """ Tests related to automatically find out the correct scope for parametrized tests (#1832). """ @@ -1236,7 +1236,7 @@ class TestMetafuncFunctionalAuto: assert output.count('preparing foo-3') == 1 -class TestMarkersWithParametrization: +class TestMarkersWithParametrization(object): pytestmark = pytest.mark.issue308 def test_simple_mark(self, testdir): s = """ diff --git a/testing/python/raises.py b/testing/python/raises.py index 8170ec793..21a6f808c 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -2,7 +2,7 @@ import pytest import sys -class TestRaises: +class TestRaises(object): def test_raises(self): source = "int('qwe')" excinfo = pytest.raises(ValueError, source) @@ -20,7 +20,7 @@ class TestRaises: pytest.raises(ValueError, int, 'hello') def test_raises_callable_no_exception(self): - class A: + class A(object): def __call__(self): pass try: diff --git a/testing/test_argcomplete.py b/testing/test_argcomplete.py index ace7d8ceb..ed6db4c78 100644 --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -69,7 +69,7 @@ class FilesCompleter(object): completion += [f + '/' for f in anticomp] return completion -class TestArgComplete: +class TestArgComplete(object): @pytest.mark.skipif("sys.platform in ('win32', 'darwin')") def test_compare_with_compgen(self): from _pytest._argcomplete import FastFilesCompleter diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 8cfd0ad85..fc2819f69 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -25,7 +25,7 @@ def mock_config(): return Config() -class TestImportHookInstallation: +class TestImportHookInstallation(object): @pytest.mark.parametrize('initial_conftest', [True, False]) @pytest.mark.parametrize('mode', ['plain', 'rewrite']) @@ -159,7 +159,7 @@ class TestImportHookInstallation: plugin_state = "{plugin_state}" - class DummyDistInfo: + class DummyDistInfo(object): project_name = 'spam' version = '1.0' @@ -174,7 +174,7 @@ class TestImportHookInstallation: 'hampkg/__init__.py'] return [] - class DummyEntryPoint: + class DummyEntryPoint(object): name = 'spam' module_name = 'spam.py' attrs = () @@ -257,7 +257,7 @@ class TestImportHookInstallation: 'pytest_tests_internal_non_existing2') -class TestBinReprIntegration: +class TestBinReprIntegration(object): def test_pytest_assertrepr_compare_called(self, testdir): testdir.makeconftest(""" @@ -288,7 +288,7 @@ def callequal(left, right, verbose=False): return plugin.pytest_assertrepr_compare(config, '==', left, right) -class TestAssert_reprcompare: +class TestAssert_reprcompare(object): def test_different_types(self): assert callequal([0, 1], 'foo') is None @@ -442,7 +442,7 @@ class TestAssert_reprcompare: assert len(expl) > 1 def test_list_bad_repr(self): - class A: + class A(object): def __repr__(self): raise ValueError(42) expl = callequal([], [A()]) @@ -501,7 +501,7 @@ class TestAssert_reprcompare: assert msg -class TestFormatExplanation: +class TestFormatExplanation(object): def test_special_chars_full(self, testdir): # Issue 453, for the bug this would raise IndexError @@ -593,7 +593,7 @@ class TestFormatExplanation: assert util.format_explanation(expl) == res -class TestTruncateExplanation: +class TestTruncateExplanation(object): """ Confirm assertion output is truncated as expected """ diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index fdf674f25..0ec528e82 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -57,7 +57,7 @@ def getmsg(f, extra_ns=None, must_pass=False): pytest.fail("function didn't raise at all") -class TestAssertionRewrite: +class TestAssertionRewrite(object): def test_place_initial_imports(self): s = """'Doc string'\nother = stuff""" @@ -333,7 +333,7 @@ class TestAssertionRewrite: @pytest.mark.skipif("sys.version_info < (3,5)") def test_at_operator_issue1290(self, testdir): testdir.makepyfile(""" - class Matrix: + class Matrix(object): def __init__(self, num): self.num = num def __matmul__(self, other): @@ -515,7 +515,7 @@ class TestAssertionRewrite: assert r"where 1 = \n{ \n~ \n}.a" in util._format_lines([getmsg(f)])[0] -class TestRewriteOnImport: +class TestRewriteOnImport(object): def test_pycache_is_a_file(self, testdir): testdir.tmpdir.join("__pycache__").write("Hello") @@ -884,7 +884,7 @@ class TestAssertionRewriteHookDetails(object): """ path = testdir.mkpydir("foo") path.join("test_foo.py").write(_pytest._code.Source(""" - class Test: + class Test(object): def test_foo(self): import pkgutil data = pkgutil.get_data('foo.test_foo', 'data.txt') @@ -912,7 +912,7 @@ def test_issue731(testdir): assert 'unbalanced braces' not in result.stdout.str() -class TestIssue925(): +class TestIssue925(object): def test_simple_case(self, testdir): testdir.makepyfile(""" def test_ternary_display(): diff --git a/testing/test_cache.py b/testing/test_cache.py index 98053f869..c1b98489e 100755 --- a/testing/test_cache.py +++ b/testing/test_cache.py @@ -7,7 +7,7 @@ import shutil pytest_plugins = "pytester", -class TestNewAPI: +class TestNewAPI(object): def test_config_cache_makedir(self, testdir): testdir.makeini("[pytest]") config = testdir.parseconfigure() @@ -129,7 +129,7 @@ def test_cache_show(testdir): ]) -class TestLastFailed: +class TestLastFailed(object): def test_lastfailed_usecase(self, testdir, monkeypatch): monkeypatch.setenv("PYTHONDONTWRITEBYTECODE", 1) diff --git a/testing/test_capture.py b/testing/test_capture.py index cbb5fc81b..365329f59 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -55,7 +55,7 @@ def StdCapture(out=True, err=True, in_=True): return capture.MultiCapture(out, err, in_, Capture=capture.SysCapture) -class TestCaptureManager: +class TestCaptureManager(object): def test_getmethod_default_no_fd(self, monkeypatch): from _pytest.capture import pytest_addoption from _pytest.config import Parser @@ -154,7 +154,7 @@ def test_collect_capturing(testdir): ]) -class TestPerTestCapturing: +class TestPerTestCapturing(object): def test_capture_and_fixtures(self, testdir): p = testdir.makepyfile(""" def setup_module(mod): @@ -275,7 +275,7 @@ class TestPerTestCapturing: ]) -class TestLoggingInteraction: +class TestLoggingInteraction(object): def test_logging_stream_ownership(self, testdir): p = testdir.makepyfile(""" def test_logging(): @@ -395,7 +395,7 @@ class TestLoggingInteraction: assert 'operation on closed file' not in result.stderr.str() -class TestCaptureFixture: +class TestCaptureFixture(object): @pytest.mark.parametrize("opt", [[], ["-s"]]) def test_std_functional(self, testdir, opt): reprec = testdir.inline_runsource(""" @@ -622,7 +622,7 @@ def test_error_during_readouterr(testdir): ]) -class TestTextIO: +class TestTextIO(object): def test_text(self): f = capture.TextIO() f.write("hello") @@ -737,7 +737,7 @@ def lsof_check(): assert len2 < len1 + 3, out2 -class TestFDCapture: +class TestFDCapture(object): pytestmark = needsosdup def test_simple(self, tmpfile): @@ -832,7 +832,7 @@ def saved_fd(fd): os.close(new_fd) -class TestStdCapture: +class TestStdCapture(object): captureclass = staticmethod(StdCapture) @contextlib.contextmanager @@ -990,7 +990,7 @@ class TestStdCaptureFD(TestStdCapture): cap.stop_capturing() -class TestStdCaptureFDinvalidFD: +class TestStdCaptureFDinvalidFD(object): pytestmark = needsosdup def test_stdcapture_fd_invalid_fd(self, testdir): diff --git a/testing/test_collection.py b/testing/test_collection.py index 4e44874e1..8575aa63a 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -2,7 +2,7 @@ import pytest, py from _pytest.main import Session, EXIT_NOTESTSCOLLECTED -class TestCollector: +class TestCollector(object): def test_collect_versus_item(self): from pytest import Collector, Item assert not issubclass(Collector, Item) @@ -50,7 +50,7 @@ class TestCollector: def test_getparent(self, testdir): modcol = testdir.getmodulecol(""" - class TestClass: + class TestClass(object): def test_foo(): pass """) @@ -88,7 +88,7 @@ class TestCollector: def test_can_skip_class_with_test_attr(self, testdir): """Assure test class is skipped when using `__test__=False` (See #2007).""" testdir.makepyfile(""" - class TestFoo(): + class TestFoo(object): __test__ = False def __init__(self): pass @@ -101,7 +101,7 @@ class TestCollector: '*no tests ran in*', ]) -class TestCollectFS: +class TestCollectFS(object): def test_ignored_certain_directories(self, testdir): tmpdir = testdir.tmpdir tmpdir.ensure("build", 'test_notfound.py') @@ -163,11 +163,11 @@ class TestCollectFS: assert [x.name for x in items] == ['test_%s' % dirname] -class TestCollectPluginHookRelay: +class TestCollectPluginHookRelay(object): def test_pytest_collect_file(self, testdir): wascalled = [] - class Plugin: + class Plugin(object): def pytest_collect_file(self, path, parent): if not path.basename.startswith("."): # Ignore hidden files, e.g. .testmondata. @@ -181,7 +181,7 @@ class TestCollectPluginHookRelay: def test_pytest_collect_directory(self, testdir): wascalled = [] - class Plugin: + class Plugin(object): def pytest_collect_directory(self, path, parent): wascalled.append(path.basename) @@ -192,7 +192,7 @@ class TestCollectPluginHookRelay: assert "world" in wascalled -class TestPrunetraceback: +class TestPrunetraceback(object): def test_custom_repr_failure(self, testdir): p = testdir.makepyfile(""" @@ -238,7 +238,7 @@ class TestPrunetraceback: ]) -class TestCustomConftests: +class TestCustomConftests(object): def test_ignore_collect_path(self, testdir): testdir.makeconftest(""" def pytest_ignore_collect(path, config): @@ -333,7 +333,7 @@ class TestCustomConftests: "*test_x*" ]) -class TestSession: +class TestSession(object): def test_parsearg(self, testdir): p = testdir.makepyfile("def test_func(): pass") subdir = testdir.mkdir("sub") @@ -391,7 +391,7 @@ class TestSession: def test_collect_protocol_method(self, testdir): p = testdir.makepyfile(""" - class TestClass: + class TestClass(object): def test_method(self): pass """) @@ -490,7 +490,7 @@ class TestSession: def test_find_byid_without_instance_parents(self, testdir): p = testdir.makepyfile(""" - class TestClass: + class TestClass(object): def test_method(self): pass """) @@ -500,7 +500,7 @@ class TestSession: item, = items assert item.nodeid.endswith("TestClass::()::test_method") -class Test_getinitialnodes: +class Test_getinitialnodes(object): def test_global_file(self, testdir, tmpdir): x = tmpdir.ensure("x.py") with tmpdir.as_cwd(): @@ -527,7 +527,7 @@ class Test_getinitialnodes: for col in col.listchain(): assert col.config is config -class Test_genitems: +class Test_genitems(object): def test_check_collect_hashes(self, testdir): p = testdir.makepyfile(""" def test_1(): @@ -550,7 +550,7 @@ class Test_genitems: def testone(): pass - class TestX: + class TestX(object): def testmethod_one(self): pass @@ -583,11 +583,11 @@ class Test_genitems: python_functions = *_test test """) p = testdir.makepyfile(''' - class MyTestSuite: + class MyTestSuite(object): def x_test(self): pass - class TestCase: + class TestCase(object): def test_y(self): pass ''') @@ -602,7 +602,7 @@ def test_matchnodes_two_collections_same_file(testdir): def pytest_configure(config): config.pluginmanager.register(Plugin2()) - class Plugin2: + class Plugin2(object): def pytest_collect_file(self, path, parent): if path.ext == ".abc": return MyFile2(path, parent) @@ -634,7 +634,7 @@ def test_matchnodes_two_collections_same_file(testdir): ]) -class TestNodekeywords: +class TestNodekeywords(object): def test_no_under(self, testdir): modcol = testdir.getmodulecol(""" def test_pass(): pass diff --git a/testing/test_config.py b/testing/test_config.py index e6aa423e8..7876063bd 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -4,7 +4,7 @@ import _pytest._code from _pytest.config import getcfg, get_common_ancestor, determine_setup from _pytest.main import EXIT_NOTESTSCOLLECTED -class TestParseIni: +class TestParseIni(object): @pytest.mark.parametrize('section, filename', [('pytest', 'pytest.ini'), ('tool:pytest', 'setup.cfg')]) @@ -84,7 +84,7 @@ class TestParseIni: result = testdir.inline_run("--confcutdir=.") assert result.ret == 0 -class TestConfigCmdlineParsing: +class TestConfigCmdlineParsing(object): def test_parsing_again_fails(self, testdir): config = testdir.parseconfig() pytest.raises(AssertionError, lambda: config.parse([])) @@ -115,7 +115,7 @@ class TestConfigCmdlineParsing: ret = pytest.main("-c " + temp_cfg_file) assert ret == _pytest.main.EXIT_OK -class TestConfigAPI: +class TestConfigAPI(object): def test_config_trace(self, testdir): config = testdir.parseconfig() l = [] @@ -304,7 +304,7 @@ class TestConfigAPI: assert config.getoption('confcutdir') == str(testdir.tmpdir.join('dir')) -class TestConfigFromdictargs: +class TestConfigFromdictargs(object): def test_basic_behavior(self): from _pytest.config import Config option_dict = { @@ -389,19 +389,19 @@ def test_preparse_ordering_with_setuptools(testdir, monkeypatch): def my_iter(name): assert name == "pytest11" - class Dist: + class Dist(object): project_name = 'spam' version = '1.0' def _get_metadata(self, name): return ['foo.txt,sha256=abc,123'] - class EntryPoint: + class EntryPoint(object): name = "mytestplugin" dist = Dist() def load(self): - class PseudoPlugin: + class PseudoPlugin(object): x = 42 return PseudoPlugin() @@ -423,14 +423,14 @@ def test_setuptools_importerror_issue1479(testdir, monkeypatch): def my_iter(name): assert name == "pytest11" - class Dist: + class Dist(object): project_name = 'spam' version = '1.0' def _get_metadata(self, name): return ['foo.txt,sha256=abc,123'] - class EntryPoint: + class EntryPoint(object): name = "mytestplugin" dist = Dist() @@ -450,14 +450,14 @@ def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch): def my_iter(name): assert name == "pytest11" - class Dist: + class Dist(object): project_name = 'spam' version = '1.0' def _get_metadata(self, name): return ['foo.txt,sha256=abc,123'] - class EntryPoint: + class EntryPoint(object): name = "mytestplugin" dist = Dist() @@ -557,7 +557,7 @@ def test_notify_exception(testdir, capfd): out, err = capfd.readouterr() assert "ValueError" in err - class A: + class A(object): def pytest_internalerror(self, excrepr): return True @@ -571,7 +571,7 @@ def test_load_initial_conftest_last_ordering(testdir): from _pytest.config import get_config pm = get_config().pluginmanager - class My: + class My(object): def pytest_load_initial_conftests(self): pass @@ -602,7 +602,7 @@ def test_get_plugin_specs_as_list(): assert _get_plugin_specs_as_list(('foo', 'bar')) == ['foo', 'bar'] -class TestWarning: +class TestWarning(object): def test_warn_config(self, testdir): testdir.makeconftest(""" l = [] @@ -641,7 +641,7 @@ class TestWarning: *WT1*test_warn_on_test_item*:7 hello* """) -class TestRootdir: +class TestRootdir(object): def test_simple_noini(self, tmpdir): assert get_common_ancestor([tmpdir]) == tmpdir a = tmpdir.mkdir("a") @@ -699,7 +699,7 @@ class TestRootdir: assert rootdir == tmpdir -class TestOverrideIniArgs: +class TestOverrideIniArgs(object): @pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split()) def test_override_ini_names(self, testdir, name): testdir.tmpdir.join(name).write(py.std.textwrap.dedent(""" diff --git a/testing/test_conftest.py b/testing/test_conftest.py index c0fa74701..e9fd1927a 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -24,14 +24,14 @@ def ConftestWithSetinitial(path): return conftest def conftest_setinitial(conftest, args, confcutdir=None): - class Namespace: + class Namespace(object): def __init__(self): self.file_or_dir = args self.confcutdir = str(confcutdir) self.noconftest = False conftest._set_initial_conftests(Namespace()) -class TestConftestValueAccessGlobal: +class TestConftestValueAccessGlobal(object): def test_basic_init(self, basedir): conftest = PytestPluginManager() p = basedir.join("adir") @@ -265,7 +265,7 @@ def test_conftest_found_with_double_dash(testdir): """) -class TestConftestVisibility: +class TestConftestVisibility(object): def _setup_tree(self, testdir): # for issue616 # example mostly taken from: # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html @@ -398,7 +398,7 @@ def test_search_conftest_up_to_inifile(testdir, confcutdir, passed, error): def test_issue1073_conftest_special_objects(testdir): testdir.makeconftest(""" - class DontTouchMe: + class DontTouchMe(object): def __getattr__(self, x): raise Exception('cant touch me') diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d4d903708..429bb8de9 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -6,7 +6,7 @@ from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile import pytest -class TestDoctests: +class TestDoctests(object): def test_collect_testtextfile(self, testdir): w = testdir.maketxtfile(whatever="") @@ -378,7 +378,7 @@ class TestDoctests: def test_doctestmodule_two_tests_one_fail(self, testdir): p = testdir.makepyfile(""" - class MyClass: + class MyClass(object): def bad_meth(self): ''' >>> magic = 42 @@ -401,7 +401,7 @@ class TestDoctests: doctest_optionflags = ELLIPSIS NORMALIZE_WHITESPACE """) p = testdir.makepyfile(""" - class MyClass: + class MyClass(object): ''' >>> a = "foo " >>> print(a) @@ -418,7 +418,7 @@ class TestDoctests: doctest_optionflags = ELLIPSIS """) p = testdir.makepyfile(""" - class MyClass: + class MyClass(object): ''' >>> a = "foo " >>> print(a) @@ -505,7 +505,7 @@ class TestDoctests: reprec.assertoutcome(failed=1) -class TestLiterals: +class TestLiterals(object): @pytest.mark.parametrize('config_mode', ['ini', 'comment']) def test_allow_unicode(self, testdir, config_mode): @@ -592,7 +592,7 @@ class TestLiterals: reprec.assertoutcome(passed=passed, failed=int(not passed)) -class TestDoctestSkips: +class TestDoctestSkips(object): """ If all examples in a doctest are skipped due to the SKIP option, then the tests should be SKIPPED rather than PASSED. (#957) @@ -646,7 +646,7 @@ class TestDoctestSkips: reprec.assertoutcome(passed=0, skipped=0) -class TestDoctestAutoUseFixtures: +class TestDoctestAutoUseFixtures(object): SCOPES = ['module', 'session', 'class', 'function'] @@ -765,7 +765,7 @@ class TestDoctestAutoUseFixtures: result.stdout.fnmatch_lines(['*=== 1 passed in *']) -class TestDoctestNamespaceFixture: +class TestDoctestNamespaceFixture(object): SCOPES = ['module', 'session', 'class', 'function'] @@ -815,7 +815,7 @@ class TestDoctestNamespaceFixture: reprec.assertoutcome(passed=1) -class TestDoctestReportingOption: +class TestDoctestReportingOption(object): def _run_doctest_report(self, testdir, format): testdir.makepyfile(""" def foo(): diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 83256d7c6..70c02332c 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -79,7 +79,7 @@ class DomNode(object): return type(self)(self.__node.nextSibling) -class TestPython: +class TestPython(object): def test_summing_simple(self, testdir): testdir.makepyfile(""" import pytest @@ -263,7 +263,7 @@ class TestPython: def test_classname_instance(self, testdir): testdir.makepyfile(""" - class TestClass: + class TestClass(object): def test_method(self): assert 0 """) @@ -376,7 +376,7 @@ class TestPython: testdir.makepyfile(""" def test_func(): assert 0 - class TestHello: + class TestHello(object): def test_hello(self): pass """) @@ -569,7 +569,7 @@ def test_mangle_test_address(): def test_dont_configure_on_slaves(tmpdir): gotten = [] - class FakeConfig: + class FakeConfig(object): def __init__(self): self.pluginmanager = self self.option = self @@ -588,7 +588,7 @@ def test_dont_configure_on_slaves(tmpdir): assert len(gotten) == 1 -class TestNonPython: +class TestNonPython(object): def test_summing_simple(self, testdir): testdir.makeconftest(""" import pytest @@ -750,7 +750,7 @@ def test_double_colon_split_function_issue469(testdir): def test_double_colon_split_method_issue469(testdir): testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): @pytest.mark.parametrize('param', ["double::colon"]) def test_func(self, param): pass diff --git a/testing/test_mark.py b/testing/test_mark.py index 5b52e55db..9474d1033 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -3,7 +3,7 @@ import os import py, pytest from _pytest.mark import MarkGenerator as Mark -class TestMark: +class TestMark(object): def test_markinfo_repr(self): from _pytest.mark import MarkInfo, Mark m = MarkInfo(Mark("hello", (1,2), {})) @@ -301,7 +301,7 @@ def test_parametrized_collected_from_command_line(testdir): rec.assertoutcome(passed=3) -class TestFunctional: +class TestFunctional(object): def test_mark_per_function(self, testdir): p = testdir.makepyfile(""" @@ -326,7 +326,7 @@ class TestFunctional: def test_marklist_per_class(self, testdir): item = testdir.getitem(""" import pytest - class TestClass: + class TestClass(object): pytestmark = [pytest.mark.hello, pytest.mark.world] def test_func(self): assert TestClass.test_func.hello @@ -339,7 +339,7 @@ class TestFunctional: item = testdir.getitem(""" import pytest pytestmark = [pytest.mark.hello, pytest.mark.world] - class TestClass: + class TestClass(object): def test_func(self): assert TestClass.test_func.hello assert TestClass.test_func.world @@ -352,7 +352,7 @@ class TestFunctional: item = testdir.getitem(""" import pytest @pytest.mark.hello - class TestClass: + class TestClass(object): def test_func(self): assert TestClass.test_func.hello """) @@ -363,7 +363,7 @@ class TestFunctional: item = testdir.getitem(""" import pytest @pytest.mark.hello - class TestClass: + class TestClass(object): pytestmark = pytest.mark.world def test_func(self): assert TestClass.test_func.hello @@ -377,7 +377,7 @@ class TestFunctional: p = testdir.makepyfile(""" import pytest pytestmark = pytest.mark.hello("pos1", x=1, y=2) - class TestClass: + class TestClass(object): # classlevel overrides module level pytestmark = pytest.mark.hello(x=3) @pytest.mark.hello("pos0", z=4) @@ -403,11 +403,11 @@ class TestFunctional: # issue 199 - propagate markers into nested classes p = testdir.makepyfile(""" import pytest - class TestA: + class TestA(object): pytestmark = pytest.mark.a def test_b(self): assert True - class TestC: + class TestC(object): # this one didnt get marked def test_d(self): assert True @@ -422,7 +422,7 @@ class TestFunctional: import pytest @pytest.mark.a - class Base: pass + class Base(object): pass @pytest.mark.b class Test1(Base): @@ -441,7 +441,7 @@ class TestFunctional: p = testdir.makepyfile(""" import pytest - class TestBase: + class TestBase(object): def test_foo(self): pass @@ -465,7 +465,7 @@ class TestFunctional: import pytest @pytest.mark.a - class Base: pass + class Base(object): pass @pytest.mark.b class Base2(Base): pass @@ -485,7 +485,7 @@ class TestFunctional: def test_mark_with_wrong_marker(self, testdir): reprec = testdir.inline_runsource(""" import pytest - class pytestmark: + class pytestmark(object): pass def test_func(): pass @@ -630,7 +630,7 @@ class TestFunctional: reprec.assertoutcome(skipped=1) -class TestKeywordSelection: +class TestKeywordSelection(object): def test_select_simple(self, testdir): file_test = testdir.makepyfile(""" @@ -659,7 +659,7 @@ class TestKeywordSelection: p = testdir.makepyfile(test_select=""" def test_1(): pass - class TestClass: + class TestClass(object): def test_2(self): pass """) diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 9d02e2cc0..04a53d93a 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -16,7 +16,7 @@ def mp(): def test_setattr(): - class A: + class A(object): x = 1 monkeypatch = MonkeyPatch() @@ -39,7 +39,7 @@ def test_setattr(): assert A.x == 5 -class TestSetattrWithImportPath: +class TestSetattrWithImportPath(object): def test_string_expression(self, monkeypatch): monkeypatch.setattr("os.path.abspath", lambda x: "hello2") assert os.path.abspath("123") == "hello2" @@ -79,7 +79,7 @@ class TestSetattrWithImportPath: def test_delattr(): - class A: + class A(object): x = 1 monkeypatch = MonkeyPatch() @@ -294,7 +294,7 @@ class SampleNewInherit(SampleNew): pass -class SampleOld: +class SampleOld(object): # oldstyle on python2 @staticmethod def hello(): diff --git a/testing/test_nose.py b/testing/test_nose.py index f54246111..11fb83176 100644 --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -26,7 +26,7 @@ def test_setup_func_with_setup_decorator(): from _pytest.nose import call_optional l = [] - class A: + class A(object): @pytest.fixture(autouse=True) def f(self): l.append(1) @@ -38,7 +38,7 @@ def test_setup_func_with_setup_decorator(): def test_setup_func_not_callable(): from _pytest.nose import call_optional - class A: + class A(object): f = 1 call_optional(A(), "f") @@ -270,7 +270,7 @@ def test_nose_setup_ordering(testdir): def setup_module(mod): mod.visited = True - class TestClass: + class TestClass(object): def setup(self): assert visited def test_first(self): @@ -377,7 +377,7 @@ def test_istest_class_decorator(testdir): p = testdir.makepyfile(""" import nose.tools @nose.tools.istest - class NotTestPrefix: + class NotTestPrefix(object): def test_method(self): pass """) @@ -388,7 +388,7 @@ def test_nottest_class_decorator(testdir): testdir.makepyfile(""" import nose.tools @nose.tools.nottest - class TestPrefix: + class TestPrefix(object): def test_method(self): pass """) diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index e933dbb8d..03d71de43 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -8,7 +8,7 @@ from _pytest import config as parseopt def parser(): return parseopt.Parser() -class TestParser: +class TestParser(object): def test_no_help_by_default(self, capsys): parser = parseopt.Parser(usage="xyz") pytest.raises(SystemExit, lambda: parser.parse(["-h"])) @@ -139,7 +139,7 @@ class TestParser: parser.addoption("--hello", dest="hello", action="store") parser.addoption("--world", dest="world", default=42) - class A: + class A(object): pass option = A() diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 8123424ca..f0d2a9ba2 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -2,7 +2,7 @@ import sys import pytest -class TestPasteCapture: +class TestPasteCapture(object): @pytest.fixture def pastebinlist(self, monkeypatch, request): @@ -71,7 +71,7 @@ class TestPasteCapture: ]) -class TestPaste: +class TestPaste(object): @pytest.fixture def pastebin(self, request): @@ -88,7 +88,7 @@ class TestPaste: def mocked(url, data): calls.append((url, data)) - class DummyFile: + class DummyFile(object): def read(self): # part of html of a normal response return b'View raw.' diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 63a0c2f00..cf6d6f7fb 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -18,7 +18,7 @@ def custom_pdb_calls(): called = [] # install dummy debugger class and track which methods were called on it - class _CustomPdb: + class _CustomPdb(object): def __init__(self, *args, **kwargs): called.append("init") @@ -33,7 +33,7 @@ def custom_pdb_calls(): -class TestPDB: +class TestPDB(object): @pytest.fixture def pdblist(self, request): @@ -374,7 +374,7 @@ class TestPDB: def test_pdb_custom_cls_with_settrace(self, testdir, monkeypatch): testdir.makepyfile(custom_pdb=""" - class CustomPdb: + class CustomPdb(object): def set_trace(*args, **kwargs): print 'custom set_trace>' """) diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 45ad321a3..3214d868b 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -11,7 +11,7 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED, Session def pytestpm(): return PytestPluginManager() -class TestPytestPluginInteractions: +class TestPytestPluginInteractions(object): def test_addhooks_conftestplugin(self, testdir): testdir.makepyfile(newhooks=""" def pytest_myhook(xyz): @@ -85,7 +85,7 @@ class TestPytestPluginInteractions: config = testdir.parseconfig() l = [] - class A: + class A(object): def pytest_configure(self, config): l.append(self) @@ -105,11 +105,11 @@ class TestPytestPluginInteractions: pytestpm = get_config().pluginmanager # fully initialized with plugins saveindent = [] - class api1: + class api1(object): def pytest_plugin_registered(self): saveindent.append(pytestpm.trace.root.indent) - class api2: + class api2(object): def pytest_plugin_registered(self): saveindent.append(pytestpm.trace.root.indent) raise ValueError() @@ -156,11 +156,11 @@ class TestPytestPluginInteractions: def test_warn_on_deprecated_multicall(self, pytestpm): warnings = [] - class get_warnings: + class get_warnings(object): def pytest_logwarning(self, message): warnings.append(message) - class Plugin: + class Plugin(object): def pytest_configure(self, __multicall__): pass @@ -173,11 +173,11 @@ class TestPytestPluginInteractions: def test_warn_on_deprecated_addhooks(self, pytestpm): warnings = [] - class get_warnings: + class get_warnings(object): def pytest_logwarning(self, code, fslocation, message, nodeid): warnings.append(message) - class Plugin: + class Plugin(object): def pytest_testhook(): pass @@ -221,7 +221,7 @@ def test_importplugin_error_message(testdir, pytestpm): assert py.std.re.match(expected, str(excinfo.value)) -class TestPytestPluginManager: +class TestPytestPluginManager(object): def test_register_imported_modules(self): pm = PytestPluginManager() mod = py.std.types.ModuleType("x.y.pytest_hello") @@ -348,7 +348,7 @@ class TestPytestPluginManager: pytestpm.consider_conftest(mod) -class TestPytestPluginManagerBootstrapming: +class TestPytestPluginManagerBootstrapming(object): def test_preparse_args(self, pytestpm): pytest.raises(ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"])) diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 49cf43a3e..9c9b56371 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -12,7 +12,7 @@ def test_make_hook_recorder(testdir): pytest.xfail("internal reportrecorder tests need refactoring") - class rep: + class rep(object): excinfo = None passed = False failed = True @@ -25,7 +25,7 @@ def test_make_hook_recorder(testdir): failures = recorder.getfailures() assert failures == [rep] - class rep: + class rep(object): excinfo = None passed = False failed = False @@ -74,7 +74,7 @@ def test_testdir_runs_with_plugin(testdir): def make_holder(): - class apiclass: + class apiclass(object): def pytest_xyz(self, arg): "x" def pytest_xyz_noarg(self): diff --git a/testing/test_resultlog.py b/testing/test_resultlog.py index e2d4fc263..c2f4a801c 100644 --- a/testing/test_resultlog.py +++ b/testing/test_resultlog.py @@ -70,7 +70,7 @@ def test_write_log_entry(): assert entry_lines[1:] == [' '+line for line in longrepr.splitlines()] -class TestWithFunctionIntegration: +class TestWithFunctionIntegration(object): # XXX (hpk) i think that the resultlog plugin should # provide a Parser object so that one can remain # ignorant regarding formatting details. diff --git a/testing/test_runner.py b/testing/test_runner.py index 727defa92..265e99d54 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -8,7 +8,7 @@ import pytest import sys from _pytest import runner, main -class TestSetupState: +class TestSetupState(object): def test_setup(self, testdir): ss = runner.SetupState() item = testdir.getitem("def test_func(): pass") @@ -71,7 +71,7 @@ class TestSetupState: assert err.value.args == ('oops2',) -class BaseFunctionalTests: +class BaseFunctionalTests(object): def test_passfunction(self, testdir): reports = testdir.runitem(""" def test_func(): @@ -200,7 +200,7 @@ class BaseFunctionalTests: rec = testdir.inline_runsource(""" import pytest - class TestClass: + class TestClass(object): def test_method(self): pass def teardown_class(cls): @@ -239,7 +239,7 @@ class BaseFunctionalTests: rec = testdir.inline_runsource(""" import pytest - class TestClass: + class TestClass(object): def teardown_method(self, x, y, z): pass @@ -351,12 +351,12 @@ class TestExecutionForked(BaseFunctionalTests): assert rep.failed assert rep.when == "???" -class TestSessionReports: +class TestSessionReports(object): def test_collect_result(self, testdir): col = testdir.getmodulecol(""" def test_func1(): pass - class TestClass: + class TestClass(object): pass """) rep = runner.collect_one_node(col) @@ -409,7 +409,7 @@ def test_runtest_in_module_ordering(testdir): import pytest def pytest_runtest_setup(item): # runs after class-level! item.function.mylist.append("module") - class TestClass: + class TestClass(object): def pytest_runtest_setup(self, item): assert not hasattr(item.function, 'mylist') item.function.mylist = ['class'] @@ -680,7 +680,7 @@ def test_store_except_info_on_eror(): sys.last_traceback and friends. """ # Simulate item that raises a specific exception - class ItemThatRaises: + class ItemThatRaises(object): def runtest(self): raise IndexError('TEST') try: @@ -693,7 +693,7 @@ def test_store_except_info_on_eror(): assert sys.last_traceback -class TestReportContents: +class TestReportContents(object): """ Test user-level API of ``TestReport`` objects. """ diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index e1f0924c6..9bf15bd66 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -24,7 +24,7 @@ def test_module_and_function_setup(testdir): assert modlevel[0] == 42 assert test_modlevel.answer == 17 - class TestFromClass: + class TestFromClass(object): def test_module(self): assert modlevel[0] == 42 assert not hasattr(test_modlevel, 'answer') @@ -69,7 +69,7 @@ def test_setup_function_failure_no_teardown(testdir): def test_class_setup(testdir): reprec = testdir.inline_runsource(""" - class TestSimpleClassSetup: + class TestSimpleClassSetup(object): clslevel = [] def setup_class(cls): cls.clslevel.append(23) @@ -92,7 +92,7 @@ def test_class_setup(testdir): def test_class_setup_failure_no_teardown(testdir): reprec = testdir.inline_runsource(""" - class TestSimpleClassSetup: + class TestSimpleClassSetup(object): clslevel = [] def setup_class(cls): 0/0 @@ -110,7 +110,7 @@ def test_class_setup_failure_no_teardown(testdir): def test_method_setup(testdir): reprec = testdir.inline_runsource(""" - class TestSetupMethod: + class TestSetupMethod(object): def setup_method(self, meth): self.methsetup = meth def teardown_method(self, meth): @@ -126,7 +126,7 @@ def test_method_setup(testdir): def test_method_setup_failure_no_teardown(testdir): reprec = testdir.inline_runsource(""" - class TestMethodSetup: + class TestMethodSetup(object): clslevel = [] def setup_method(self, method): self.clslevel.append(1) @@ -145,7 +145,7 @@ def test_method_setup_failure_no_teardown(testdir): def test_method_generator_setup(testdir): reprec = testdir.inline_runsource(""" - class TestSetupTeardownOnInstance: + class TestSetupTeardownOnInstance(object): def setup_class(cls): cls.classsetup = True @@ -195,7 +195,7 @@ def test_func_generator_setup(testdir): def test_method_setup_uses_fresh_instances(testdir): reprec = testdir.inline_runsource(""" - class TestSelfState1: + class TestSelfState1(object): memory = [] def test_hello(self): self.memory.append(self) @@ -276,7 +276,7 @@ def test_setup_teardown_function_level_with_optional_argument(testdir, monkeypat def test_function_1(): pass def test_function_2(): pass - class Test: + class Test(object): def setup_method(self, {arg}): trace('setup_method') def teardown_method(self, {arg}): trace('teardown_method') diff --git a/testing/test_session.py b/testing/test_session.py index a7dcb27a4..b6e7d2b6c 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -2,7 +2,7 @@ import pytest from _pytest.main import EXIT_NOTESTSCOLLECTED -class SessionTests: +class SessionTests(object): def test_basic_testitem_events(self, testdir): tfile = testdir.makepyfile(""" def test_one(): @@ -11,7 +11,7 @@ class SessionTests: assert 0 def test_other(): raise ValueError(23) - class TestClass: + class TestClass(object): def test_two(self, someargs): pass """) @@ -97,12 +97,12 @@ class SessionTests: def test_broken_repr(self, testdir): p = testdir.makepyfile(""" import pytest - class BrokenRepr1: + class BrokenRepr1(object): foo=0 def __repr__(self): raise Exception("Ha Ha fooled you, I'm a broken repr().") - class TestBrokenClass: + class TestBrokenClass(object): def test_explicit_bad_repr(self): t = BrokenRepr1() pytest.raises(Exception, 'repr(t)') @@ -145,7 +145,7 @@ class TestNewSession(SessionTests): l.append(2) def test_3(): assert l == [1,2] - class Testmygroup: + class Testmygroup(object): reslist = l def test_1(self): self.reslist.append(1) @@ -167,7 +167,7 @@ class TestNewSession(SessionTests): def test_one(): raise ValueError() - class TestX: + class TestX(object): def test_method_one(self): pass diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 2e7868d3a..6a8d147ad 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -5,7 +5,7 @@ from _pytest.skipping import MarkEvaluator, folded_skips, pytest_runtest_setup from _pytest.runner import runtestprotocol -class TestEvaluator: +class TestEvaluator(object): def test_no_marker(self, testdir): item = testdir.getitem("def test_func(): pass") evalskipif = MarkEvaluator(item, 'skipif') @@ -114,7 +114,7 @@ class TestEvaluator: def test_skipif_class(self, testdir): item, = testdir.getitems(""" import pytest - class TestClass: + class TestClass(object): pytestmark = pytest.mark.skipif("config._hackxyz") def test_func(self): pass @@ -126,7 +126,7 @@ class TestEvaluator: assert expl == "condition: config._hackxyz" -class TestXFail: +class TestXFail(object): @pytest.mark.parametrize('strict', [True, False]) def test_xfail_simple(self, testdir, strict): @@ -452,7 +452,7 @@ class TestXFail: assert result.ret == (1 if strict else 0) -class TestXFailwithSetupTeardown: +class TestXFailwithSetupTeardown(object): def test_failing_setup_issue9(self, testdir): testdir.makepyfile(""" import pytest @@ -484,7 +484,7 @@ class TestXFailwithSetupTeardown: ]) -class TestSkip: +class TestSkip(object): def test_skip_class(self, testdir): testdir.makepyfile(""" import pytest @@ -581,7 +581,7 @@ class TestSkip: "*1 skipped*", ]) -class TestSkipif: +class TestSkipif(object): def test_skipif_conditional(self, testdir): item = testdir.getitem(""" import pytest @@ -648,7 +648,7 @@ def test_skipif_class(testdir): p = testdir.makepyfile(""" import pytest - class TestClass: + class TestClass(object): pytestmark = pytest.mark.skipif("True") def test_that(self): assert 0 @@ -667,7 +667,7 @@ def test_skip_reasons_folding(): message = "justso" longrepr = (path, lineno, message) - class X: + class X(object): pass ev1 = X() ev1.when = "execute" @@ -694,7 +694,7 @@ def test_skipped_reasons_functional(testdir): doskip() def test_func(): pass - class TestClass: + class TestClass(object): def test_method(self): doskip() """, @@ -892,7 +892,7 @@ def test_imperativeskip_on_xfail_test(testdir): *2 skipped* """) -class TestBooleanCondition: +class TestBooleanCondition(object): def test_skipif(self, testdir): testdir.makepyfile(""" import pytest diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 3efd7b1f9..77fb3b154 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -16,7 +16,7 @@ from _pytest.terminal import build_summary_stats_line, _plugin_nameversions DistInfo = collections.namedtuple('DistInfo', ['project_name', 'version']) -class Option: +class Option(object): def __init__(self, verbose=False, fulltrace=False): self.verbose = verbose self.fulltrace = fulltrace @@ -56,7 +56,7 @@ def test_plugin_nameversion(input, expected): assert result == expected -class TestTerminal: +class TestTerminal(object): def test_pass_skip_fail(self, testdir, option): testdir.makepyfile(""" import pytest @@ -127,7 +127,7 @@ class TestTerminal: def test_itemreport_subclasses_show_subclassed_file(self, testdir): testdir.makepyfile(test_p1=""" - class BaseTests: + class BaseTests(object): def test_p1(self): pass class TestClass(BaseTests): @@ -151,7 +151,7 @@ class TestTerminal: def test_itemreport_directclasses_not_shown_as_subclasses(self, testdir): a = testdir.mkpydir("a123") a.join("test_hello123.py").write(_pytest._code.Source(""" - class TestClass: + class TestClass(object): def test_method(self): pass """)) @@ -204,7 +204,7 @@ class TestTerminal: result.stdout.fnmatch_lines(['*KeyboardInterrupt*']) -class TestCollectonly: +class TestCollectonly(object): def test_collectonly_basic(self, testdir): testdir.makepyfile(""" def test_func(): @@ -249,7 +249,7 @@ class TestCollectonly: p = testdir.makepyfile(""" def test_func1(): pass - class TestClass: + class TestClass(object): def test_method(self): pass """) @@ -310,7 +310,7 @@ def test_repr_python_version(monkeypatch): finally: monkeypatch.undo() # do this early as pytest can get confused -class TestFixtureReporting: +class TestFixtureReporting(object): def test_setup_fixture_error(self, testdir): testdir.makepyfile(""" def setup_function(function): @@ -395,7 +395,7 @@ class TestFixtureReporting: "*1 failed*", ]) -class TestTerminalFunctional: +class TestTerminalFunctional(object): def test_deselected(self, testdir): testpath = testdir.makepyfile(""" def test_one(): @@ -431,7 +431,7 @@ class TestTerminalFunctional: p1 = testdir.makepyfile(""" def test_passes(): pass - class TestClass: + class TestClass(object): def test_method(self): pass """) @@ -487,7 +487,7 @@ class TestTerminalFunctional: raise ValueError() def test_pass(): pass - class TestClass: + class TestClass(object): def test_skip(self): pytest.skip("hello") def test_gen(): @@ -612,8 +612,8 @@ def test_color_yes_collection_on_non_atty(testdir, verbose): def test_getreportopt(): - class config: - class option: + class config(object): + class option(object): reportchars = "" disablepytestwarnings = True @@ -683,7 +683,7 @@ def test_traceconfig(testdir, monkeypatch): assert result.ret == EXIT_NOTESTSCOLLECTED -class TestGenericReporting: +class TestGenericReporting(object): """ this test class can be subclassed with a different option provider to run e.g. distributed tests. """ diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 232acb6d2..32ac76331 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -34,7 +34,7 @@ def test_ensuretemp(recwarn): assert d1 == d2 assert d1.check(dir=1) -class TestTempdirHandler: +class TestTempdirHandler(object): def test_mktemp(self, testdir): from _pytest.tmpdir import TempdirFactory config = testdir.parseconfig() @@ -48,7 +48,7 @@ class TestTempdirHandler: assert tmp2.relto(t.getbasetemp()).startswith("this") assert tmp2 != tmp -class TestConfigTmpdir: +class TestConfigTmpdir(object): def test_getbasetemp_custom_removes_old(self, testdir): mytemp = testdir.tmpdir.join("xyz") p = testdir.makepyfile(""" diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 9625ae0f8..832ea08cc 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -385,7 +385,7 @@ def test_trial_testfunction_todo_property(testdir): reprec.assertoutcome(skipped=1) -class TestTrialUnittest: +class TestTrialUnittest(object): def setup_class(cls): cls.ut = pytest.importorskip("twisted.trial.unittest") @@ -704,7 +704,7 @@ def test_unittest_setup_interaction(testdir, fix_type, stmt): def test_non_unittest_no_setupclass_support(testdir): testpath = testdir.makepyfile(""" - class TestFoo: + class TestFoo(object): x = 0 @classmethod