From fc11b81005800fcc611edbea57c26b37561703db Mon Sep 17 00:00:00 2001 From: Jeffrey Rackauckas Date: Sun, 7 Oct 2018 19:19:48 -0700 Subject: [PATCH 01/44] Exclude durations that are 0.00 seconds long. --- changelog/4063.trivial.rst | 1 + src/_pytest/runner.py | 3 +++ testing/acceptance_test.py | 32 +++++++++++++++++++++++--------- 3 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 changelog/4063.trivial.rst diff --git a/changelog/4063.trivial.rst b/changelog/4063.trivial.rst new file mode 100644 index 000000000..3e0aaf0f0 --- /dev/null +++ b/changelog/4063.trivial.rst @@ -0,0 +1 @@ +Exclude 0.00 second entries from ``--duration`` output. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 1ba9ff310..8f1a710f9 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -30,6 +30,7 @@ def pytest_addoption(parser): def pytest_terminal_summary(terminalreporter): durations = terminalreporter.config.option.durations + verbose = terminalreporter.config.getvalue("verbose") if durations is None: return tr = terminalreporter @@ -49,6 +50,8 @@ def pytest_terminal_summary(terminalreporter): dlist = dlist[:durations] for rep in dlist: + if verbose < 2 and rep.duration < 0.01: + break nodeid = rep.nodeid.replace("::()::", "::") tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid)) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 332af27b5..9d76415da 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -816,7 +816,7 @@ class TestDurations(object): result = testdir.runpytest("--durations=10") assert result.ret == 0 result.stdout.fnmatch_lines_random( - ["*durations*", "*call*test_3*", "*call*test_2*", "*call*test_1*"] + ["*durations*", "*call*test_3*", "*call*test_2*"] ) def test_calls_show_2(self, testdir): @@ -830,6 +830,18 @@ class TestDurations(object): testdir.makepyfile(self.source) result = testdir.runpytest("--durations=0") assert result.ret == 0 + for x in "23": + for y in ("call",): # 'setup', 'call', 'teardown': + for line in result.stdout.lines: + if ("test_%s" % x) in line and y in line: + break + else: + raise AssertionError("not found {} {}".format(x, y)) + + def test_calls_showall_verbose(self, testdir): + testdir.makepyfile(self.source) + result = testdir.runpytest("--durations=0", "-vv") + assert result.ret == 0 for x in "123": for y in ("call",): # 'setup', 'call', 'teardown': for line in result.stdout.lines: @@ -840,9 +852,9 @@ class TestDurations(object): def test_with_deselected(self, testdir): testdir.makepyfile(self.source) - result = testdir.runpytest("--durations=2", "-k test_1") + result = testdir.runpytest("--durations=2", "-k test_2") assert result.ret == 0 - result.stdout.fnmatch_lines(["*durations*", "*call*test_1*"]) + result.stdout.fnmatch_lines(["*durations*", "*call*test_2*"]) def test_with_failing_collection(self, testdir): testdir.makepyfile(self.source) @@ -862,13 +874,15 @@ class TestDurations(object): class TestDurationWithFixture(object): source = """ + import pytest import time - frag = 0.001 - def setup_function(func): - time.sleep(frag * 3) - def test_1(): - time.sleep(frag*2) - def test_2(): + frag = 0.01 + + @pytest.fixture + def setup_fixt(): + time.sleep(frag) + + def test_1(setup_fixt): time.sleep(frag) """ From 81426c3d196028d77fb1bcbcccca8b9d83ea79a3 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Wed, 10 Oct 2018 18:02:37 +0200 Subject: [PATCH 02/44] tests: harden test_cmdline_python_package_symlink --- testing/acceptance_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index b0d0a7e61..fde25549d 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -738,8 +738,8 @@ class TestInvocationVariants(object): assert result.ret == 0 result.stdout.fnmatch_lines( [ - "*lib/foo/bar/test_bar.py::test_bar*PASSED*", - "*lib/foo/bar/test_bar.py::test_other*PASSED*", + "*lib/foo/bar/test_bar.py::test_bar PASSED*", + "*lib/foo/bar/test_bar.py::test_other PASSED*", "*2 passed*", ] ) From 6bf4692c7d8100b19dc0178764398edbd7803701 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 12 Oct 2018 15:15:35 +0200 Subject: [PATCH 03/44] acceptance_test: clarify/document/fix tests Ref: https://github.com/pytest-dev/pytest/commit/e2e6e317118d6d15ccdf6f6708a48c08d85cbc25#r30863971 --- testing/acceptance_test.py | 40 ++++++++++++++------------------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index fde25549d..29b4f2b42 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -12,6 +12,13 @@ import pytest from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR +def prepend_pythonpath(*dirs): + cur = os.getenv("PYTHONPATH") + if cur: + dirs += (cur,) + return os.pathsep.join(str(p) for p in dirs) + + class TestGeneralUsage(object): def test_config_error(self, testdir): testdir.copy_example("conftest_usageerror/conftest.py") @@ -570,14 +577,8 @@ class TestInvocationVariants(object): assert result.ret == 0 result.stdout.fnmatch_lines(["*1 passed*"]) - def join_pythonpath(what): - cur = os.environ.get("PYTHONPATH") - if cur: - return str(what) + os.pathsep + cur - return what - empty_package = testdir.mkpydir("empty_package") - monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(empty_package))) + monkeypatch.setenv("PYTHONPATH", str(empty_package), prepend=os.pathsep) # the path which is not a package raises a warning on pypy; # no idea why only pypy and not normal python warn about it here with warnings.catch_warnings(): @@ -586,7 +587,7 @@ class TestInvocationVariants(object): assert result.ret == 0 result.stdout.fnmatch_lines(["*2 passed*"]) - monkeypatch.setenv("PYTHONPATH", str(join_pythonpath(testdir))) + monkeypatch.setenv("PYTHONPATH", str(testdir), prepend=os.pathsep) result = testdir.runpytest("--pyargs", "tpkg.test_missing", syspathinsert=True) assert result.ret != 0 result.stderr.fnmatch_lines(["*not*found*test_missing*"]) @@ -626,18 +627,13 @@ class TestInvocationVariants(object): # ├── __init__.py # └── test_world.py - def join_pythonpath(*dirs): - cur = os.environ.get("PYTHONPATH") - if cur: - dirs += (cur,) - return os.pathsep.join(str(p) for p in dirs) - - monkeypatch.setenv("PYTHONPATH", join_pythonpath(*search_path)) + # NOTE: the different/reversed ordering is intentional here. + monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path)) for p in search_path: monkeypatch.syspath_prepend(p) # mixed module and filenames: - os.chdir("world") + monkeypatch.chdir("world") result = testdir.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world") assert result.ret == 0 result.stdout.fnmatch_lines( @@ -688,8 +684,6 @@ class TestInvocationVariants(object): pytest.skip(six.text_type(e.args[0])) monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False) - search_path = ["lib", os.path.join("local", "lib")] - dirname = "lib" d = testdir.mkdir(dirname) foo = d.mkdir("foo") @@ -722,13 +716,9 @@ class TestInvocationVariants(object): # ├── conftest.py # └── test_bar.py - def join_pythonpath(*dirs): - cur = os.getenv("PYTHONPATH") - if cur: - dirs += (cur,) - return os.pathsep.join(str(p) for p in dirs) - - monkeypatch.setenv("PYTHONPATH", join_pythonpath(*search_path)) + # NOTE: the different/reversed ordering is intentional here. + search_path = ["lib", os.path.join("local", "lib")] + monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path)) for p in search_path: monkeypatch.syspath_prepend(p) From 10ddc466bf8cd221a2c088ff2064cd058b51d9a1 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Fri, 12 Oct 2018 16:52:13 +0200 Subject: [PATCH 04/44] minor: typo and code style --- src/_pytest/fixtures.py | 5 ++--- src/_pytest/main.py | 7 ++----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index ffaa1b09a..21de82b02 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1013,7 +1013,7 @@ class FixtureFunctionMarker(object): def __call__(self, function): if isclass(function): - raise ValueError("class fixtures not supported (may be in the future)") + raise ValueError("class fixtures not supported (maybe in the future)") if getattr(function, "_pytestfixturefunction", False): raise ValueError( @@ -1366,8 +1366,7 @@ class FixtureManager(object): fixturedefs = self._arg2fixturedefs[argname] except KeyError: return None - else: - return tuple(self._matchfactories(fixturedefs, nodeid)) + return tuple(self._matchfactories(fixturedefs, nodeid)) def _matchfactories(self, fixturedefs, nodeid): for fixturedef in fixturedefs: diff --git a/src/_pytest/main.py b/src/_pytest/main.py index ce07285a4..5ad91dfc4 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -564,9 +564,7 @@ class Session(nodes.FSCollector): return True def _tryconvertpyarg(self, x): - """Convert a dotted module name to path. - - """ + """Convert a dotted module name to path.""" try: with _patched_find_module(): loader = pkgutil.find_loader(x) @@ -598,8 +596,7 @@ class Session(nodes.FSCollector): raise UsageError( "file or package not found: " + arg + " (missing __init__.py?)" ) - else: - raise UsageError("file not found: " + arg) + raise UsageError("file not found: " + arg) parts[0] = path return parts From ee54fb9a6b3d64224059201e6d3a2a238961e6e6 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Oct 2018 17:01:22 +0200 Subject: [PATCH 05/44] pytester: use EXIT_INTERRUPTED --- src/_pytest/pytester.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index a50999172..e3bf060e3 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -19,7 +19,7 @@ from _pytest.capture import MultiCapture, SysCapture from _pytest._code import Source import py import pytest -from _pytest.main import Session, EXIT_OK +from _pytest.main import Session, EXIT_INTERRUPTED, EXIT_OK from _pytest.assertion.rewrite import AssertionRewritingHook from _pytest.compat import Path from _pytest.compat import safe_str @@ -845,7 +845,7 @@ class Testdir(object): # typically we reraise keyboard interrupts from the child run # because it's our user requesting interruption of the testing - if ret == 2 and not kwargs.get("no_reraise_ctrlc"): + if ret == EXIT_INTERRUPTED and not kwargs.get("no_reraise_ctrlc"): calls = reprec.getcalls("pytest_keyboard_interrupt") if calls and calls[-1].excinfo.type == KeyboardInterrupt: raise KeyboardInterrupt() From 91b279749835a0dd2130cb2e6c54e4ab3b4d8848 Mon Sep 17 00:00:00 2001 From: Thomas Hess Date: Sat, 13 Oct 2018 20:33:31 +0200 Subject: [PATCH 06/44] docs: deprecation.rst: Add missing arguments to code example In the proposed new style using `@pytest.mark.parametrize`, the example function signature missed the actual arguments. Add the missing arguments --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index a9d153206..14eeeb08f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -243,7 +243,7 @@ This form of test function doesn't support fixtures properly, and users should s .. code-block:: python @pytest.mark.parametrize("x, y", [(2, 4), (3, 9)]) - def test_squared(): + def test_squared(x, y): assert x ** x == y From 47f5c2900263c635e8159dd1050754a7504270d5 Mon Sep 17 00:00:00 2001 From: Jeffrey Rackauckas Date: Sat, 13 Oct 2018 12:51:04 -0700 Subject: [PATCH 07/44] Update messaging for --durations when not in verbose mode. --- changelog/4063.trivial.rst | 2 +- doc/en/usage.rst | 1 + src/_pytest/runner.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog/4063.trivial.rst b/changelog/4063.trivial.rst index 3e0aaf0f0..465356401 100644 --- a/changelog/4063.trivial.rst +++ b/changelog/4063.trivial.rst @@ -1 +1 @@ -Exclude 0.00 second entries from ``--duration`` output. +Exclude 0.00 second entries from ``--duration`` output unless ``-vv`` is passed on the command-line. diff --git a/doc/en/usage.rst b/doc/en/usage.rst index e5521bba5..cc118fad8 100644 --- a/doc/en/usage.rst +++ b/doc/en/usage.rst @@ -269,6 +269,7 @@ To get a list of the slowest 10 test durations:: pytest --durations=10 +By default, pytest will not show test durations that are too small (<0.01s) unless ``-vv`` is passed on the command-line. Creating JUnitXML format files ---------------------------------------------------- diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 8f1a710f9..f01b06314 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -51,6 +51,7 @@ def pytest_terminal_summary(terminalreporter): for rep in dlist: if verbose < 2 and rep.duration < 0.01: + tr.write_line("0.00 durations hidden. Use -vv to show these durations.") break nodeid = rep.nodeid.replace("::()::", "::") tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid)) From 7a271a91b09e39889775bbc94718d7fb023a1bfa Mon Sep 17 00:00:00 2001 From: Jeffrey Rackauckas Date: Sat, 13 Oct 2018 12:55:17 -0700 Subject: [PATCH 08/44] Fix rounding error when displaying durations in non-verbose mode. --- src/_pytest/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index f01b06314..654bd4f22 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -50,7 +50,7 @@ def pytest_terminal_summary(terminalreporter): dlist = dlist[:durations] for rep in dlist: - if verbose < 2 and rep.duration < 0.01: + if verbose < 2 and rep.duration < 0.005: tr.write_line("0.00 durations hidden. Use -vv to show these durations.") break nodeid = rep.nodeid.replace("::()::", "::") From d3d8d53e413d36eb12b387c404c65e6ce18805b1 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Oct 2018 16:42:33 +0200 Subject: [PATCH 09/44] tests: test_pdb: fix print statements --- testing/test_pdb.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 4739f0e2d..f04a2f3a0 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -345,7 +345,7 @@ class TestPDB(object): import pytest def test_1(): i = 0 - print ("hello17") + print("hello17") pytest.set_trace() x = 3 """ @@ -383,7 +383,7 @@ class TestPDB(object): """ import pytest def test_1(capsys): - print ("hello1") + print("hello1") pytest.set_trace() """ ) @@ -420,7 +420,7 @@ class TestPDB(object): def test_1(): pdb.set_trace() def test_2(): - print ("hello") + print("hello") assert 0 """ ) @@ -461,10 +461,10 @@ class TestPDB(object): import pytest def test_1(): i = 0 - print ("hello17") + print("hello17") pytest.set_trace() x = 3 - print ("hello18") + print("hello18") pytest.set_trace() x = 4 """ @@ -525,7 +525,7 @@ class TestPDB(object): """ def pytest_enter_pdb(config): assert config.testing_verification == 'configured' - print 'enter_pdb_hook' + print('enter_pdb_hook') def pytest_configure(config): config.testing_verification = 'configured' @@ -562,7 +562,7 @@ class TestPDB(object): custom_pdb=""" class CustomPdb(object): def set_trace(*args, **kwargs): - print 'custom set_trace>' + print('custom set_trace>') """ ) p1 = testdir.makepyfile( From 3683d92c530472cab40d74d9e8c951b33f9ef411 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 13 Oct 2018 18:36:20 -0300 Subject: [PATCH 10/44] Adjust the 'durations hidden' message --- src/_pytest/runner.py | 3 ++- testing/acceptance_test.py | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 654bd4f22..057317993 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -51,7 +51,8 @@ def pytest_terminal_summary(terminalreporter): for rep in dlist: if verbose < 2 and rep.duration < 0.005: - tr.write_line("0.00 durations hidden. Use -vv to show these durations.") + tr.write_line("") + tr.write_line("(0.00 durations hidden. Use -vv to show these durations.)") break nodeid = rep.nodeid.replace("::()::", "::") tr.write_line("%02.2fs %-8s %s" % (rep.duration, rep.when, nodeid)) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 9d76415da..59d3c012a 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -818,6 +818,10 @@ class TestDurations(object): result.stdout.fnmatch_lines_random( ["*durations*", "*call*test_3*", "*call*test_2*"] ) + assert "test_something" not in result.stdout.str() + result.stdout.fnmatch_lines( + ["(0.00 durations hidden. Use -vv to show these durations.)"] + ) def test_calls_show_2(self, testdir): testdir.makepyfile(self.source) From 448830e6566735919068b34e5e40abccf05ff524 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Oct 2018 16:33:53 +0200 Subject: [PATCH 11/44] Do not print INTERNALERROR with --pdb This gets printed by the terminal reporter already, and currently results in the same error being displayed twice, e.g. when raising an `Exception` manually from `pytest.debugging.pytest_exception_interact`. --- changelog/4132.bugfix.rst | 1 + src/_pytest/debugging.py | 3 --- testing/test_pdb.py | 6 +++++- 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 changelog/4132.bugfix.rst diff --git a/changelog/4132.bugfix.rst b/changelog/4132.bugfix.rst new file mode 100644 index 000000000..1fbb9afad --- /dev/null +++ b/changelog/4132.bugfix.rst @@ -0,0 +1 @@ +Fix duplicate printing of internal errors when using ``--pdb``. diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index f51dff373..d9a6a8154 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -109,9 +109,6 @@ class PdbInvoke(object): _enter_pdb(node, call.excinfo, report) def pytest_internalerror(self, excrepr, excinfo): - for line in str(excrepr).split("\n"): - sys.stderr.write("INTERNALERROR> %s\n" % line) - sys.stderr.flush() tb = _postmortem_traceback(excinfo) post_mortem(tb) diff --git a/testing/test_pdb.py b/testing/test_pdb.py index f04a2f3a0..cda553c44 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -334,8 +334,12 @@ class TestPDB(object): ) p1 = testdir.makepyfile("def test_func(): pass") child = testdir.spawn_pytest("--pdb %s" % p1) - # child.expect(".*import pytest.*") child.expect("Pdb") + + # INTERNALERROR is only displayed once via terminal reporter. + assert len([x for x in child.before.decode().splitlines() + if x.startswith("INTERNALERROR> Traceback")]) == 1 + child.sendeof() self.flush(child) From 86c7dcff689ecb72a27f6d9dd48abf56bb9d969d Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 13 Oct 2018 16:49:30 +0200 Subject: [PATCH 12/44] pdb: handle quitting in post_mortem `help quit` in pdb says: > Quit from the debugger. The program being executed is aborted. But pytest would continue with the next tests, often making it necessary to kill the pytest process when using `--pdb` and trying to cancel the tests using `KeyboardInterrupt` / `Ctrl-C`. --- src/_pytest/debugging.py | 8 ++++++-- testing/test_pdb.py | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index f51dff373..325cd60dd 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,10 +1,12 @@ """ interactive debugging with PDB, the Python Debugger. """ from __future__ import absolute_import, division, print_function + +import os import pdb import sys -import os from doctest import UnexpectedException +from _pytest import outcomes from _pytest.config import hookimpl try: @@ -164,8 +166,9 @@ def _enter_pdb(node, excinfo, rep): rep.toterminal(tw) tw.sep(">", "entering PDB") tb = _postmortem_traceback(excinfo) - post_mortem(tb) rep._pdbshown = True + if post_mortem(tb): + outcomes.exit("Quitting debugger") return rep @@ -196,3 +199,4 @@ def post_mortem(t): p = Pdb() p.reset() p.interaction(None, t) + return p.quitting diff --git a/testing/test_pdb.py b/testing/test_pdb.py index 4739f0e2d..4a5e740f7 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -25,6 +25,8 @@ def custom_pdb_calls(): # install dummy debugger class and track which methods were called on it class _CustomPdb(object): + quitting = False + def __init__(self, *args, **kwargs): called.append("init") @@ -142,6 +144,9 @@ class TestPDB(object): def test_1(): i = 0 assert i == 1 + + def test_not_called_due_to_quit(): + pass """ ) child = testdir.spawn_pytest("--pdb %s" % p1) @@ -150,8 +155,9 @@ class TestPDB(object): child.expect("Pdb") child.sendeof() rest = child.read().decode("utf8") - assert "1 failed" in rest + assert "= 1 failed in" in rest assert "def test_1" not in rest + assert "Exit: Quitting debugger" in rest self.flush(child) @staticmethod @@ -321,7 +327,7 @@ class TestPDB(object): child = testdir.spawn_pytest("--pdb %s" % p1) # child.expect(".*import pytest.*") child.expect("Pdb") - child.sendeof() + child.sendline("c") child.expect("1 error") self.flush(child) @@ -376,6 +382,7 @@ class TestPDB(object): rest = child.read().decode("utf8") assert "1 failed" in rest assert "reading from stdin while output" not in rest + assert "BdbQuit" in rest self.flush(child) def test_pdb_and_capsys(self, testdir): @@ -518,7 +525,9 @@ class TestPDB(object): def test_pdb_collection_failure_is_shown(self, testdir): p1 = testdir.makepyfile("xxx") result = testdir.runpytest_subprocess("--pdb", p1) - result.stdout.fnmatch_lines(["*NameError*xxx*", "*1 error*"]) + result.stdout.fnmatch_lines( + ["E NameError: *xxx*", "*! *Exit: Quitting debugger !*"] # due to EOF + ) def test_enter_pdb_hook_is_called(self, testdir): testdir.makeconftest( From 4a49715614a015b18f33ce442e23bdab4f584750 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 14 Oct 2018 00:07:40 +0200 Subject: [PATCH 13/44] tox.ini: pexpect: use posargs; cleanup posargs - no need for {posargs:testing} really - remove `-ra`, used with addopts already --- tox.ini | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tox.ini b/tox.ini index 1c77f989d..3372ee207 100644 --- a/tox.ini +++ b/tox.ini @@ -18,7 +18,7 @@ envlist = [testenv] commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof -ra {posargs:testing} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof coverage: coverage combine coverage: coverage report passenv = USER USERNAME @@ -43,7 +43,7 @@ deps = nose passenv = USER USERNAME TRAVIS commands = - pytest -n auto -ra --runpytest=subprocess {posargs:testing} + pytest -n auto --runpytest=subprocess [testenv:linting] @@ -61,7 +61,7 @@ deps = {env:_PYTEST_TOX_EXTRA_DEP:} passenv = USER USERNAME TRAVIS commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:testing} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto [testenv:py36-xdist] # NOTE: copied from above due to https://github.com/tox-dev/tox/issues/706. @@ -80,7 +80,7 @@ deps = pexpect {env:_PYTEST_TOX_EXTRA_DEP:} commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra test_pdb.py test_terminal.py test_unittest.py + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest test_pdb.py test_terminal.py test_unittest.py {posargs} [testenv:py36-pexpect] changedir = {[testenv:py27-pexpect]changedir} @@ -101,14 +101,14 @@ setenv = PYTHONDONTWRITEBYTECODE=1 passenv = USER USERNAME TRAVIS commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto -ra {posargs:.} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs:.} [testenv:py27-trial] deps = twisted {env:_PYTEST_TOX_EXTRA_DEP:} commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/test_unittest.py} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:testing/test_unittest.py} [testenv:py36-trial] deps = {[testenv:py27-trial]deps} @@ -119,7 +119,7 @@ deps = numpy {env:_PYTEST_TOX_EXTRA_DEP:} commands= - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra {posargs:testing/python/approx.py} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:testing/python/approx.py} [testenv:py36-numpy] deps = {[testenv:py27-numpy]deps} @@ -154,7 +154,7 @@ deps = PyYAML {env:_PYTEST_TOX_EXTRA_DEP:} commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -ra doc/en + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest doc/en {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest [testenv:regen] @@ -175,7 +175,7 @@ commands = [testenv:jython] changedir = testing commands = - {envpython} {envbindir}/py.test-jython -ra {posargs} + {envpython} {envbindir}/py.test-jython {posargs} [testenv:py36-freeze] changedir = testing/freeze From e3bf9cede4151c930092f68e7088a3e1a379241b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 13 Oct 2018 22:13:25 -0300 Subject: [PATCH 14/44] Fix linting --- testing/test_pdb.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/testing/test_pdb.py b/testing/test_pdb.py index cda553c44..6b9625b55 100644 --- a/testing/test_pdb.py +++ b/testing/test_pdb.py @@ -337,8 +337,16 @@ class TestPDB(object): child.expect("Pdb") # INTERNALERROR is only displayed once via terminal reporter. - assert len([x for x in child.before.decode().splitlines() - if x.startswith("INTERNALERROR> Traceback")]) == 1 + assert ( + len( + [ + x + for x in child.before.decode().splitlines() + if x.startswith("INTERNALERROR> Traceback") + ] + ) + == 1 + ) child.sendeof() self.flush(child) From 7c380b19f393ed4f71d66e6d57439b5d59951571 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 14 Oct 2018 12:31:43 +0200 Subject: [PATCH 15/44] tox.ini: passenv: COVERAGE_* This is required to pass through COVERAGE_PROCESS_START etc. --- tox.ini | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index 3372ee207..0b2cba407 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof coverage: coverage combine coverage: coverage report -passenv = USER USERNAME +passenv = USER USERNAME COVERAGE_* setenv = # configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage" coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m @@ -41,7 +41,6 @@ deps = pytest-xdist>=1.13 py27: mock nose -passenv = USER USERNAME TRAVIS commands = pytest -n auto --runpytest=subprocess @@ -59,7 +58,6 @@ deps = nose hypothesis>=3.56 {env:_PYTEST_TOX_EXTRA_DEP:} -passenv = USER USERNAME TRAVIS commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto @@ -99,7 +97,6 @@ changedir=testing setenv = {[testenv]setenv} PYTHONDONTWRITEBYTECODE=1 -passenv = USER USERNAME TRAVIS commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs:.} From 6d0667f1dba390d7692d2c8157960a6f747ce291 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 14 Oct 2018 14:23:09 +0200 Subject: [PATCH 16/44] CI: run specialized factors in a single job Given the setup time for jobs, it makes sense to run *-pexpect,*-trial,*-numpy in a single build job. --- .travis.yml | 20 ++++++++------------ appveyor.yml | 15 ++++++--------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3936e599b..5c479feed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,19 +12,15 @@ install: - pip install --upgrade --pre tox env: matrix: - # note: please use "tox --listenvs" to populate the build matrix below - # please remove the linting env in all cases - - TOXENV=py27-pexpect - - TOXENV=py27-xdist - - TOXENV=py27-trial - - TOXENV=py27-numpy - - TOXENV=py27-pluggymaster PYTEST_NO_COVERAGE=1 - - TOXENV=py36-pexpect - - TOXENV=py36-xdist - - TOXENV=py36-trial - - TOXENV=py36-numpy - - TOXENV=py36-pluggymaster PYTEST_NO_COVERAGE=1 + # Specialized factors for py27. + - TOXENV=py27-pexpect,py27-trial,py27-numpy - TOXENV=py27-nobyte + - TOXENV=py27-xdist + - TOXENV=py27-pluggymaster PYTEST_NO_COVERAGE=1 + # Specialized factors for py36. + - TOXENV=py36-pexpect,py36-trial,py36-numpy + - TOXENV=py36-xdist + - TOXENV=py36-pluggymaster PYTEST_NO_COVERAGE=1 jobs: include: diff --git a/appveyor.yml b/appveyor.yml index efc880638..c8329c717 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,5 @@ environment: matrix: - - TOXENV: "linting,docs,doctesting" - PYTEST_NO_COVERAGE: "1" - TOXENV: "py27" - TOXENV: "py34" - TOXENV: "py35" @@ -9,19 +7,18 @@ environment: - TOXENV: "py37" - TOXENV: "pypy" PYTEST_NO_COVERAGE: "1" - - TOXENV: "py27-xdist" - - TOXENV: "py27-trial" - - TOXENV: "py27-numpy" + # Specialized factors for py27. + - TOXENV: "py27-trial,py27-numpy,py27-nobyte" - TOXENV: "py27-pluggymaster" PYTEST_NO_COVERAGE: "1" - - TOXENV: "py36-xdist" - - TOXENV: "py36-trial" - - TOXENV: "py36-numpy" + - TOXENV: "py27-xdist" + # Specialized factors for py36. + - TOXENV: "py36-trial,py36-numpy" - TOXENV: "py36-pluggymaster" PYTEST_NO_COVERAGE: "1" - - TOXENV: "py27-nobyte" - TOXENV: "py36-freeze" PYTEST_NO_COVERAGE: "1" + - TOXENV: "py36-xdist" install: - echo Installed Pythons From 7ded937e19c4ceb5332dc9719b88ef8fcb78feb5 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 14 Oct 2018 14:24:28 +0200 Subject: [PATCH 17/44] AppVeyor: use fast_finish This runs py27, py37 and linting first - simulating the baseline stage used on Travis. --- appveyor.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index c8329c717..abe431984 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,10 +1,12 @@ environment: matrix: - TOXENV: "py27" - - TOXENV: "py34" - - TOXENV: "py35" - - TOXENV: "py36" - TOXENV: "py37" + PYTEST_NO_COVERAGE: "1" + - TOXENV: "linting,docs,doctesting" + - TOXENV: "py36" + - TOXENV: "py35" + - TOXENV: "py34" - TOXENV: "pypy" PYTEST_NO_COVERAGE: "1" # Specialized factors for py27. @@ -20,6 +22,9 @@ environment: PYTEST_NO_COVERAGE: "1" - TOXENV: "py36-xdist" +matrix: + fast_finish: true + install: - echo Installed Pythons - dir c:\Python* From 3bd9f981a2d1e6b62e7d0c7ac03bca79c4877b3a Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sun, 14 Oct 2018 12:02:35 +0200 Subject: [PATCH 18/44] tox.ini: clean up changedir --- tox.ini | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tox.ini b/tox.ini index 3372ee207..123fb2fde 100644 --- a/tox.ini +++ b/tox.ini @@ -36,7 +36,6 @@ deps = {env:_PYTEST_TOX_EXTRA_DEP:} [testenv:py27-subprocess] -changedir = . deps = pytest-xdist>=1.13 py27: mock @@ -74,16 +73,14 @@ deps = commands = {[testenv:py27-xdist]commands} [testenv:py27-pexpect] -changedir = testing platform = linux|darwin deps = pexpect {env:_PYTEST_TOX_EXTRA_DEP:} commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest test_pdb.py test_terminal.py test_unittest.py {posargs} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest testing/test_pdb.py testing/test_terminal.py testing/test_unittest.py {posargs} [testenv:py36-pexpect] -changedir = {[testenv:py27-pexpect]changedir} platform = {[testenv:py27-pexpect]platform} deps = {[testenv:py27-pexpect]deps} commands = {[testenv:py27-pexpect]commands} @@ -95,13 +92,12 @@ deps = py27: mock {env:_PYTEST_TOX_EXTRA_DEP:} distribute = true -changedir=testing setenv = {[testenv]setenv} PYTHONDONTWRITEBYTECODE=1 passenv = USER USERNAME TRAVIS commands = - {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs:.} + {env:_PYTEST_TOX_COVERAGE_RUN:} pytest -n auto {posargs} [testenv:py27-trial] deps = From 486ded3fcae5aac100b49e49ef55192053e15807 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 14 Oct 2018 12:22:56 -0300 Subject: [PATCH 19/44] Fix flaky durations test Unfortunately due to fluctuations in runtime "test_something" might still appear in the final message. Example failure: https://ci.appveyor.com/project/pytestbot/pytest/builds/19494829/job/8lx847u0c78m63wf --- testing/acceptance_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 6f791dc84..41cdba067 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -808,7 +808,6 @@ class TestDurations(object): result.stdout.fnmatch_lines_random( ["*durations*", "*call*test_3*", "*call*test_2*"] ) - assert "test_something" not in result.stdout.str() result.stdout.fnmatch_lines( ["(0.00 durations hidden. Use -vv to show these durations.)"] ) From 48081458466f1ae62766be7593cc9b9e682ddbef Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 14 Oct 2018 15:17:08 -0300 Subject: [PATCH 20/44] test_request_garbage is flaky when running with xdist Example failure: https://travis-ci.org/pytest-dev/pytest/jobs/441305926#L545 --- testing/python/fixture.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/testing/python/fixture.py b/testing/python/fixture.py index 7e125e0b7..7ec7e9c1c 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -494,6 +494,12 @@ class TestRequestBasic(object): reason="this method of test doesn't work on pypy", ) def test_request_garbage(self, testdir): + try: + import xdist # noqa + except ImportError: + pass + else: + pytest.xfail("this test is flaky when executed with xdist") testdir.makepyfile( """ import sys From 2e42d937dcbfc17398210e957e054e815c694ca2 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 14 Oct 2018 16:11:47 -0700 Subject: [PATCH 21/44] Display the filename when encountering `SyntaxWarning`. ```console $ cd t && rm -rf __pycache__ && pytest t.py -q -c /dev/null; cd .. . [100%] =============================== warnings summary =============================== :2: DeprecationWarning: invalid escape sequence \. -- Docs: https://docs.pytest.org/en/latest/warnings.html 1 passed, 1 warnings in 0.01 seconds ``` ```console $ cd t && rm -rf __pycache__ && pytest t.py -q -c /dev/null; cd .. . [100%] =============================== warnings summary =============================== /tmp/pytest/t/t.py:2: DeprecationWarning: invalid escape sequence \. '\.wat' -- Docs: https://docs.pytest.org/en/latest/warnings.html 1 passed, 1 warnings in 0.01 seconds ``` --- changelog/4152.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/4152.bugfix.rst diff --git a/changelog/4152.bugfix.rst b/changelog/4152.bugfix.rst new file mode 100644 index 000000000..ce2547294 --- /dev/null +++ b/changelog/4152.bugfix.rst @@ -0,0 +1 @@ +Display the filename when encountering ``SyntaxWarning``. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 7a11c4ec1..385ae4e77 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -398,7 +398,7 @@ def _rewrite_test(config, fn): finally: del state._indecode try: - tree = ast.parse(source) + tree = ast.parse(source, filename=fn.strpath) except SyntaxError: # Let this pop up again in the real import. state.trace("failed to parse: %r" % (fn,)) From 661013c3e922c17f2dcf90a96bcc74b95a681475 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Mon, 15 Oct 2018 11:13:24 +0300 Subject: [PATCH 22/44] Add testdir examples to CONTRIBUTING guide Hopefully Closes: #4151 --- CONTRIBUTING.rst | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c005c2fb2..eb36122b5 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -280,6 +280,37 @@ Here is a simple overview, with pytest-specific bits: base: features # if it's a feature +Writing Tests +---------------------------- + +Writing tests for plugins or for pytest itself is done using the `testdir fixture `_, + +For example: + +.. code-block:: python + + def test_true_assertion(testdir): + testdir.makepyfile( + """ + def test_foo(): + assert True + """ + ) + result = testdir.runpytest() + result.assert_outcomes(failed=0, passed=1) + + + def test_true_assertion(testdir): + testdir.makepyfile( + """ + def test_foo(): + assert False + """ + ) + result = testdir.runpytest() + result.assert_outcomes(failed=1, passed=0) + + Joining the Development Team ---------------------------- From 99d957bd3df2bd4fcb4a4603a2073d6fc448b1e6 Mon Sep 17 00:00:00 2001 From: Tomer Keren Date: Mon, 15 Oct 2018 11:36:31 +0300 Subject: [PATCH 23/44] Check off PR requirements --- AUTHORS | 1 + changelog/4151.doc.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/4151.doc.rst diff --git a/AUTHORS b/AUTHORS index 2be74441a..463810bd9 100644 --- a/AUTHORS +++ b/AUTHORS @@ -209,6 +209,7 @@ Thomas Hisch Tim Strazny Tom Dalton Tom Viner +Tomer Keren Trevor Bekolay Tyler Goodlet Tzu-ping Chung diff --git a/changelog/4151.doc.rst b/changelog/4151.doc.rst new file mode 100644 index 000000000..da561002a --- /dev/null +++ b/changelog/4151.doc.rst @@ -0,0 +1 @@ +Add tempir testing example to CONTRIBUTING.rst guide From f129ba617f8d481ba8469f2e039a574c8717b312 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 08:00:16 -0300 Subject: [PATCH 24/44] Improve docs a bit --- CONTRIBUTING.rst | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index eb36122b5..c8ef03209 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -283,9 +283,9 @@ Here is a simple overview, with pytest-specific bits: Writing Tests ---------------------------- -Writing tests for plugins or for pytest itself is done using the `testdir fixture `_, +Writing tests for plugins or for pytest itself is often done using the `testdir fixture `_, as a "black-box" test. -For example: +For example, to ensure a simple test passes you can write: .. code-block:: python @@ -300,6 +300,11 @@ For example: result.assert_outcomes(failed=0, passed=1) +Alternatively, it is possible to make checks based on the actual output of the termal using +*glob-like* expressions: + +.. code-block:: python + def test_true_assertion(testdir): testdir.makepyfile( """ @@ -308,7 +313,12 @@ For example: """ ) result = testdir.runpytest() - result.assert_outcomes(failed=1, passed=0) + result.stdout.fnmatch_lines(["*assert False*, "*1 failed*"]) + +When choosing a file where to write a new test, take a look at the existing files and see if there's +one file which looks like a good fit. For example, a regression test about a bug in the ``--lf`` option +should go into ``test_cacheprovider.py``, given that this option is implemented in ``cacheprovider.py``. +If in doubt, go ahead and open a PR with your best guess and we can discuss this over the code. Joining the Development Team From ea25eb1ecc679cb1ef3a88aefe7d6bc30fa978c2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 08:15:40 -0300 Subject: [PATCH 25/44] Fix linting --- CONTRIBUTING.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c8ef03209..d3202f7c8 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -313,8 +313,8 @@ Alternatively, it is possible to make checks based on the actual output of the t """ ) result = testdir.runpytest() - result.stdout.fnmatch_lines(["*assert False*, "*1 failed*"]) - + result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"]) + When choosing a file where to write a new test, take a look at the existing files and see if there's one file which looks like a good fit. For example, a regression test about a bug in the ``--lf`` option should go into ``test_cacheprovider.py``, given that this option is implemented in ``cacheprovider.py``. From 9e867ce8642d6ed6e672c6aa770a034c62f5573e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 12:19:52 -0300 Subject: [PATCH 26/44] Use full link to changelog's README in PR template Fix #4156 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 23a9f8c56..7054f063d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,7 +3,7 @@ Thanks for submitting a PR, your contribution is really appreciated! Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is just a guideline): -- [ ] Create a new changelog file in the `changelog` folder, with a name like `..rst`. See [changelog/README.rst](/changelog/README.rst) for details. +- [ ] Create a new changelog file in the `changelog` folder, with a name like `..rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details. - [ ] Target the `master` branch for bug fixes, documentation updates and trivial changes. - [ ] Target the `features` branch for new features and removals/deprecations. - [ ] Include documentation when adding new features. From e8c220b9bd31924aa94f0410d3a6f0c50e9ab18d Mon Sep 17 00:00:00 2001 From: Thomas Hisch Date: Mon, 15 Oct 2018 19:29:39 +0200 Subject: [PATCH 27/44] Increase required verbosity level for debug output To show the subclassed file in legacy test suits in the runtest output you have to set the verbosity level to at least "-vv" now. Closes #3211 --- changelog/4159.feature.rst | 3 +++ src/_pytest/terminal.py | 4 +++- testing/acceptance_test.py | 4 ++-- testing/test_terminal.py | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 changelog/4159.feature.rst diff --git a/changelog/4159.feature.rst b/changelog/4159.feature.rst new file mode 100644 index 000000000..28ca7462e --- /dev/null +++ b/changelog/4159.feature.rst @@ -0,0 +1,3 @@ +For test-suites containing test classes, the information about the subclassed +module is now output only if a higher verbosity level is specified (at least +"-vv"). diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index f4dbbe61a..8deb330cc 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -676,7 +676,9 @@ class TerminalReporter(object): if fspath: res = mkrel(nodeid).replace("::()", "") # parens-normalization - if nodeid.split("::")[0] != fspath.replace("\\", nodes.SEP): + if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace( + "\\", nodes.SEP + ): res += " <- " + self.startdir.bestrelpath(fspath) else: res = "[location]" diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 2a6c75740..3dd56bf87 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -760,8 +760,8 @@ class TestInvocationVariants(object): if hasattr(py.path.local, "mksymlinkto"): result.stdout.fnmatch_lines( [ - "lib/foo/bar/test_bar.py::test_bar <- local/lib/foo/bar/test_bar.py PASSED*", - "lib/foo/bar/test_bar.py::test_other <- local/lib/foo/bar/test_bar.py PASSED*", + "lib/foo/bar/test_bar.py::test_bar PASSED*", + "lib/foo/bar/test_bar.py::test_other PASSED*", "*2 passed*", ] ) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 7651f3ab3..af2dc2f00 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -154,7 +154,7 @@ class TestTerminal(object): ) result = testdir.runpytest(p2) result.stdout.fnmatch_lines(["*test_p2.py .*", "*1 passed*"]) - result = testdir.runpytest("-v", p2) + result = testdir.runpytest("-vv", p2) result.stdout.fnmatch_lines( ["*test_p2.py::TestMore::test_p1* <- *test_p1.py*PASSED*"] ) @@ -170,7 +170,7 @@ class TestTerminal(object): """ ) ) - result = testdir.runpytest("-v") + result = testdir.runpytest("-vv") assert result.ret == 0 result.stdout.fnmatch_lines(["*a123/test_hello123.py*PASS*"]) assert " <- " not in result.stdout.str() From 39a13d70647ae8c7a984209a3424b5b4052efa4f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 20:17:02 +0000 Subject: [PATCH 28/44] Fix tmp_path example in docs --- doc/en/tmpdir.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index 728621152..aff9a9308 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -31,7 +31,7 @@ created in the `base temporary directory`_. p = d / "hello.txt" p.write_text(CONTENT) assert p.read_text() == CONTENT - assert len(tmpdir.listdir()) == 1 + assert len(list(tmp_path.iterdir())) == 1 assert 0 Running this would result in a passed test except for the last From 2868c314953e3a2cf2c753ebb87710d65c906cfa Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 20:23:30 +0000 Subject: [PATCH 29/44] Preparing release version 3.9.0 --- CHANGELOG.rst | 146 ++++++++++++++++++++++++++++++ changelog/2293.feature.rst | 4 - changelog/2293.trivial.rst | 1 - changelog/2535.bugfix.rst | 1 - changelog/3057.bugfix.rst | 1 - changelog/3332.feature.rst | 4 - changelog/3616.deprecation.rst | 22 ----- changelog/3713.doc.rst | 1 - changelog/3849.feature.rst | 1 - changelog/3946.bugfix.rst | 2 - changelog/3964.feature.rst | 2 - changelog/3985.feature.rst | 1 - changelog/3988.deprecation.rst | 1 - changelog/3988.trivial.rst | 1 - changelog/4013.feature.rst | 2 - changelog/4058.doc.rst | 1 - changelog/4063.trivial.rst | 1 - changelog/4064.doc.rst | 1 - changelog/4066.bugfix.rst | 1 - changelog/4073.feature.rst | 1 - changelog/4093.trivial.rst | 1 - changelog/4098.feature.rst | 1 - changelog/4102.bugfix.rst | 1 - changelog/4102.feature.rst | 4 - changelog/4108.bugfix.rst | 5 - changelog/4132.bugfix.rst | 1 - changelog/4135.bugfix.rst | 1 - changelog/4149.feature.rst | 1 - changelog/4151.doc.rst | 1 - changelog/4152.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-3.9.0.rst | 43 +++++++++ doc/en/builtin.rst | 14 ++- doc/en/example/markers.rst | 16 ++-- doc/en/example/nonpython.rst | 2 +- doc/en/example/simple.rst | 4 +- doc/en/fixture.rst | 6 +- doc/en/tmpdir.rst | 23 ++++- doc/en/writing_plugins.rst | 14 ++- 39 files changed, 252 insertions(+), 83 deletions(-) delete mode 100644 changelog/2293.feature.rst delete mode 100644 changelog/2293.trivial.rst delete mode 100644 changelog/2535.bugfix.rst delete mode 100644 changelog/3057.bugfix.rst delete mode 100644 changelog/3332.feature.rst delete mode 100644 changelog/3616.deprecation.rst delete mode 100644 changelog/3713.doc.rst delete mode 100644 changelog/3849.feature.rst delete mode 100644 changelog/3946.bugfix.rst delete mode 100644 changelog/3964.feature.rst delete mode 100644 changelog/3985.feature.rst delete mode 100644 changelog/3988.deprecation.rst delete mode 100644 changelog/3988.trivial.rst delete mode 100644 changelog/4013.feature.rst delete mode 100644 changelog/4058.doc.rst delete mode 100644 changelog/4063.trivial.rst delete mode 100644 changelog/4064.doc.rst delete mode 100644 changelog/4066.bugfix.rst delete mode 100644 changelog/4073.feature.rst delete mode 100644 changelog/4093.trivial.rst delete mode 100644 changelog/4098.feature.rst delete mode 100644 changelog/4102.bugfix.rst delete mode 100644 changelog/4102.feature.rst delete mode 100644 changelog/4108.bugfix.rst delete mode 100644 changelog/4132.bugfix.rst delete mode 100644 changelog/4135.bugfix.rst delete mode 100644 changelog/4149.feature.rst delete mode 100644 changelog/4151.doc.rst delete mode 100644 changelog/4152.bugfix.rst create mode 100644 doc/en/announce/release-3.9.0.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 26bc28af1..0f0193864 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,152 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 3.9.0 (2018-10-15) +========================= + +Deprecations +------------ + +- `#3616 `_: The following accesses have been documented as deprecated for years, but are now actually emitting deprecation warnings. + + * Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances. Now + users will this warning:: + + usage of Function.Module is deprecated, please use pytest.Module instead + + Users should just ``import pytest`` and access those objects using the ``pytest`` module. + + * ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can + consult `funcarg comparision section in the docs `_. + + * Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector`` + subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during + collection. + + This issue should affect only advanced plugins who create new collection types, so if you see this warning + message please contact the authors so they can change the code. + + * The warning that produces the message below has changed to ``RemovedInPytest4Warning``:: + + getfuncargvalue is deprecated, use getfixturevalue + + +- `#3988 `_: Add a Deprecation warning for pytest.ensuretemp as it was deprecated since a while. + + + +Features +-------- + +- `#2293 `_: Improve usage errors messages by hiding internal details which can be distracting and noisy. + + This has the side effect that some error conditions that previously raised generic errors (such as + ``ValueError`` for unregistered marks) are now raising ``Failed`` exceptions. + + +- `#3332 `_: Improve the error displayed when a ``conftest.py`` file could not be imported. + + In order to implement this, a new ``chain`` parameter was added to ``ExceptionInfo.getrepr`` + to show or hide chained tracebacks in Python 3 (defaults to ``True``). + + +- `#3849 `_: Add ``empty_parameter_set_mark=fail_at_collect`` ini option for raising an exception when parametrize collects an empty set. + + +- `#3964 `_: Log messages generated in the collection phase are shown when + live-logging is enabled and/or when they are logged to a file. + + +- `#3985 `_: Introduce ``tmp_path`` as a fixture providing a Path object. + + +- `#4013 `_: Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version + any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default. + + +- `#4073 `_: Allow specification of timeout for ``Testdir.runpytest_subprocess()`` and ``Testdir.run()``. + + +- `#4098 `_: Add returncode argument to pytest.exit() to exit pytest with a specific return code. + + +- `#4102 `_: Reimplement ``pytest.deprecated_call`` using ``pytest.warns`` so it supports the ``match='...'`` keyword argument. + + This has the side effect that ``pytest.deprecated_call`` now raises ``pytest.fail.Exception`` instead + of ``AssertionError``. + + +- `#4149 `_: Require setuptools>=30.3 and move most of the metadata to ``setup.cfg``. + + + +Bug Fixes +--------- + +- `#2535 `_: Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture. + + +- `#3057 `_: ``request.fixturenames`` now correctly returns the name of fixtures created by ``request.getfixturevalue()``. + + +- `#3946 `_: Warning filters passed as command line options using ``-W`` now take precedence over filters defined in ``ini`` + configuration files. + + +- `#4066 `_: Fix source reindenting by using ``textwrap.dedent`` directly. + + +- `#4102 `_: ``pytest.warn`` will capture previously-warned warnings in Python 2. Previously they were never raised. + + +- `#4108 `_: Resolve symbolic links for args. + + This fixes running ``pytest tests/test_foo.py::test_bar``, where ``tests`` + is a symlink to ``project/app/tests``: + previously ``project/app/conftest.py`` would be ignored for fixtures then. + + +- `#4132 `_: Fix duplicate printing of internal errors when using ``--pdb``. + + +- `#4135 `_: pathlib based tmpdir cleanup now correctly handles symlinks in the folder. + + +- `#4152 `_: Display the filename when encountering ``SyntaxWarning``. + + + +Improved Documentation +---------------------- + +- `#3713 `_: Update usefixtures documentation to clarify that it can't be used with fixture functions. + + +- `#4058 `_: Update fixture documentation to specify that a fixture can be invoked twice in the scope it's defined for. + + +- `#4064 `_: According to unittest.rst, setUpModule and tearDownModule were not implemented, but it turns out they are. So updated the documentation for unittest. + + +- `#4151 `_: Add tempir testing example to CONTRIBUTING.rst guide + + + +Trivial/Internal Changes +------------------------ + +- `#2293 `_: The internal ``MarkerError`` exception has been removed. + + +- `#3988 `_: Port the implementation of tmpdir to pathlib. + + +- `#4063 `_: Exclude 0.00 second entries from ``--duration`` output unless ``-vv`` is passed on the command-line. + + +- `#4093 `_: Fixed formatting of string literals in internal tests. + + pytest 3.8.2 (2018-10-02) ========================= diff --git a/changelog/2293.feature.rst b/changelog/2293.feature.rst deleted file mode 100644 index 5e56ba321..000000000 --- a/changelog/2293.feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve usage errors messages by hiding internal details which can be distracting and noisy. - -This has the side effect that some error conditions that previously raised generic errors (such as -``ValueError`` for unregistered marks) are now raising ``Failed`` exceptions. diff --git a/changelog/2293.trivial.rst b/changelog/2293.trivial.rst deleted file mode 100644 index a11245127..000000000 --- a/changelog/2293.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -The internal ``MarkerError`` exception has been removed. diff --git a/changelog/2535.bugfix.rst b/changelog/2535.bugfix.rst deleted file mode 100644 index ec16e81ea..000000000 --- a/changelog/2535.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Improve error message when test functions of ``unittest.TestCase`` subclasses use a parametrized fixture. diff --git a/changelog/3057.bugfix.rst b/changelog/3057.bugfix.rst deleted file mode 100644 index 8cc22f278..000000000 --- a/changelog/3057.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -``request.fixturenames`` now correctly returns the name of fixtures created by ``request.getfixturevalue()``. diff --git a/changelog/3332.feature.rst b/changelog/3332.feature.rst deleted file mode 100644 index e0110c451..000000000 --- a/changelog/3332.feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Improve the error displayed when a ``conftest.py`` file could not be imported. - -In order to implement this, a new ``chain`` parameter was added to ``ExceptionInfo.getrepr`` -to show or hide chained tracebacks in Python 3 (defaults to ``True``). diff --git a/changelog/3616.deprecation.rst b/changelog/3616.deprecation.rst deleted file mode 100644 index 8ea1b4d3d..000000000 --- a/changelog/3616.deprecation.rst +++ /dev/null @@ -1,22 +0,0 @@ -The following accesses have been documented as deprecated for years, but are now actually emitting deprecation warnings. - -* Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances. Now - users will this warning:: - - usage of Function.Module is deprecated, please use pytest.Module instead - - Users should just ``import pytest`` and access those objects using the ``pytest`` module. - -* ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can - consult `funcarg comparision section in the docs `_. - -* Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector`` - subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during - collection. - - This issue should affect only advanced plugins who create new collection types, so if you see this warning - message please contact the authors so they can change the code. - -* The warning that produces the message below has changed to ``RemovedInPytest4Warning``:: - - getfuncargvalue is deprecated, use getfixturevalue diff --git a/changelog/3713.doc.rst b/changelog/3713.doc.rst deleted file mode 100644 index c1d6b51b8..000000000 --- a/changelog/3713.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Update usefixtures documentation to clarify that it can't be used with fixture functions. diff --git a/changelog/3849.feature.rst b/changelog/3849.feature.rst deleted file mode 100644 index 26cbfe7b4..000000000 --- a/changelog/3849.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Add ``empty_parameter_set_mark=fail_at_collect`` ini option for raising an exception when parametrize collects an empty set. diff --git a/changelog/3946.bugfix.rst b/changelog/3946.bugfix.rst deleted file mode 100644 index 1b5248b4c..000000000 --- a/changelog/3946.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Warning filters passed as command line options using ``-W`` now take precedence over filters defined in ``ini`` -configuration files. diff --git a/changelog/3964.feature.rst b/changelog/3964.feature.rst deleted file mode 100644 index 37788c6f7..000000000 --- a/changelog/3964.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Log messages generated in the collection phase are shown when -live-logging is enabled and/or when they are logged to a file. diff --git a/changelog/3985.feature.rst b/changelog/3985.feature.rst deleted file mode 100644 index 19070cad0..000000000 --- a/changelog/3985.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Introduce ``tmp_path`` as a fixture providing a Path object. diff --git a/changelog/3988.deprecation.rst b/changelog/3988.deprecation.rst deleted file mode 100644 index b731112e4..000000000 --- a/changelog/3988.deprecation.rst +++ /dev/null @@ -1 +0,0 @@ -Add a Deprecation warning for pytest.ensuretemp as it was deprecated since a while. diff --git a/changelog/3988.trivial.rst b/changelog/3988.trivial.rst deleted file mode 100644 index 876db9798..000000000 --- a/changelog/3988.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Port the implementation of tmpdir to pathlib. diff --git a/changelog/4013.feature.rst b/changelog/4013.feature.rst deleted file mode 100644 index 84c3ab79d..000000000 --- a/changelog/4013.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version -any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default. diff --git a/changelog/4058.doc.rst b/changelog/4058.doc.rst deleted file mode 100644 index 51d568f54..000000000 --- a/changelog/4058.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Update fixture documentation to specify that a fixture can be invoked twice in the scope it's defined for. diff --git a/changelog/4063.trivial.rst b/changelog/4063.trivial.rst deleted file mode 100644 index 465356401..000000000 --- a/changelog/4063.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Exclude 0.00 second entries from ``--duration`` output unless ``-vv`` is passed on the command-line. diff --git a/changelog/4064.doc.rst b/changelog/4064.doc.rst deleted file mode 100644 index 7b34fe43e..000000000 --- a/changelog/4064.doc.rst +++ /dev/null @@ -1 +0,0 @@ -According to unittest.rst, setUpModule and tearDownModule were not implemented, but it turns out they are. So updated the documentation for unittest. diff --git a/changelog/4066.bugfix.rst b/changelog/4066.bugfix.rst deleted file mode 100644 index 64980d6e8..000000000 --- a/changelog/4066.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix source reindenting by using ``textwrap.dedent`` directly. diff --git a/changelog/4073.feature.rst b/changelog/4073.feature.rst deleted file mode 100644 index 5b0ed5927..000000000 --- a/changelog/4073.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Allow specification of timeout for ``Testdir.runpytest_subprocess()`` and ``Testdir.run()``. diff --git a/changelog/4093.trivial.rst b/changelog/4093.trivial.rst deleted file mode 100644 index cbfbeb00d..000000000 --- a/changelog/4093.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed formatting of string literals in internal tests. diff --git a/changelog/4098.feature.rst b/changelog/4098.feature.rst deleted file mode 100644 index 1a53de759..000000000 --- a/changelog/4098.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Add returncode argument to pytest.exit() to exit pytest with a specific return code. diff --git a/changelog/4102.bugfix.rst b/changelog/4102.bugfix.rst deleted file mode 100644 index dd066c38d..000000000 --- a/changelog/4102.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -``pytest.warn`` will capture previously-warned warnings in Python 2. Previously they were never raised. diff --git a/changelog/4102.feature.rst b/changelog/4102.feature.rst deleted file mode 100644 index ee43ddc24..000000000 --- a/changelog/4102.feature.rst +++ /dev/null @@ -1,4 +0,0 @@ -Reimplement ``pytest.deprecated_call`` using ``pytest.warns`` so it supports the ``match='...'`` keyword argument. - -This has the side effect that ``pytest.deprecated_call`` now raises ``pytest.fail.Exception`` instead -of ``AssertionError``. diff --git a/changelog/4108.bugfix.rst b/changelog/4108.bugfix.rst deleted file mode 100644 index d136d5996..000000000 --- a/changelog/4108.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -Resolve symbolic links for args. - -This fixes running ``pytest tests/test_foo.py::test_bar``, where ``tests`` -is a symlink to ``project/app/tests``: -previously ``project/app/conftest.py`` would be ignored for fixtures then. diff --git a/changelog/4132.bugfix.rst b/changelog/4132.bugfix.rst deleted file mode 100644 index 1fbb9afad..000000000 --- a/changelog/4132.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix duplicate printing of internal errors when using ``--pdb``. diff --git a/changelog/4135.bugfix.rst b/changelog/4135.bugfix.rst deleted file mode 100644 index d4f8a851d..000000000 --- a/changelog/4135.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -pathlib based tmpdir cleanup now correctly handles symlinks in the folder. diff --git a/changelog/4149.feature.rst b/changelog/4149.feature.rst deleted file mode 100644 index 7f9908b15..000000000 --- a/changelog/4149.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Require setuptools>=30.3 and move most of the metadata to ``setup.cfg``. diff --git a/changelog/4151.doc.rst b/changelog/4151.doc.rst deleted file mode 100644 index da561002a..000000000 --- a/changelog/4151.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Add tempir testing example to CONTRIBUTING.rst guide diff --git a/changelog/4152.bugfix.rst b/changelog/4152.bugfix.rst deleted file mode 100644 index ce2547294..000000000 --- a/changelog/4152.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Display the filename when encountering ``SyntaxWarning``. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index e6c712120..4dad6fd4f 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.9.0 release-3.8.2 release-3.8.1 release-3.8.0 diff --git a/doc/en/announce/release-3.9.0.rst b/doc/en/announce/release-3.9.0.rst new file mode 100644 index 000000000..14cfbe903 --- /dev/null +++ b/doc/en/announce/release-3.9.0.rst @@ -0,0 +1,43 @@ +pytest-3.9.0 +======================================= + +The pytest team is proud to announce the 3.9.0 release! + +pytest is a mature Python testing tool with more than a 2000 tests +against itself, passing on many different interpreters and platforms. + +This release contains a number of bugs fixes and improvements, so users are encouraged +to take a look at the CHANGELOG: + + https://docs.pytest.org/en/latest/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/latest/ + +As usual, you can upgrade from pypi via: + + pip install -U pytest + +Thanks to all who contributed to this release, among them: + +* Andrea Cimatoribus +* Ankit Goel +* Anthony Sottile +* Ben Eyal +* Bruno Oliveira +* Daniel Hahler +* Jeffrey Rackauckas +* Jose Carlos Menezes +* Kyle Altendorf +* Niklas JQ +* Palash Chatterjee +* Ronny Pfannschmidt +* Thomas Hess +* Thomas Hisch +* Tomer Keren +* Victor Maryama + + +Happy testing, +The Pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index e52151a1b..f921b5d64 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -104,7 +104,9 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a See http://docs.python.org/library/warnings.html for information on warning categories. tmpdir_factory - Return a TempdirFactory instance for the test session. + Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session. + tmp_path_factory + Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session. tmpdir Return a temporary directory path object which is unique to each test function invocation, @@ -113,6 +115,16 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a path object. .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html + tmp_path + Return a temporary directory path object + which is unique to each test function invocation, + created as a sub directory of the base temporary + directory. The returned object is a :class:`pathlib.Path` + object. + + .. note:: + + in python < 3.6 this is a pathlib2.Path no tests ran in 0.12 seconds diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index a2cb8a676..cb6368a64 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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected @@ -44,7 +44,7 @@ Or the inverse, running all tests except the webtest ones:: $ pytest -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected @@ -64,7 +64,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item @@ -77,7 +77,7 @@ You can also select on the class:: $ pytest -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item @@ -90,7 +90,7 @@ Or select multiple nodes:: $ pytest -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -128,7 +128,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected @@ -141,7 +141,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected @@ -156,7 +156,7 @@ Or to select "http" and "quick" tests:: $ pytest -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 2 deselected diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index a266b5bfe..bda15065a 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode:: nonpython $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collecting ... collected 2 items diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 7ec27d547..b16070287 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -357,7 +357,7 @@ which will add info only when run with "--v":: $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache info1: did you know that ... did you? @@ -574,7 +574,7 @@ We can run this:: file $REGENDOC_TMPDIR/b/test_error.py, line 1 def test_root(db): # no db here, will error out E fixture 'db' not found - > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmpdir, tmpdir_factory + > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, record_xml_property, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. $REGENDOC_TMPDIR/b/test_error.py:1 diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index fa111afa4..65664c0b2 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -732,7 +732,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:: $ pytest test_fixture_marks.py -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 3 items @@ -775,7 +775,7 @@ Here we declare an ``app`` fixture which receives the previously defined $ pytest -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -844,7 +844,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items diff --git a/doc/en/tmpdir.rst b/doc/en/tmpdir.rst index aff9a9308..d8cd8b705 100644 --- a/doc/en/tmpdir.rst +++ b/doc/en/tmpdir.rst @@ -38,9 +38,30 @@ Running this would result in a passed test except for the last ``assert 0`` line which we use to look at values:: $ pytest test_tmp_path.py - ... #fill fom regendoc + =========================== test session starts ============================ + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y + rootdir: $REGENDOC_TMPDIR, inifile: + collected 1 item + test_tmp_path.py F [100%] + ================================= FAILURES ================================= + _____________________________ test_create_file _____________________________ + + tmp_path = PosixPath('PYTEST_TMPDIR/test_create_file0') + + def test_create_file(tmp_path): + d = tmp_path / "sub" + d.mkdir() + p = d / "hello.txt" + p.write_text(CONTENT) + assert p.read_text() == CONTENT + assert len(list(tmp_path.iterdir())) == 1 + > assert 0 + E assert 0 + + test_tmp_path.py:13: AssertionError + ========================= 1 failed in 0.12 seconds ========================= The ``tmp_path_factory`` fixture -------------------------------- diff --git a/doc/en/writing_plugins.rst b/doc/en/writing_plugins.rst index 70e48f817..2cb1caefb 100644 --- a/doc/en/writing_plugins.rst +++ b/doc/en/writing_plugins.rst @@ -420,9 +420,21 @@ additionally it is possible to copy examples for a example folder before running ============================= warnings summary ============================= $REGENDOC_TMPDIR/test_example.py:4: PytestExperimentalApiWarning: testdir.copy_example is an experimental api that may change over time testdir.copy_example("test_example.py") + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Class is deprecated, please use pytest.Class instead + return getattr(object, name, default) + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.File is deprecated, please use pytest.File instead + return getattr(object, name, default) + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Function is deprecated, please use pytest.Function instead + return getattr(object, name, default) + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Instance is deprecated, please use pytest.Instance instead + return getattr(object, name, default) + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Item is deprecated, please use pytest.Item instead + return getattr(object, name, default) + $PYTHON_PREFIX/lib/python3.6/site-packages/_pytest/compat.py:321: RemovedInPytest4Warning: usage of Session.Module is deprecated, please use pytest.Module instead + return getattr(object, name, default) -- Docs: https://docs.pytest.org/en/latest/warnings.html - =================== 2 passed, 1 warnings in 0.12 seconds =================== + =================== 2 passed, 7 warnings in 0.12 seconds =================== For more information about the result object that ``runpytest()`` returns, and the methods that it provides please check out the :py:class:`RunResult From 12edc4e7b83fdf712f0c9f266a3beba1650b6bef Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 15 Oct 2018 20:06:59 -0300 Subject: [PATCH 30/44] Pass TRAVIS env var to test environments [skip appveyor] xdist has an workaround inplace for Travis so "-n auto" works. Fix #4162 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4ccb0305e..98d2ce041 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --lsof coverage: coverage combine coverage: coverage report -passenv = USER USERNAME COVERAGE_* +passenv = USER USERNAME COVERAGE_* TRAVIS setenv = # configuration if a user runs tox with a "coverage" factor, for example "tox -e py36-coverage" coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m From f55ded20a951988391d7f2877bc94e648a014948 Mon Sep 17 00:00:00 2001 From: Vincent Barbaresi Date: Tue, 16 Oct 2018 14:46:38 +0200 Subject: [PATCH 31/44] fix #3533: properly escape raw XML object Using string formatting with the raw escaped object lead to string evaluation "" Format the unescaped string first, then use the XML escape method as a last step. --- src/_pytest/junitxml.py | 8 +++++--- testing/test_junitxml.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index ac00c772a..a39c94c13 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -221,12 +221,14 @@ class _NodeReporter(object): else: filename, lineno, skipreason = report.longrepr if skipreason.startswith("Skipped: "): - skipreason = bin_xml_escape(skipreason[9:]) + skipreason = skipreason[9:] + details = "%s:%s: %s" % (filename, lineno, skipreason) + self.append( Junit.skipped( - "%s:%s: %s" % (filename, lineno, skipreason), + bin_xml_escape(details), type="pytest.skip", - message=skipreason, + message=bin_xml_escape(skipreason), ) ) self.write_captured_output(report) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 29d3f7f6e..079b01f32 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1222,3 +1222,19 @@ def test_set_suite_name(testdir, suite_name): assert result.ret == 0 node = dom.find_first_by_tag("testsuite") node.assert_attr(name=expected) + + +def test_escaped_skipreason_issue3533(testdir): + testdir.makepyfile( + """ + import pytest + @pytest.mark.skip(reason='1 <> 2') + def test_skip(): + pass + """ + ) + _, dom = runandparse(testdir) + node = dom.find_first_by_tag("testcase") + snode = node.find_first_by_tag("skipped") + assert "1 <> 2" in snode.text + snode.assert_attr(message="1 <> 2") From d72154acda1e3f14ce6d531b5e4f54aff9e9a5f4 Mon Sep 17 00:00:00 2001 From: Vincent Barbaresi Date: Tue, 16 Oct 2018 15:01:07 +0200 Subject: [PATCH 32/44] add changelog for #3533 --- changelog/3533.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3533.bugfix.rst diff --git a/changelog/3533.bugfix.rst b/changelog/3533.bugfix.rst new file mode 100644 index 000000000..89f136458 --- /dev/null +++ b/changelog/3533.bugfix.rst @@ -0,0 +1 @@ +Fix unescaped XML raw objects in JUnit report for skipped tests From 456715a5c1b4e573cb87b9864c1ca83616944395 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 16 Oct 2018 21:48:39 +0200 Subject: [PATCH 33/44] fix url quotes in setup.cfg metadata --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index a898b66c6..8cd3858fd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ name = pytest description = pytest: simple powerful testing with Python long_description = file: README.rst -url = "https://docs.pytest.org/en/latest/" +url = https://docs.pytest.org/en/latest/ project_urls = Source=https://github.com/pytest-dev/pytest Tracker=https://github.com/pytest-dev/pytest/issues From 253c5786af681604f4e0c2b315f17fa5bcc950c2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 16 Oct 2018 22:11:40 +0200 Subject: [PATCH 34/44] Preparing release version 3.9.1 --- CHANGELOG.rst | 11 +++++++++++ changelog/4159.feature.rst | 3 --- doc/en/announce/index.rst | 1 + doc/en/announce/release-3.9.1.rst | 20 ++++++++++++++++++++ doc/en/example/markers.rst | 16 ++++++++-------- doc/en/example/nonpython.rst | 2 +- doc/en/example/simple.rst | 2 +- doc/en/fixture.rst | 6 +++--- 8 files changed, 45 insertions(+), 16 deletions(-) delete mode 100644 changelog/4159.feature.rst create mode 100644 doc/en/announce/release-3.9.1.rst diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0f0193864..7a5c83a00 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,17 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 3.9.1 (2018-10-16) +========================= + +Features +-------- + +- `#4159 `_: For test-suites containing test classes, the information about the subclassed + module is now output only if a higher verbosity level is specified (at least + "-vv"). + + pytest 3.9.0 (2018-10-15) ========================= diff --git a/changelog/4159.feature.rst b/changelog/4159.feature.rst deleted file mode 100644 index 28ca7462e..000000000 --- a/changelog/4159.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -For test-suites containing test classes, the information about the subclassed -module is now output only if a higher verbosity level is specified (at least -"-vv"). diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 4dad6fd4f..a692eee15 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-3.9.1 release-3.9.0 release-3.8.2 release-3.8.1 diff --git a/doc/en/announce/release-3.9.1.rst b/doc/en/announce/release-3.9.1.rst new file mode 100644 index 000000000..f050e4653 --- /dev/null +++ b/doc/en/announce/release-3.9.1.rst @@ -0,0 +1,20 @@ +pytest-3.9.1 +======================================= + +pytest 3.9.1 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 https://docs.pytest.org/en/latest/changelog.html. + +Thanks to all who contributed to this release, among them: + +* Bruno Oliveira +* Ronny Pfannschmidt +* Thomas Hisch + + +Happy testing, +The pytest Development Team diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index cb6368a64..a2cb8a676 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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected @@ -44,7 +44,7 @@ Or the inverse, running all tests except the webtest ones:: $ pytest -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected @@ -64,7 +64,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item @@ -77,7 +77,7 @@ You can also select on the class:: $ pytest -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 1 item @@ -90,7 +90,7 @@ Or select multiple nodes:: $ pytest -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -128,7 +128,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 3 deselected @@ -141,7 +141,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 1 deselected @@ -156,7 +156,7 @@ Or to select "http" and "quick" tests:: $ pytest -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 4 items / 2 deselected diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index bda15065a..a266b5bfe 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -59,7 +59,7 @@ consulted when reporting in ``verbose`` mode:: nonpython $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR/nonpython, inifile: collecting ... collected 2 items diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index b16070287..df83ec97e 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -357,7 +357,7 @@ which will add info only when run with "--v":: $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache info1: did you know that ... did you? diff --git a/doc/en/fixture.rst b/doc/en/fixture.rst index 65664c0b2..fa111afa4 100644 --- a/doc/en/fixture.rst +++ b/doc/en/fixture.rst @@ -732,7 +732,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:: $ pytest test_fixture_marks.py -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 3 items @@ -775,7 +775,7 @@ Here we declare an ``app`` fixture which receives the previously defined $ pytest -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 2 items @@ -844,7 +844,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.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python3.6 + platform linux -- Python 3.x.y, pytest-3.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: $REGENDOC_TMPDIR, inifile: collecting ... collected 8 items From c5bbf8ac73a78fd15016296e808d13f2a2a983f1 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 16 Oct 2018 22:21:15 +0200 Subject: [PATCH 35/44] make note about the unpublished 3.9.0 release --- CHANGELOG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 7a5c83a00..015f9dbd3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -29,8 +29,8 @@ Features "-vv"). -pytest 3.9.0 (2018-10-15) -========================= +pytest 3.9.0 (2018-10-15 - not published due to a release automation bug) +========================================================================= Deprecations ------------ From 215a2ed3dec9d762a2fadb08c5393eb36ddf224f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 16 Oct 2018 21:00:57 -0300 Subject: [PATCH 36/44] Update warnings docs Some points on the document work different in 3.9, plus changed the order of the sections a bit to make more sense for users reading it for the first time. --- doc/en/warnings.rst | 205 +++++++++++++++++++++----------------------- 1 file changed, 96 insertions(+), 109 deletions(-) diff --git a/doc/en/warnings.rst b/doc/en/warnings.rst index 060057d91..f83377cf6 100644 --- a/doc/en/warnings.rst +++ b/doc/en/warnings.rst @@ -75,60 +75,6 @@ Both ``-W`` command-line option and ``filterwarnings`` ini option are based on P `-W option`_ and `warnings.simplefilter`_, so please refer to those sections in the Python documentation for other examples and advanced usage. -Disabling warning summary -------------------------- - -Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the -warning summary entirely from the test run output. - -Disabling warning capture entirely ----------------------------------- - -This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with: - - .. code-block:: ini - - [pytest] - addopts = -p no:warnings - -Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings -using an external system. - - -.. _`deprecation-warnings`: - -DeprecationWarning and PendingDeprecationWarning ------------------------------------------------- - -.. versionadded:: 3.8 -.. versionchanged:: 3.9 - -By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning``. - -Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over -(such as third-party libraries), in which case you might use the standard warning filters options (ini or marks). -For example: - -.. code-block:: ini - - [pytest] - filterwarnings = - ignore:.*U.*mode is deprecated:DeprecationWarning - - -.. note:: - If warnings are configured at the interpreter level, using - the `PYTHONWARNINGS `_ environment variable or the - ``-W`` command-line option, pytest will not configure any filters by default. - -.. note:: - This feature makes pytest more compliant with `PEP-0506 `_ which suggests that those warnings should - be shown by default by test runners, but pytest doesn't follow ``PEP-0506`` completely because resetting all - warning filters like suggested in the PEP will break existing test suites that configure warning filters themselves - by calling ``warnings.simplefilter`` (see issue `#2430 `_ - for an example of that). - - .. _`filterwarnings`: ``@pytest.mark.filterwarnings`` @@ -167,24 +113,6 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable: pytestmark = pytest.mark.filterwarnings("error") -.. note:: - - Except for these features, pytest does not change the python warning filter; it only captures - and displays the warnings which are issued with respect to the currently configured filter, - including changes to the filter made by test functions or by the system under test. - -.. note:: - - ``DeprecationWarning`` and ``PendingDeprecationWarning`` are hidden by the standard library - by default so you have to explicitly configure them to be displayed in your ``pytest.ini``: - - .. code-block:: ini - - [pytest] - filterwarnings = - once::DeprecationWarning - once::PendingDeprecationWarning - *Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_ *plugin.* @@ -193,6 +121,102 @@ decorator or to all tests in a module by setting the ``pytestmark`` variable: .. _warnings.simplefilter: https://docs.python.org/3/library/warnings.html#warnings.simplefilter .. _`pytest-warnings`: https://github.com/fschulze/pytest-warnings +Disabling warnings summary +-------------------------- + +Although not recommended, you can use the ``--disable-warnings`` command-line option to suppress the +warning summary entirely from the test run output. + +Disabling warning capture entirely +---------------------------------- + +This plugin is enabled by default but can be disabled entirely in your ``pytest.ini`` file with: + + .. code-block:: ini + + [pytest] + addopts = -p no:warnings + +Or passing ``-p no:warnings`` in the command-line. This might be useful if your test suites handles warnings +using an external system. + + +.. _`deprecation-warnings`: + +DeprecationWarning and PendingDeprecationWarning +------------------------------------------------ + +.. versionadded:: 3.8 +.. versionchanged:: 3.9 + +By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from +user code and third-party libraries, as recommended by `PEP-0506 `_. +This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed. + +Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over +(such as third-party libraries), in which case you might use the warning filters options (ini or marks) to ignore +those warnings. + +For example: + +.. code-block:: ini + + [pytest] + filterwarnings = + ignore:.*U.*mode is deprecated:DeprecationWarning + + +This will ignore all warnings of type ``DeprecationWarning`` where the start of the message matches +the regular expression ``".*U.*mode is deprecated"``. + +.. note:: + If warnings are configured at the interpreter level, using + the `PYTHONWARNINGS `_ environment variable or the + ``-W`` command-line option, pytest will not configure any filters by default. + + Also pytest doesn't follow ``PEP-0506`` suggestion of resetting all warning filters because + it might break test suites that configure warning filters themselves + by calling ``warnings.simplefilter`` (see issue `#2430 `_ + for an example of that). + + +.. _`ensuring a function triggers a deprecation warning`: + +.. _ensuring_function_triggers: + +Ensuring code triggers a deprecation warning +-------------------------------------------- + +You can also call a global helper for checking +that a certain function call triggers a ``DeprecationWarning`` or +``PendingDeprecationWarning``:: + + import pytest + + def test_global(): + pytest.deprecated_call(myfunction, 17) + +By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be +caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide +them. If you wish to record them in your own code, use the +command ``warnings.simplefilter('always')``:: + + import warnings + import pytest + + def test_deprecation(recwarn): + warnings.simplefilter('always') + warnings.warn("deprecated", DeprecationWarning) + assert len(recwarn) == 1 + assert recwarn.pop(DeprecationWarning) + +You can also use it as a contextmanager:: + + def test_global(): + with pytest.deprecated_call(): + myobject.deprecated_method() + + .. _`asserting warnings`: @@ -299,43 +323,6 @@ warnings, or index into it to get a particular recorded warning. Full API: :class:`WarningsRecorder`. -.. _`ensuring a function triggers a deprecation warning`: - -.. _ensuring_function_triggers: - -Ensuring a function triggers a deprecation warning -------------------------------------------------------- - -You can also call a global helper for checking -that a certain function call triggers a ``DeprecationWarning`` or -``PendingDeprecationWarning``:: - - import pytest - - def test_global(): - pytest.deprecated_call(myfunction, 17) - -By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be -caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide -them. If you wish to record them in your own code, use the -command ``warnings.simplefilter('always')``:: - - import warnings - import pytest - - def test_deprecation(recwarn): - warnings.simplefilter('always') - warnings.warn("deprecated", DeprecationWarning) - assert len(recwarn) == 1 - assert recwarn.pop(DeprecationWarning) - -You can also use it as a contextmanager:: - - def test_global(): - with pytest.deprecated_call(): - myobject.deprecated_method() - - .. _internal-warnings: From ab8907f6f5b7a0d9df645651dbb34732b775b9cb Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Tue, 16 Oct 2018 17:23:29 -0700 Subject: [PATCH 37/44] s/comparision/comparison/g [ci skip] --- CHANGELOG.rst | 2 +- doc/en/deprecations.rst | 2 +- src/_pytest/logging.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 015f9dbd3..14881e373 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -45,7 +45,7 @@ Deprecations Users should just ``import pytest`` and access those objects using the ``pytest`` module. * ``request.cached_setup``, this was the precursor of the setup/teardown mechanism available to fixtures. You can - consult `funcarg comparision section in the docs `_. + consult `funcarg comparison section in the docs `_. * Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector`` subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 30746d035..2fb451d7e 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -56,7 +56,7 @@ This should be updated to make use of standard fixture mechanisms: session.close() -You can consult `funcarg comparision section in the docs `_ for +You can consult `funcarg comparison section in the docs `_ for more information. This has been documented as deprecated for years, but only now we are actually emitting deprecation warnings. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index fe6711ac7..ee6795250 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -279,7 +279,7 @@ class LogCaptureFixture(object): Unlike 'records', which contains the format string and parameters for interpolation, log messages in this list are all interpolated. Unlike 'text', which contains the output from the handler, log messages in this list are unadorned with - levels, timestamps, etc, making exact comparisions more reliable. + levels, timestamps, etc, making exact comparisons more reliable. Note that traceback or stack info (from :func:`logging.exception` or the `exc_info` or `stack_info` arguments to the logging functions) is not included, as this is added by the formatter in the handler. From ba5a2955443313dd4b49ce539508ef5be93966b2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 17 Oct 2018 14:53:41 -0300 Subject: [PATCH 38/44] Fix hook name in deprecations.rst As mentioned in https://github.com/pytest-dev/pytest/issues/4128#issuecomment-430690498 --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 30746d035..3a06c7d5f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -68,7 +68,7 @@ Using ``Class`` in custom Collectors .. deprecated:: 3.9 Using objects named ``"Class"`` as a way to customize the type of nodes that are collected in ``Collector`` -subclasses has been deprecated. Users instead should use ``pytest_collect_make_item`` to customize node types during +subclasses has been deprecated. Users instead should use ``pytest_pycollect_makeitem`` to customize node types during collection. This issue should affect only advanced plugins who create new collection types, so if you see this warning From 4f4c91caf5a95d6aa9f0207f9ec880f1be75dd99 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 17 Oct 2018 20:08:07 +0200 Subject: [PATCH 39/44] fix #4177 - pin setuptools>=40.0 --- changelog/4177.bugfix.rst | 1 + pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog/4177.bugfix.rst diff --git a/changelog/4177.bugfix.rst b/changelog/4177.bugfix.rst new file mode 100644 index 000000000..b26ad4bad --- /dev/null +++ b/changelog/4177.bugfix.rst @@ -0,0 +1 @@ +Pin ``setuptools>=40.0`` to support ``py_modules`` in ``setup.cfg`` diff --git a/pyproject.toml b/pyproject.toml index c83bd853d..d17b936c1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] requires = [ # sync with setup.py until we discard non-pep-517/518 - "setuptools>=30.3", + "setuptools>=40.0", "setuptools-scm", "wheel", ] diff --git a/setup.py b/setup.py index 6bab5312d..ac0739455 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ if "_PYTEST_SETUP_SKIP_PLUGGY_DEP" not in os.environ: def main(): setup( use_scm_version={"write_to": "src/_pytest/_version.py"}, - setup_requires=["setuptools-scm", "setuptools>=30.3"], + setup_requires=["setuptools-scm", "setuptools>=40.0"], package_dir={"": "src"}, install_requires=INSTALL_REQUIRES, ) From cc335d44a09e7d3e204b9304f4c0361ebce4c726 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 17 Oct 2018 20:43:27 +0200 Subject: [PATCH 40/44] fix #4179 - bring back the current testrun symlink --- changelog/4179.bugfix.rst | 1 + src/_pytest/pathlib.py | 21 +++++++++++++++++++++ testing/test_tmpdir.py | 4 ++++ 3 files changed, 26 insertions(+) create mode 100644 changelog/4179.bugfix.rst diff --git a/changelog/4179.bugfix.rst b/changelog/4179.bugfix.rst new file mode 100644 index 000000000..6f7467f50 --- /dev/null +++ b/changelog/4179.bugfix.rst @@ -0,0 +1 @@ +Restore the tmpdir behaviour of symlinking the current test run. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index cda5e9947..081fce904 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -100,6 +100,26 @@ else: _max = max +def _force_symlink(root, target, link_to): + """helper to create the current symlink + + its full of race conditions that are reasonably ok to ignore + for the contex of best effort linking to the latest testrun + + the presumption being thatin case of much parallelism + the inaccuracy is going to be acceptable + """ + current_symlink = root.joinpath(target) + try: + current_symlink.unlink() + except OSError: + pass + try: + current_symlink.symlink_to(link_to) + except Exception: + pass + + def make_numbered_dir(root, prefix): """create a directory with a increased number as suffix for the given prefix""" for i in range(10): @@ -112,6 +132,7 @@ def make_numbered_dir(root, prefix): except Exception: pass else: + _force_symlink(root, prefix + "current", new_path) return new_path else: raise EnvironmentError( diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 9f4158eb7..441714528 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -196,6 +196,10 @@ class TestNumberedDir(object): assert d.name.startswith(self.PREFIX) assert d.name.endswith(str(i)) + symlink = tmp_path.joinpath(self.PREFIX + "current") + assert symlink.is_symlink() + assert symlink.resolve() == d.resolve() + def test_cleanup_lock_create(self, tmp_path): d = tmp_path.joinpath("test") d.mkdir() From 8dca8f3c9f3ca09bfa11fb1b322a4707c098bab6 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 17 Oct 2018 21:16:44 +0200 Subject: [PATCH 41/44] fix test_cleanup_keep for expecting symlinks --- testing/test_tmpdir.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 441714528..f1b6fe424 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -248,7 +248,7 @@ class TestNumberedDir(object): def test_cleanup_keep(self, tmp_path): self._do_cleanup(tmp_path) - a, b = tmp_path.iterdir() + a, b = (x for x in tmp_path.iterdir() if not x.is_symlink()) print(a, b) def test_cleanup_locked(self, tmp_path): From 56dd7bc551f739a00795ab866578ce3789fa572e Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 17 Oct 2018 21:39:23 +0200 Subject: [PATCH 42/44] TestNumberedDir: ignore that symlinks arent created on windows --- testing/test_tmpdir.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index f1b6fe424..3c413e7c2 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -197,8 +197,10 @@ class TestNumberedDir(object): assert d.name.endswith(str(i)) symlink = tmp_path.joinpath(self.PREFIX + "current") - assert symlink.is_symlink() - assert symlink.resolve() == d.resolve() + if symlink.exists(): + # unix + assert symlink.is_symlink() + assert symlink.resolve() == d.resolve() def test_cleanup_lock_create(self, tmp_path): d = tmp_path.joinpath("test") From 12f94b81c0b76dfcdf32290615d6755458b6d626 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 17 Oct 2018 18:18:08 -0300 Subject: [PATCH 43/44] No longer upload code coverage to coveralls We have since moved to codecov and uploading to coveralls is breaking OS-X builds for py37 [1], so we might as well take this opportunity to drop it. [1] https://travis-ci.org/pytest-dev/pytest/jobs/442858038 --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5c479feed..00abca0b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -93,12 +93,6 @@ after_success: coverage xml --ignore-errors coverage report -m --ignore-errors bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -F "${TOXENV//-/,},linux" - - # Coveralls does not support merged reports. - if [[ "$TOXENV" = py37 ]]; then - pip install coveralls - coveralls - fi fi notifications: From f694d8d6ad4320276001f2a4e40c717a8291d705 Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Thu, 18 Oct 2018 03:27:30 +0200 Subject: [PATCH 44/44] Make --color more colorful --- AUTHORS | 1 + changelog/4188.feature.rst | 1 + src/_pytest/terminal.py | 26 +++++++++++++------------- 3 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 changelog/4188.feature.rst diff --git a/AUTHORS b/AUTHORS index c63c0a005..e5bf56a65 100644 --- a/AUTHORS +++ b/AUTHORS @@ -202,6 +202,7 @@ Stefan Zimmermann Stefano Taschini Steffen Allner Stephan Obermann +Sven-Hendrik Haase Tadek Teleżyński Tarcisio Fischer Tareq Alayan diff --git a/changelog/4188.feature.rst b/changelog/4188.feature.rst new file mode 100644 index 000000000..d3169efc0 --- /dev/null +++ b/changelog/4188.feature.rst @@ -0,0 +1 @@ +Make ``--color`` emit colorful dots when not running in verbose mode. Earlier, it would only colorize the test-by-test output if ``--verbose`` was also passed. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 8deb330cc..d207dd785 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -263,7 +263,7 @@ class TerminalReporter(object): char = {"xfailed": "x", "skipped": "s"}.get(char, char) return char in self.reportchars - def write_fspath_result(self, nodeid, res): + def write_fspath_result(self, nodeid, res, **markup): fspath = self.config.rootdir.join(nodeid.split("::")[0]) if fspath != self.currentfspath: if self.currentfspath is not None and self._show_progress_info: @@ -272,7 +272,7 @@ class TerminalReporter(object): fspath = self.startdir.bestrelpath(fspath) self._tw.line() self._tw.write(fspath + " ") - self._tw.write(res) + self._tw.write(res, **markup) def write_ensure_prefix(self, prefix, extra="", **kwargs): if self.currentfspath != prefix: @@ -386,22 +386,22 @@ class TerminalReporter(object): # probably passed setup/teardown return running_xdist = hasattr(rep, "node") + if markup is None: + if rep.passed: + markup = {"green": True} + elif rep.failed: + markup = {"red": True} + elif rep.skipped: + markup = {"yellow": True} + else: + markup = {} if self.verbosity <= 0: if not running_xdist and self.showfspath: - self.write_fspath_result(rep.nodeid, letter) + self.write_fspath_result(rep.nodeid, letter, **markup) else: - self._tw.write(letter) + self._tw.write(letter, **markup) else: self._progress_nodeids_reported.add(rep.nodeid) - if markup is None: - if rep.passed: - markup = {"green": True} - elif rep.failed: - markup = {"red": True} - elif rep.skipped: - markup = {"yellow": True} - else: - markup = {} line = self._locationline(rep.nodeid, *rep.location) if not running_xdist: self.write_ensure_prefix(line, word, **markup)