From 2a2b8cee09a1a6b706423f7655129e17d7e0383d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 18 Oct 2016 22:58:31 -0200 Subject: [PATCH 01/22] Fix false-positive warnings from assertion rewrite hook Fix #2005 --- CHANGELOG.rst | 11 ++++++++++- _pytest/assertion/rewrite.py | 7 ++++++- testing/test_assertrewrite.py | 16 ++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2fb15aa11..3abfc04f6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,15 @@ * When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_). Thanks `@nicoddemus`_ for the PR. +* Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but + were later marked explicitly by ``pytest.register_assert_rewrite`` + or implicitly as a plugin (`#2005`_). + Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR. + +* + +* + * @@ -21,7 +30,7 @@ .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 .. _#1998: https://github.com/pytest-dev/pytest/issues/1998 .. _#2004: https://github.com/pytest-dev/pytest/issues/2004 - +.. _#2005: https://github.com/pytest-dev/pytest/issues/2005 3.0.3 diff --git a/_pytest/assertion/rewrite.py b/_pytest/assertion/rewrite.py index 80d6ee3ba..6b4c1f483 100644 --- a/_pytest/assertion/rewrite.py +++ b/_pytest/assertion/rewrite.py @@ -51,6 +51,7 @@ class AssertionRewritingHook(object): self.fnpats = config.getini("python_files") self.session = None self.modules = {} + self._rewritten_names = set() self._register_with_pkg_resources() self._must_rewrite = set() @@ -92,6 +93,8 @@ class AssertionRewritingHook(object): if not self._should_rewrite(name, fn_pypath, state): return None + self._rewritten_names.add(name) + # The requested module looks like a test file, so rewrite it. This is # the most magical part of the process: load the source, rewrite the # asserts, and load the rewritten source. We also cache the rewritten @@ -178,7 +181,9 @@ class AssertionRewritingHook(object): """ already_imported = set(names).intersection(set(sys.modules)) if already_imported: - self._warn_already_imported(already_imported) + for name in names: + if name not in self._rewritten_names: + self._warn_already_imported(already_imported) self._must_rewrite.update(names) def _warn_already_imported(self, names): diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index cedd435f8..e72266a18 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -543,6 +543,22 @@ def test_rewritten(): ''') assert testdir.runpytest_subprocess().ret == 0 + def test_remember_rewritten_modules(self, pytestconfig, testdir, monkeypatch): + """ + AssertionRewriteHook should remember rewritten modules so it + doesn't give false positives (#2005). + """ + monkeypatch.syspath_prepend(testdir.tmpdir) + testdir.makepyfile(test_remember_rewritten_modules='') + warnings = [] + hook = AssertionRewritingHook(pytestconfig) + monkeypatch.setattr(hook.config, 'warn', lambda code, msg: warnings.append(msg)) + hook.find_module('test_remember_rewritten_modules') + hook.load_module('test_remember_rewritten_modules') + hook.mark_rewrite('test_remember_rewritten_modules') + hook.mark_rewrite('test_remember_rewritten_modules') + assert warnings == [] + class TestAssertionRewriteHookDetails(object): def test_loader_is_package_false_for_module(self, testdir): From 37dcdfbc58441a266272d8ab4a8cc985ca51fb84 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 20 Oct 2016 23:39:28 -0200 Subject: [PATCH 02/22] Re-enable docstring testing of _pytest modules on CI * Fix doctests * List one env per line in tox.ini * "doctesting" tox env now also tests docstrings using doctest --- _pytest/python.py | 22 +++++++++++++--------- _pytest/recwarn.py | 7 ++++++- appveyor.yml | 9 +++++---- tox.ini | 28 ++++++++++++++++++---------- 4 files changed, 42 insertions(+), 24 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index 62d2896ea..a42e7185e 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1105,7 +1105,9 @@ def raises(expected_exception, *args, **kwargs): >>> with raises(ZeroDivisionError, message="Expecting ZeroDivisionError"): ... pass - ... Failed: Expecting ZeroDivisionError + Traceback (most recent call last): + ... + Failed: Expecting ZeroDivisionError .. note:: @@ -1116,19 +1118,21 @@ def raises(expected_exception, *args, **kwargs): Lines of code after that, within the scope of the context manager will not be executed. For example:: - >>> with raises(OSError) as exc_info: - assert 1 == 1 # this will execute as expected - raise OSError(errno.EEXISTS, 'directory exists') - assert exc_info.value.errno == errno.EEXISTS # this will not execute + >>> value = 15 + >>> 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 Instead, the following approach must be taken (note the difference in scope):: - >>> with raises(OSError) as exc_info: - assert 1 == 1 # this will execute as expected - raise OSError(errno.EEXISTS, 'directory exists') + >>> with raises(ValueError) as exc_info: + ... if value > 10: + ... raise ValueError("value must be <= 10") + ... + >>> assert str(exc_info.value) == "value must be <= 10" - assert exc_info.value.errno == errno.EEXISTS # this will now execute Or you can specify a callable by passing a to-be-called lambda:: diff --git a/_pytest/recwarn.py b/_pytest/recwarn.py index a89474c03..87823bfbc 100644 --- a/_pytest/recwarn.py +++ b/_pytest/recwarn.py @@ -36,8 +36,13 @@ def deprecated_call(func=None, *args, **kwargs): This function can be used as a context manager:: + >>> import warnings + >>> def api_call_v2(): + ... warnings.warn('use v3 of this api', DeprecationWarning) + ... return 200 + >>> with deprecated_call(): - ... myobject.deprecated_method() + ... assert api_call_v2() == 200 Note: we cannot use WarningsRecorder here because it is still subject to the mechanism that prevents warnings of the same type from being diff --git a/appveyor.yml b/appveyor.yml index 3144f2095..cd95611cb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -20,10 +20,11 @@ install: # install pypy using choco (redirect to a file and write to console in case # choco install returns non-zero, because choco install python.pypy is too # noisy) - - choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1) - - set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy - - echo PyPy installed - - pypy --version + # pypy is disabled until #1963 gets fixed + #- choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1) + #- set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy + #- echo PyPy installed + #- pypy --version - C:\Python35\python -m pip install tox diff --git a/tox.ini b/tox.ini index ca55e7813..53a76180b 100644 --- a/tox.ini +++ b/tox.ini @@ -3,9 +3,18 @@ minversion=2.0 distshare={homedir}/.tox/distshare # make sure to update enviroment list on appveyor.yml envlist= - linting,py26,py27,py33,py34,py35,pypy, - {py27,py35}-{pexpect,xdist,trial}, - py27-nobyte,doctesting,freeze,docs + linting + py26 + py27 + py33 + py34 + py35 + pypy + {py27,py35}-{pexpect,xdist,trial} + py27-nobyte + doctesting + freeze + docs [testenv] commands= pytest --lsof -rfsxX {posargs:testing} @@ -90,10 +99,6 @@ deps={[testenv:py27-trial]deps} commands= pytest -ra {posargs:testing/test_unittest.py} -[testenv:doctest] -commands=pytest --doctest-modules _pytest -deps= - [testenv:docs] basepython=python changedir=doc/en @@ -106,9 +111,12 @@ commands= [testenv:doctesting] basepython = python -changedir=doc/en +usedevelop=True +skipsdist=True deps=PyYAML -commands= pytest -rfsxX {posargs} +commands= + pytest -rfsxX doc/en + pytest --doctest-modules {toxinidir}/_pytest [testenv:regen] changedir=doc/en @@ -139,7 +147,7 @@ commands= [testenv:coveralls] passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH COVERALLS_REPO_TOKEN usedevelop=True -basepython=python3.4 +basepython=python3.5 changedir=. deps = {[testenv]deps} From 11ec96a927e5571f39ab290d31fbb41200c791b8 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 21 Oct 2016 12:10:35 -0400 Subject: [PATCH 03/22] Extract child flush as a staticmethod --- testing/test_pdb.py | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/testing/test_pdb.py b/testing/test_pdb.py index d79d71262..aecf51bbc 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -76,6 +76,10 @@ class TestPDB: rest = child.read().decode("utf8") assert "1 failed" in rest assert "def test_1" not in rest + self.flush(child) + + @staticmethod + def flush(child): if child.isalive(): child.wait() @@ -95,8 +99,7 @@ class TestPDB: child.sendeof() rest = child.read().decode("utf8") assert 'debug.me' in rest - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_capture(self, testdir): p1 = testdir.makepyfile(""" @@ -111,8 +114,7 @@ class TestPDB: rest = child.read().decode("utf8") assert "1 failed" in rest assert "getrekt" not in rest - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_exception(self, testdir): p1 = testdir.makepyfile(""" @@ -130,8 +132,7 @@ class TestPDB: child.expect(".*function") child.sendeof() child.expect("1 failed") - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_on_collection_issue181(self, testdir): p1 = testdir.makepyfile(""" @@ -143,8 +144,7 @@ class TestPDB: child.expect("(Pdb)") child.sendeof() child.expect("1 error") - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_on_internal_error(self, testdir): testdir.makeconftest(""" @@ -156,8 +156,7 @@ class TestPDB: #child.expect(".*import pytest.*") child.expect("(Pdb)") child.sendeof() - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_capturing_simple(self, testdir): p1 = testdir.makepyfile(""" @@ -177,8 +176,7 @@ class TestPDB: assert "1 failed" in rest assert "def test_1" in rest assert "hello17" in rest # out is captured - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_set_trace_interception(self, testdir): p1 = testdir.makepyfile(""" @@ -193,8 +191,7 @@ class TestPDB: rest = child.read().decode("utf8") assert "1 failed" in rest assert "reading from stdin while output" not in rest - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_and_capsys(self, testdir): p1 = testdir.makepyfile(""" @@ -209,8 +206,7 @@ class TestPDB: child.expect("hello1") child.sendeof() child.read() - if child.isalive(): - child.wait() + self.flush(child) def test_set_trace_capturing_afterwards(self, testdir): p1 = testdir.makepyfile(""" @@ -229,8 +225,7 @@ class TestPDB: child.expect("hello") child.sendeof() child.read() - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_doctest(self, testdir): p1 = testdir.makepyfile(""" @@ -249,8 +244,7 @@ class TestPDB: child.sendeof() rest = child.read().decode("utf8") assert "1 failed" in rest - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_interaction_capturing_twice(self, testdir): p1 = testdir.makepyfile(""" @@ -276,8 +270,7 @@ class TestPDB: assert "def test_1" in rest assert "hello17" in rest # out is captured assert "hello18" in rest # out is captured - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_used_outside_test(self, testdir): p1 = testdir.makepyfile(""" @@ -331,8 +324,7 @@ class TestPDB: child.expect("enter_pdb_hook") child.send('c\n') child.sendeof() - if child.isalive(): - child.wait() + self.flush(child) def test_pdb_custom_cls(self, testdir): called = [] From 60a347aeb51582f6fee87497dfdb4f079a6f5c82 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 21 Oct 2016 12:11:35 -0400 Subject: [PATCH 04/22] Also use flush where wait was called unconditionally --- testing/test_pdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/test_pdb.py b/testing/test_pdb.py index aecf51bbc..062ae1fb9 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -281,7 +281,7 @@ class TestPDB: child = testdir.spawn("%s %s" %(sys.executable, p1)) child.expect("x = 5") child.sendeof() - child.wait() + self.flush(child) def test_pdb_used_in_generate_tests(self, testdir): p1 = testdir.makepyfile(""" @@ -295,7 +295,7 @@ class TestPDB: child = testdir.spawn_pytest(str(p1)) child.expect("x = 5") child.sendeof() - child.wait() + self.flush(child) def test_pdb_collection_failure_is_shown(self, testdir): p1 = testdir.makepyfile("""xxx """) From f2c01c5407f3c7853bdd463b8aa2856e3a6398e1 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 21 Oct 2016 12:36:42 -0400 Subject: [PATCH 05/22] Restore pexpect tests and bypass isalive/wait on macOS. Ref #2022. --- _pytest/pytester.py | 2 -- testing/test_pdb.py | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/_pytest/pytester.py b/_pytest/pytester.py index 651160cc7..a8bb39794 100644 --- a/_pytest/pytester.py +++ b/_pytest/pytester.py @@ -1002,8 +1002,6 @@ class Testdir: pexpect = pytest.importorskip("pexpect", "3.0") if hasattr(sys, 'pypy_version_info') and '64' in platform.machine(): pytest.skip("pypy-64 bit not supported") - if sys.platform == "darwin": - pytest.xfail("pexpect does not work reliably on darwin?!") if sys.platform.startswith("freebsd"): pytest.xfail("pexpect does not work reliably on freebsd") logfile = self.tmpdir.join("spawn.out").open("wb") diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 062ae1fb9..b22f5128e 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -1,4 +1,5 @@ import sys +import platform import _pytest._code import pytest @@ -80,6 +81,8 @@ class TestPDB: @staticmethod def flush(child): + if platform.system() == 'Darwin': + return if child.isalive(): child.wait() From 6f93ffb5d4de88fe6ad57d3195938d538988e45b Mon Sep 17 00:00:00 2001 From: Mathieu Clabaut Date: Sun, 30 Oct 2016 09:46:08 +0100 Subject: [PATCH 06/22] Report teardown output on test failure Until now, teardown stdout/stderr output was not reported upon test failure. However such output is sometime necessary to understand the failure. fix #442 --- AUTHORS | 1 + CHANGELOG.rst | 5 ++++- _pytest/terminal.py | 12 ++++++++++++ testing/test_terminal.py | 25 +++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 910a82e49..ae67fe429 100644 --- a/AUTHORS +++ b/AUTHORS @@ -90,6 +90,7 @@ Markus Unterwaditzer Martijn Faassen Martin K. Scherer Martin Prusse +Mathieu Clabaut Matt Bachmann Matt Williams Matthias Hafner diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3abfc04f6..dfedb0419 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -17,7 +17,8 @@ or implicitly as a plugin (`#2005`_). Thanks `@RonnyPfannschmidt`_ for the report and `@nicoddemus`_ for the PR. -* +* Report teardown output on test failure (`#442`_). + Thanks `@matclab`_ or the PR. * @@ -26,7 +27,9 @@ .. _@cwitty: https://github.com/cwitty .. _@okulynyak: https://github.com/okulynyak +.. _@matclab: https://github.com/matclab +.. _#442: https://github.com/pytest-dev/pytest/issues/442 .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 .. _#1998: https://github.com/pytest-dev/pytest/issues/1998 .. _#2004: https://github.com/pytest-dev/pytest/issues/2004 diff --git a/_pytest/terminal.py b/_pytest/terminal.py index fdbe4ec36..16bf75733 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -458,6 +458,15 @@ class TerminalReporter: self.write_sep("_", msg) self._outrep_summary(rep) + def print_teardown_sections(self, rep): + for secname, content in rep.sections: + if 'teardown' in secname: + self._tw.sep('-', secname) + if content[-1:] == "\n": + content = content[:-1] + self._tw.line(content) + + def summary_failures(self): if self.config.option.tbstyle != "no": reports = self.getreports('failed') @@ -473,6 +482,9 @@ class TerminalReporter: markup = {'red': True, 'bold': True} self.write_sep("_", msg, **markup) self._outrep_summary(rep) + for report in self.getreports(''): + if report.nodeid == rep.nodeid and report.when == 'teardown': + self.print_teardown_sections(report) def summary_errors(self): if self.config.option.tbstyle != "no": diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 66214c80e..3efd7b1f9 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -370,6 +370,31 @@ class TestFixtureReporting: "*1 failed*1 error*", ]) + def test_setup_teardown_output_and_test_failure(self, testdir): + """ Test for issue #442 """ + testdir.makepyfile(""" + def setup_function(function): + print ("setup func") + + def test_fail(): + assert 0, "failingfunc" + + def teardown_function(function): + print ("teardown func") + """) + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*test_fail*", + "*def test_fail():", + "*failingfunc*", + "*Captured stdout setup*", + "*setup func*", + "*Captured stdout teardown*", + "*teardown func*", + + "*1 failed*", + ]) + class TestTerminalFunctional: def test_deselected(self, testdir): testpath = testdir.makepyfile(""" From 382fa231a1c6a959e22c26eac1fcc42996314bd4 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 31 Oct 2016 06:49:06 +0100 Subject: [PATCH 07/22] Update "Next Open Trainings" --- doc/en/talks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/talks.rst b/doc/en/talks.rst index 1572832f0..46188bbe7 100644 --- a/doc/en/talks.rst +++ b/doc/en/talks.rst @@ -4,7 +4,7 @@ Talks and Tutorials .. sidebar:: Next Open Trainings - `professional testing with pytest and tox `_, 27-29th June 2016, Freiburg, Germany + `pytest workshop `_, 8th December 2016, Bern, Switzerland .. _`funcargs`: funcargs.html From e2bb4f893bd3e512179cdf98d24a9ad2f72411cf Mon Sep 17 00:00:00 2001 From: Georgy Dyuldin Date: Wed, 2 Nov 2016 15:45:40 +0300 Subject: [PATCH 08/22] Fix teardown error message in generated xUnit XML It was "test setup failure" even error happens on test teardown. --- CHANGELOG.rst | 8 +++++--- _pytest/junitxml.py | 6 +++++- testing/test_junitxml.py | 24 ++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dfedb0419..210359fb4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,7 +20,8 @@ * Report teardown output on test failure (`#442`_). Thanks `@matclab`_ or the PR. -* +* Fix teardown error message in generated xUnit XML. + Thanks `@gdyuldin`_ or the PR. * @@ -28,6 +29,7 @@ .. _@cwitty: https://github.com/cwitty .. _@okulynyak: https://github.com/okulynyak .. _@matclab: https://github.com/matclab +.. _@gdyuldin: https://github.com/gdyuldin .. _#442: https://github.com/pytest-dev/pytest/issues/442 .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 @@ -98,7 +100,7 @@ enabled. This allows proper post mortem debugging for all applications which have significant logic in their tearDown machinery (`#1890`_). Thanks `@mbyt`_ for the PR. - + * Fix use of deprecated ``getfuncargvalue`` method in the internal doctest plugin. Thanks `@ViviCoder`_ for the report (`#1898`_). @@ -395,7 +397,7 @@ time or change existing behaviors in order to make them less surprising/more use * Refined logic for determining the ``rootdir``, considering only valid paths which fixes a number of issues: `#1594`_, `#1435`_ and `#1471`_. - Updated the documentation according to current behavior. Thanks to + Updated the documentation according to current behavior. Thanks to `@blueyed`_, `@davehunt`_ and `@matthiasha`_ for the PR. * Always include full assertion explanation. The previous behaviour was hiding diff --git a/_pytest/junitxml.py b/_pytest/junitxml.py index da190ff21..97d0675a6 100644 --- a/_pytest/junitxml.py +++ b/_pytest/junitxml.py @@ -156,8 +156,12 @@ class _NodeReporter(object): Junit.skipped, "collection skipped", report.longrepr) def append_error(self, report): + if getattr(report, 'when', None) == 'teardown': + msg = "test teardown failure" + else: + msg = "test setup failure" self._add_simple( - Junit.error, "test setup failure", report.longrepr) + Junit.error, msg, report.longrepr) self._write_captured_output(report) def append_skipped(self, report): diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index aec2741f1..85e49e451 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -165,6 +165,30 @@ class TestPython: fnode.assert_attr(message="test setup failure") assert "ValueError" in fnode.toxml() + def test_teardown_error(self, testdir): + testdir.makepyfile(""" + import pytest + + @pytest.fixture + def arg(): + yield + raise ValueError() + def test_function(arg): + pass + """) + result, dom = runandparse(testdir) + assert result.ret + node = dom.find_first_by_tag("testsuite") + tnode = node.find_first_by_tag("testcase") + tnode.assert_attr( + file="test_teardown_error.py", + line="6", + classname="test_teardown_error", + name="test_function") + fnode = tnode.find_first_by_tag("error") + fnode.assert_attr(message="test teardown failure") + assert "ValueError" in fnode.toxml() + def test_skip_contains_name_reason(self, testdir): testdir.makepyfile(""" import pytest From 006a901b861e9de28daf11ab4b10b87bed18aba1 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 27 Oct 2016 21:15:05 -0200 Subject: [PATCH 09/22] Properly handle exceptions in multiprocessing tasks Fix #1984 --- CHANGELOG.rst | 11 ++++++++- _pytest/_code/code.py | 15 ++++++++---- testing/code/test_excinfo.py | 44 ++++++++++++++++++++++++++++++++++++ testing/test_assertion.py | 31 +++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 210359fb4..44a7f9a39 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,7 +6,7 @@ * Import errors when collecting test modules now display the full traceback (`#1976`_). Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR. -* Fix confusing command-line help message for custom options with two or more `metavar` properties (`#2004`_). +* Fix confusing command-line help message for custom options with two or more ``metavar`` properties (`#2004`_). Thanks `@okulynyak`_ and `@davehunt`_ for the report and `@nicoddemus`_ for the PR. * When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_). @@ -23,9 +23,17 @@ * Fix teardown error message in generated xUnit XML. Thanks `@gdyuldin`_ or the PR. +* Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_). + Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR. + +* + +* + * +.. _@adborden: https://github.com/adborden .. _@cwitty: https://github.com/cwitty .. _@okulynyak: https://github.com/okulynyak .. _@matclab: https://github.com/matclab @@ -33,6 +41,7 @@ .. _#442: https://github.com/pytest-dev/pytest/issues/442 .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 +.. _#1984: https://github.com/pytest-dev/pytest/issues/1984 .. _#1998: https://github.com/pytest-dev/pytest/issues/1998 .. _#2004: https://github.com/pytest-dev/pytest/issues/2004 .. _#2005: https://github.com/pytest-dev/pytest/issues/2005 diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py index 30e12940b..416ee0b1b 100644 --- a/_pytest/_code/code.py +++ b/_pytest/_code/code.py @@ -623,16 +623,23 @@ class FormattedExcinfo(object): e = excinfo.value descr = None while e is not None: - reprtraceback = self.repr_traceback(excinfo) - reprcrash = excinfo._getreprcrash() + if excinfo: + reprtraceback = self.repr_traceback(excinfo) + reprcrash = excinfo._getreprcrash() + else: + # fallback to native repr if the exception doesn't have a traceback: + # ExceptionInfo objects require a full traceback to work + reprtraceback = ReprTracebackNative(py.std.traceback.format_exception(type(e), e, None)) + reprcrash = None + repr_chain += [(reprtraceback, reprcrash, descr)] if e.__cause__ is not None: e = e.__cause__ - excinfo = ExceptionInfo((type(e), e, e.__traceback__)) + excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None descr = 'The above exception was the direct cause of the following exception:' elif e.__context__ is not None: e = e.__context__ - excinfo = ExceptionInfo((type(e), e, e.__traceback__)) + excinfo = ExceptionInfo((type(e), e, e.__traceback__)) if e.__traceback__ else None descr = 'During handling of the above exception, another exception occurred:' else: e = None diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 283f8eb76..3aae9c71c 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1050,6 +1050,50 @@ raise ValueError() assert line.endswith('mod.py') assert tw.lines[47] == ":15: AttributeError" + @pytest.mark.skipif("sys.version_info[0] < 3") + @pytest.mark.parametrize('reason, description', [ + ('cause', 'The above exception was the direct cause of the following exception:'), + ('context', 'During handling of the above exception, another exception occurred:'), + ]) + def test_exc_chain_repr_without_traceback(self, importasmod, reason, description): + """ + Handle representation of exception chains where one of the exceptions doesn't have a + real traceback, such as those raised in a subprocess submitted by the multiprocessing + module (#1984). + """ + from _pytest.pytester import LineMatcher + exc_handling_code = ' from e' if reason == 'cause' else '' + mod = importasmod(""" + def f(): + try: + g() + except Exception as e: + raise RuntimeError('runtime problem'){exc_handling_code} + def g(): + raise ValueError('invalid value') + """.format(exc_handling_code=exc_handling_code)) + + with pytest.raises(RuntimeError) as excinfo: + mod.f() + + # emulate the issue described in #1984 + attr = '__%s__' % reason + getattr(excinfo.value, attr).__traceback__ = None + + r = excinfo.getrepr() + tw = py.io.TerminalWriter(stringio=True) + tw.hasmarkup = False + r.toterminal(tw) + + matcher = LineMatcher(tw.stringio.getvalue().splitlines()) + matcher.fnmatch_lines([ + "ValueError: invalid value", + description, + "* except Exception as e:", + "> * raise RuntimeError('runtime problem')" + exc_handling_code, + "E *RuntimeError: runtime problem", + ]) + @pytest.mark.parametrize("style", ["short", "long"]) @pytest.mark.parametrize("encoding", [None, "utf8", "utf16"]) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 2d4761431..48cd26f02 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -749,6 +749,37 @@ def test_traceback_failure(testdir): "*test_traceback_failure.py:4: AssertionError" ]) + +@pytest.mark.skipif(sys.version_info[:2] <= (3, 3), reason='Python 3.4+ shows chained exceptions on multiprocess') +def test_exception_handling_no_traceback(testdir): + """ + Handle chain exceptions in tasks submitted by the multiprocess module (#1984). + """ + p1 = testdir.makepyfile(""" + from multiprocessing import Pool + + def process_task(n): + assert n == 10 + + def multitask_job(): + tasks = [1] + with Pool(processes=1) as pool: + pool.map(process_task, tasks) + + def test_multitask_job(): + multitask_job() + """) + result = testdir.runpytest(p1, "--tb=long") + result.stdout.fnmatch_lines([ + "====* FAILURES *====", + "*multiprocessing.pool.RemoteTraceback:*", + "Traceback (most recent call last):", + "*assert n == 10", + "The above exception was the direct cause of the following exception:", + "> * multitask_job()", + ]) + + @pytest.mark.skipif("'__pypy__' in sys.builtin_module_names or sys.platform.startswith('java')" ) def test_warn_missing(testdir): testdir.makepyfile("") From a190ad27f2664272c52e6beabb9f60f65eaa2143 Mon Sep 17 00:00:00 2001 From: Manuel Jacob Date: Sun, 6 Nov 2016 09:00:04 +0100 Subject: [PATCH 10/22] Change version to be in normal form according to PEP 440. The version is changed from 3.0.4.dev to 3.0.4.dev0. Note that according to PEP 440 these are considered equivalent, but 3.0.4.dev0 is the normal form. This standard was followed when the version was set to 3.0.3.dev0 in commit ee284ec5, but in commit a87b1c79 the version was set to 3.0.4.dev, leaving the development number implicit again. --- CHANGELOG.rst | 4 ++-- _pytest/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 44a7f9a39..0f6f7ad02 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,5 @@ -3.0.4.dev -========= +3.0.4.dev0 +========== * diff --git a/_pytest/__init__.py b/_pytest/__init__.py index d9f72e9b4..b070c40d1 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.4.dev' +__version__ = '3.0.4.dev0' From e46e653794e3b72d7cc02d374086191224221501 Mon Sep 17 00:00:00 2001 From: Dan Wandschneider Date: Mon, 7 Nov 2016 18:24:10 -0800 Subject: [PATCH 11/22] Clean up unittest TestCase objects after tests are complete (#1649). Fix #1649 Users of unittest style TestCases will create expensive objects in setUp. We should clean up TestCase instances that are lying around so that they don't fill up memory. --- AUTHORS | 1 + CHANGELOG.rst | 5 ++++- _pytest/unittest.py | 3 +++ testing/test_unittest.py | 23 +++++++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index ae67fe429..378bac5a4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -36,6 +36,7 @@ Christopher Gilling Daniel Grana Daniel Hahler Daniel Nuri +Daniel Wandschneider Danielle Jenkins Dave Hunt David Díaz-Barquero diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0f6f7ad02..5dada862a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -26,7 +26,8 @@ * Properly handle exceptions in ``multiprocessing`` tasks (`#1984`_). Thanks `@adborden`_ for the report and `@nicoddemus`_ for the PR. -* +* Clean up unittest TestCase objects after tests are complete (`#1649`_). + Thanks `@d_b_w`_ for the report and PR. * @@ -38,6 +39,7 @@ .. _@okulynyak: https://github.com/okulynyak .. _@matclab: https://github.com/matclab .. _@gdyuldin: https://github.com/gdyuldin +.. _@d_b_w: https://github.com/d_b_w .. _#442: https://github.com/pytest-dev/pytest/issues/442 .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 @@ -45,6 +47,7 @@ .. _#1998: https://github.com/pytest-dev/pytest/issues/1998 .. _#2004: https://github.com/pytest-dev/pytest/issues/2004 .. _#2005: https://github.com/pytest-dev/pytest/issues/2005 +.. _#1649: https://github.com/pytest-dev/pytest/issues/1649 3.0.3 diff --git a/_pytest/unittest.py b/_pytest/unittest.py index 47868f448..4355efe70 100644 --- a/_pytest/unittest.py +++ b/_pytest/unittest.py @@ -94,6 +94,9 @@ class TestCaseFunction(pytest.Function): def teardown(self): if hasattr(self._testcase, 'teardown_method'): self._testcase.teardown_method(self._obj) + # Allow garbage collection on TestCase instance attributes. + self._testcase = None + self._obj = None def startTest(self, testcase): pass diff --git a/testing/test_unittest.py b/testing/test_unittest.py index b6be95fa5..9625ae0f8 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1,5 +1,6 @@ from _pytest.main import EXIT_NOTESTSCOLLECTED import pytest +import gc def test_simple_unittest(testdir): testpath = testdir.makepyfile(""" @@ -134,6 +135,28 @@ def test_teardown(testdir): assert passed == 2 assert passed + skipped + failed == 2 +def test_teardown_issue1649(testdir): + """ + Are TestCase objects cleaned up? Often unittest TestCase objects set + attributes that are large and expensive during setUp. + + The TestCase will not be cleaned up if the test fails, because it + would then exist in the stackframe. + """ + testpath = testdir.makepyfile(""" + import unittest + class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase): + def setUp(self): + self.an_expensive_object = 1 + def test_demo(self): + pass + + """) + testdir.inline_run("-s", testpath) + gc.collect() + for obj in gc.get_objects(): + assert type(obj).__name__ != 'TestCaseObjectsShouldBeCleanedUp' + @pytest.mark.skipif("sys.version_info < (2,7)") def test_unittest_skip_issue148(testdir): testpath = testdir.makepyfile(""" From 1e5b21cd6180009939130f6169c936427d0d4572 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 18 Oct 2016 00:56:44 +0200 Subject: [PATCH 12/22] Fix memory leak with pytest.raises by using weakref --- AUTHORS | 1 + CHANGELOG.rst | 3 +++ _pytest/_code/code.py | 5 +++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 378bac5a4..6de0a112b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -99,6 +99,7 @@ mbyt Michael Aquilina Michael Birtwell Michael Droettboom +Michael Seifert Mike Lundy Nicolas Delaby Oleg Pidsadnyi diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5dada862a..fb5395731 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,6 +12,9 @@ * When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_). Thanks `@nicoddemus`_ for the PR. +* Fixed memory leak in the RaisesContext (pytest.raises) (`#1965`_). + Thanks `@MSeifert04`_ for the report the PR. + * Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but were later marked explicitly by ``pytest.register_assert_rewrite`` or implicitly as a plugin (`#2005`_). diff --git a/_pytest/_code/code.py b/_pytest/_code/code.py index 416ee0b1b..5b4237939 100644 --- a/_pytest/_code/code.py +++ b/_pytest/_code/code.py @@ -1,6 +1,7 @@ import sys from inspect import CO_VARARGS, CO_VARKEYWORDS import re +from weakref import ref import py builtin_repr = repr @@ -230,7 +231,7 @@ class TracebackEntry(object): return False if py.builtin.callable(tbh): - return tbh(self._excinfo) + return tbh(None if self._excinfo is None else self._excinfo()) else: return tbh @@ -370,7 +371,7 @@ class ExceptionInfo(object): #: the exception type name self.typename = self.type.__name__ #: the exception traceback (_pytest._code.Traceback instance) - self.traceback = _pytest._code.Traceback(self.tb, excinfo=self) + self.traceback = _pytest._code.Traceback(self.tb, excinfo=ref(self)) def __repr__(self): return "" % (self.typename, len(self.traceback)) From 552c7d4286f582255752730d2c512d0aff4a44c4 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Tue, 18 Oct 2016 01:22:53 +0200 Subject: [PATCH 13/22] added test (thanks @nicoddemus) and added links in Changelog --- CHANGELOG.rst | 10 ++++++---- testing/python/raises.py | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fb5395731..35a54de4b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,7 +13,7 @@ Thanks `@nicoddemus`_ for the PR. * Fixed memory leak in the RaisesContext (pytest.raises) (`#1965`_). - Thanks `@MSeifert04`_ for the report the PR. + Thanks `@MSeifert04`_ for the report and the PR. * Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but were later marked explicitly by ``pytest.register_assert_rewrite`` @@ -39,12 +39,14 @@ .. _@adborden: https://github.com/adborden .. _@cwitty: https://github.com/cwitty -.. _@okulynyak: https://github.com/okulynyak -.. _@matclab: https://github.com/matclab -.. _@gdyuldin: https://github.com/gdyuldin .. _@d_b_w: https://github.com/d_b_w +.. _@gdyuldin: https://github.com/gdyuldin +.. _@matclab: https://github.com/matclab +.. _@MSeifert04: https://github.com/MSeifert04 +.. _@okulynyak: https://github.com/okulynyak .. _#442: https://github.com/pytest-dev/pytest/issues/442 +.. _#1965: https://github.com/pytest-dev/pytest/issues/1965 .. _#1976: https://github.com/pytest-dev/pytest/issues/1976 .. _#1984: https://github.com/pytest-dev/pytest/issues/1984 .. _#1998: https://github.com/pytest-dev/pytest/issues/1998 diff --git a/testing/python/raises.py b/testing/python/raises.py index 59fd622fd..80c3df2ab 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -96,3 +96,21 @@ class TestRaises: assert e.msg == message else: assert False, "Expected pytest.raises.Exception" + + @pytest.mark.parametrize('method', ['function', 'with']) + def test_raises_memoryleak(self, method): + import weakref + + class T: + def __call__(self): + raise ValueError + + t = T() + if method == 'function': + pytest.raises(ValueError, t) + else: + with pytest.raises(ValueError): + t() + + t = weakref.ref(t) + assert t() is None From 1130b9f742d053a429149e56b8a0c8aec72a9968 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 8 Nov 2016 21:34:45 -0200 Subject: [PATCH 14/22] Fix the stubborn test about cyclic references left by pytest.raises In Python 2, a context manager's __exit__() leaves sys.exc_info with the exception values even when it was supposed to suppress the exception, so we explicitly call sys.exc_clear() which removes the traceback and allow the object to be released. Also updated the test to not depend on the immediate destruction of the object but instead to ensure it is not being tracked as a cyclic reference. Fix #1965 --- CHANGELOG.rst | 5 ++++- _pytest/python.py | 6 +++++- testing/python/raises.py | 22 +++++++++++++++++----- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 35a54de4b..e88eb5b09 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,7 +12,10 @@ * When loading plugins, import errors which contain non-ascii messages are now properly handled in Python 2 (`#1998`_). Thanks `@nicoddemus`_ for the PR. -* Fixed memory leak in the RaisesContext (pytest.raises) (`#1965`_). +* Fixed cyclic reference when ``pytest.raises`` is used in context-manager form (`#1965`_). Also as a + result of this fix, ``sys.exc_info()`` is left empty in both context-manager and function call usages. + Previously, ``sys.exc_info`` would contain the exception caught by the context manager, + even when the expected exception occurred. Thanks `@MSeifert04`_ for the report and the PR. * Fixed false-positives warnings from assertion rewrite hook for modules that were rewritten but diff --git a/_pytest/python.py b/_pytest/python.py index a42e7185e..18432c1e7 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -1237,7 +1237,11 @@ class RaisesContext(object): exc_type, value, traceback = tp tp = exc_type, exc_type(value), traceback self.excinfo.__init__(tp) - return issubclass(self.excinfo.type, self.expected_exception) + suppress_exception = issubclass(self.excinfo.type, self.expected_exception) + if sys.version_info[0] == 2 and suppress_exception: + sys.exc_clear() + return suppress_exception + # builtin pytest.approx helper diff --git a/testing/python/raises.py b/testing/python/raises.py index 80c3df2ab..8f141cfa1 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -1,4 +1,6 @@ import pytest +import sys + class TestRaises: def test_raises(self): @@ -98,10 +100,13 @@ class TestRaises: assert False, "Expected pytest.raises.Exception" @pytest.mark.parametrize('method', ['function', 'with']) - def test_raises_memoryleak(self, method): - import weakref + def test_raises_cyclic_reference(self, method): + """ + Ensure pytest.raises does not leave a reference cycle (#1965). + """ + import gc - class T: + class T(object): def __call__(self): raise ValueError @@ -112,5 +117,12 @@ class TestRaises: with pytest.raises(ValueError): t() - t = weakref.ref(t) - assert t() is None + # ensure both forms of pytest.raises don't leave exceptions in sys.exc_info() + assert sys.exc_info() == (None, None, None) + + del t + + # ensure the t instance is not stuck in a cyclic reference + for o in gc.get_objects(): + assert type(o) is not T + From ff72db2f1a9ddd656738935909d1f83b71b2fd07 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 9 Nov 2016 19:38:11 -0200 Subject: [PATCH 15/22] Version bump to 3.0.4, CHANGELOG, announcement --- CHANGELOG.rst | 10 ++-------- _pytest/__init__.py | 2 +- doc/en/announce/index.rst | 1 + doc/en/announce/release-3.0.4.rst | 29 +++++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 doc/en/announce/release-3.0.4.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e88eb5b09..178e5406f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,7 +1,5 @@ -3.0.4.dev0 -========== - -* +3.0.4 +===== * Import errors when collecting test modules now display the full traceback (`#1976`_). Thanks `@cwitty`_ for the report and `@nicoddemus`_ for the PR. @@ -35,10 +33,6 @@ * Clean up unittest TestCase objects after tests are complete (`#1649`_). Thanks `@d_b_w`_ for the report and PR. -* - -* - .. _@adborden: https://github.com/adborden .. _@cwitty: https://github.com/cwitty diff --git a/_pytest/__init__.py b/_pytest/__init__.py index b070c40d1..97cf2527b 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.4.dev0' +__version__ = '3.0.4' diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 9cb4527ad..a1bf7bed7 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.0.4 release-3.0.3 release-3.0.2 release-3.0.1 diff --git a/doc/en/announce/release-3.0.4.rst b/doc/en/announce/release-3.0.4.rst new file mode 100644 index 000000000..852057037 --- /dev/null +++ b/doc/en/announce/release-3.0.4.rst @@ -0,0 +1,29 @@ +pytest-3.0.4 +============ + +pytest 3.0.4 has just been released to PyPI. + +This release fixes some regressions and bugs reported in the last version, +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: + +* Bruno Oliveira +* Dan Wandschneider +* Florian Bruhin +* Georgy Dyuldin +* Grigorii Eremeev +* Jason R. Coombs +* Manuel Jacob +* Mathieu Clabaut +* Michael Seifert +* Nikolaus Rath +* Ronny Pfannschmidt +* Tom V + +Happy testing, +The pytest Development Team From ab274299fee959e64a4a749806e1124eb5d2f29b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 9 Nov 2016 16:44:58 -0500 Subject: [PATCH 16/22] Regen doc for 3.0.4 --- 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 | 14 +++++++++----- 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, 63 insertions(+), 59 deletions(-) diff --git a/doc/en/assert.rst b/doc/en/assert.rst index 59d810c1d..675dece57 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 d94020fdd..4baae4c96 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 afec55fdc..454655d7e 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 1cdae8a78..5a1122515 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.3, py-1.4.31, pluggy-0.4.0 + 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 diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index f0c9b0e5a..2f5f29e0d 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 4fc9bc503..e0670aeba 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 a5e6226ae..fee2b6dcc 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 15ec22e2b..f1e9a976d 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.3, py-1.4.31, pluggy-0.4.0 + 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 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.3, py-1.4.31, pluggy-0.4.0 + 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 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.3, py-1.4.31, pluggy-0.4.0 + 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 0 items diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 93704ea87..061097cc3 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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:1190>:1: ValueError + <0-codegen $PYTHON_PREFIX/lib/python3.5/site-packages/_pytest/python.py:1204>:1: ValueError _______ TestRaises.test_raises_doesnt ________ self = diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 9c758e6a7..032f83c08 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 443e6b6be..b0595bc9d 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items @@ -375,6 +375,8 @@ Running it:: assert 0, smtp.helo() E AssertionError: (250, b'mail.python.org') E assert 0 + ------------------------- Captured stdout teardown ------------------------- + finalizing (mail.python.org) voila! The ``smtp`` fixture function picked up our mail server name from the module namespace. @@ -464,6 +466,8 @@ So let's just do another run:: E assert 0 test_module.py:11: AssertionError + ------------------------- Captured stdout teardown ------------------------- + finalizing 4 failed in 0.12 seconds We see that our two test functions each ran twice, against the different @@ -516,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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 11 items @@ -569,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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 cachedir: .cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -638,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.3, py-1.4.31, pluggy-0.4.0 -- $PYTHON_PREFIX/bin/python3.5 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 bc23ba51b..a3e21e54a 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.3, imported from $PYTHON_PREFIX/lib/python3.5/site-packages/pytest.py + This is pytest version 3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 282b0b59a..aadabf222 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 1 items diff --git a/doc/en/parametrize.rst b/doc/en/parametrize.rst index b095ff434..5cfedac8c 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 68a2d628b..a024b43a4 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 5413c136e..3287ff30f 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, 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 61a0e8841..0bc0209e7 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.3, py-1.4.31, pluggy-0.4.0 + platform linux -- Python 3.5.2, pytest-3.0.4, py-1.4.31, pluggy-0.4.0 rootdir: $REGENDOC_TMPDIR, inifile: collected 2 items From 84d70687237edab585c807fc81836da56a493921 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 9 Nov 2016 20:42:28 -0200 Subject: [PATCH 17/22] Add "check-manifest" to linting and remove unused scripts from root Fix #1 --- CONTRIBUTING.rst | 11 ++++------- MANIFEST.in | 9 +++------ plugin-test.sh | 20 -------------------- requirements-docs.txt | 3 --- runtox.py | 8 -------- tox.ini | 8 ++++++-- 6 files changed, 13 insertions(+), 46 deletions(-) delete mode 100644 plugin-test.sh delete mode 100644 requirements-docs.txt delete mode 100644 runtox.py diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 947d4e655..19b31c7f4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -199,13 +199,10 @@ but here is a simple overview: You need to have Python 2.7 and 3.5 available in your system. Now running tests is as simple as issuing this command:: - $ python3 runtox.py -e linting,py27,py35 + $ tox -e linting,py27,py35 This command will run tests via the "tox" tool against Python 2.7 and 3.5 - and also perform "lint" coding-style checks. ``runtox.py`` is - a thin wrapper around ``tox`` which installs from a development package - index where newer (not yet released to PyPI) versions of dependencies - (especially ``py``) might be present. + and also perform "lint" coding-style checks. #. You can now edit your local working copy. @@ -214,11 +211,11 @@ but here is a simple overview: To run tests on Python 2.7 and pass options to pytest (e.g. enter pdb on failure) to pytest you can do:: - $ python3 runtox.py -e py27 -- --pdb + $ tox -e py27 -- --pdb Or to only run tests in a particular test module on Python 3.5:: - $ python3 runtox.py -e py35 -- testing/test_config.py + $ tox -e py35 -- testing/test_config.py #. Commit and push once your tests pass and you are happy with your change(s):: diff --git a/MANIFEST.in b/MANIFEST.in index 079b225ec..8e2cd6118 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -11,15 +11,12 @@ include setup.py include .coveragerc -include plugin-test.sh -include requirements-docs.txt -include runtox.py - recursive-include bench *.py recursive-include extra *.py graft testing graft doc +prune doc/en/_build exclude _pytest/impl @@ -27,6 +24,6 @@ graft _pytest/vendored_packages recursive-exclude * *.pyc *.pyo -exclude appveyor/install.ps1 exclude appveyor.yml -exclude appveyor +exclude .travis.yml +prune .github diff --git a/plugin-test.sh b/plugin-test.sh deleted file mode 100644 index 7830b7c7d..000000000 --- a/plugin-test.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -# this assumes plugins are installed as sister directories - -set -e -cd ../pytest-pep8 -pytest -cd ../pytest-instafail -pytest -cd ../pytest-cache -pytest -cd ../pytest-xprocess -pytest -#cd ../pytest-cov -#pytest -cd ../pytest-capturelog -pytest -cd ../pytest-xdist -pytest - diff --git a/requirements-docs.txt b/requirements-docs.txt deleted file mode 100644 index be3a232e5..000000000 --- a/requirements-docs.txt +++ /dev/null @@ -1,3 +0,0 @@ -sphinx==1.2.3 -regendoc -pyyaml diff --git a/runtox.py b/runtox.py deleted file mode 100644 index 8c13c53e1..000000000 --- a/runtox.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python - -if __name__ == "__main__": - import subprocess - import sys - subprocess.call([sys.executable, "-m", "tox", - "-i", "ALL=https://devpi.net/hpk/dev/", - "--develop"] + sys.argv[1:]) diff --git a/tox.ini b/tox.ini index 53a76180b..bbf300ce3 100644 --- a/tox.ini +++ b/tox.ini @@ -47,9 +47,13 @@ commands= pytest --genscript=pytest1 [testenv:linting] basepython = python2.7 -deps = flake8 +deps = + flake8 restructuredtext_lint -commands = flake8 pytest.py _pytest testing + check-manifest +commands = + check-manifest + flake8 pytest.py _pytest testing rst-lint CHANGELOG.rst HOWTORELEASE.rst [testenv:py27-xdist] From 26b151953400d277bb05ac0ee505570b28e78d9a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 9 Nov 2016 20:47:14 -0200 Subject: [PATCH 18/22] Add keywords to setup.py as suggested by pyroma Related to #1 --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 23ac0eb03..cdcf3b3bb 100644 --- a/setup.py +++ b/setup.py @@ -72,6 +72,7 @@ def main(): entry_points={'console_scripts': ['pytest=pytest:main', 'py.test=pytest:main']}, classifiers=classifiers, + keywords="test unittest", cmdclass={'test': PyTest}, # the following should be enabled for release install_requires=install_requires, From aaa547e7638e4d6ff46b3cd60341d229b2ebd2a5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 10 Nov 2016 08:48:56 -0200 Subject: [PATCH 19/22] Add some recursive-exclude related to hypothesis and freeze --- MANIFEST.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MANIFEST.in b/MANIFEST.in index 8e2cd6118..0c5bfd552 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -23,6 +23,10 @@ exclude _pytest/impl graft _pytest/vendored_packages recursive-exclude * *.pyc *.pyo +recursive-exclude testing/.hypothesis * +recursive-exclude testing/freeze/~ * +recursive-exclude testing/freeze/build * +recursive-exclude testing/freeze/dist * exclude appveyor.yml exclude .travis.yml From b8c6f13b37b58dd5c86075f6da5e2f63d44e86c5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Nov 2016 12:56:07 -0200 Subject: [PATCH 20/22] Check README.rst with rst-lint --- README.rst | 2 +- tox.ini | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 6a5179ed5..5b2d329e0 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ Please use the `GitHub issue tracker `_ page for fixes and enhancements of each version. +Consult the `Changelog `__ page for fixes and enhancements of each version. License diff --git a/tox.ini b/tox.ini index bbf300ce3..76b92aa53 100644 --- a/tox.ini +++ b/tox.ini @@ -42,8 +42,6 @@ deps=pytest-xdist>=1.13 commands= pytest -n3 -rfsxX --runpytest=subprocess {posargs:testing} -[testenv:genscript] -commands= pytest --genscript=pytest1 [testenv:linting] basepython = python2.7 @@ -54,7 +52,7 @@ deps = commands = check-manifest flake8 pytest.py _pytest testing - rst-lint CHANGELOG.rst HOWTORELEASE.rst + rst-lint CHANGELOG.rst HOWTORELEASE.rst README.rst [testenv:py27-xdist] deps=pytest-xdist>=1.13 From 6c8c1da428816cb0abcb39cbdd9c8f74f1841b63 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 11 Nov 2016 16:34:52 +0100 Subject: [PATCH 21/22] add pygments dependency because of rst-lint --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 76b92aa53..17fe0e3e4 100644 --- a/tox.ini +++ b/tox.ini @@ -47,6 +47,8 @@ commands= basepython = python2.7 deps = flake8 + # pygments required by rst-lint + pygments restructuredtext_lint check-manifest commands = From 3e01e83390950331a4e208c4cf9e165b50772223 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Nov 2016 18:20:02 -0200 Subject: [PATCH 22/22] Bump version to 3.0.5.dev --- CHANGELOG.rst | 14 ++++++++++++++ _pytest/__init__.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 178e5406f..02a66079b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,17 @@ +3.0.5.dev0 +========== + +* + +* + +* + +* + +* + + 3.0.4 ===== diff --git a/_pytest/__init__.py b/_pytest/__init__.py index 97cf2527b..15043e71c 100644 --- a/_pytest/__init__.py +++ b/_pytest/__init__.py @@ -1,2 +1,2 @@ # -__version__ = '3.0.4' +__version__ = '3.0.5.dev0'