diff --git a/CHANGELOG b/CHANGELOG index 8c75acec4..ecc93a3b9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -104,6 +104,9 @@ 2.7.3 (compared to 2.7.2) ----------------------------- +- fix issue856: consider --color parameter in all outputs (for example + --fixtures). Thanks Barney Gale for the report and Bruno Oliveira for the PR. + - fix issue744: fix for ast.Call changes in Python 3.5+. Thanks Guido van Rossum, Matthias Bussonnier, Stefan Zimmermann and Thomas Kluyver. @@ -115,6 +118,10 @@ - preserve warning functions after call to pytest.deprecated_call. Thanks Pieter Mulder for PR. +- fix issue854: autouse yield_fixtures defined as class members of + unittest.TestCase subclasses now work as expected. + Thannks xmo-odoo for the report and Bruno Oliveira for the PR. + - fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the fixtures declared on the first one. Thanks Florian Bruhin for reporting and Bruno Oliveira for the PR. diff --git a/_pytest/config.py b/_pytest/config.py index a74acceaf..c8a79f6b5 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -1121,3 +1121,15 @@ def setns(obj, dic): # pytest.__all__.append(name) setattr(pytest, name, value) + +def create_terminal_writer(config, *args, **kwargs): + """Create a TerminalWriter instance configured according to the options + in the config object. Every code which requires a TerminalWriter object + and has access to a config object should use this function. + """ + tw = py.io.TerminalWriter(*args, **kwargs) + if config.option.color == 'yes': + tw.hasmarkup = True + if config.option.color == 'no': + tw.hasmarkup = False + return tw diff --git a/_pytest/genscript.py b/_pytest/genscript.py index fb2ca04cd..d6f452370 100755 --- a/_pytest/genscript.py +++ b/_pytest/genscript.py @@ -68,9 +68,10 @@ def pytest_addoption(parser): help="create standalone pytest script at given target path.") def pytest_cmdline_main(config): + import _pytest.config genscript = config.getvalue("genscript") if genscript: - tw = py.io.TerminalWriter() + tw = _pytest.config.create_terminal_writer(config) deps = ['py', 'pluggy', '_pytest', 'pytest'] if sys.version_info < (2,7): deps.append("argparse") diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py index d410c6270..af35e241e 100644 --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -62,7 +62,8 @@ def pytest_cmdline_main(config): return 0 def showhelp(config): - tw = py.io.TerminalWriter() + import _pytest.config + tw = _pytest.config.create_terminal_writer(config) tw.write(config._parser.optparser.format_help()) tw.line() tw.line() diff --git a/_pytest/mark.py b/_pytest/mark.py index 9f2e05f67..c3dc692f0 100644 --- a/_pytest/mark.py +++ b/_pytest/mark.py @@ -1,6 +1,5 @@ """ generic mechanism for marking and selecting python functions. """ import inspect -import py class MarkerError(Exception): @@ -44,9 +43,10 @@ def pytest_addoption(parser): def pytest_cmdline_main(config): + import _pytest.config if config.option.markers: config._do_configure() - tw = py.io.TerminalWriter() + tw = _pytest.config.create_terminal_writer(config) for line in config.getini("markers"): name, rest = line.split(":", 1) tw.write("@pytest.mark.%s:" % name, bold=True) diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py index f76d14a2f..f5e479158 100644 --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -1,6 +1,6 @@ """ submit failure or test session information to a pastebin service. """ import pytest -import py, sys +import sys import tempfile @@ -69,6 +69,7 @@ def create_new_paste(contents): return 'bad response: ' + response def pytest_terminal_summary(terminalreporter): + import _pytest.config if terminalreporter.config.option.pastebin != "failed": return tr = terminalreporter @@ -79,7 +80,7 @@ def pytest_terminal_summary(terminalreporter): msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc except AttributeError: msg = tr._getfailureheadline(rep) - tw = py.io.TerminalWriter(stringio=True) + tw = _pytest.config.create_terminal_writer(terminalreporter.config, stringio=True) rep.toterminal(tw) s = tw.stringio.getvalue() assert len(s) diff --git a/_pytest/pdb.py b/_pytest/pdb.py index d0f7509f9..78fedd373 100644 --- a/_pytest/pdb.py +++ b/_pytest/pdb.py @@ -4,7 +4,6 @@ import pdb import sys import pytest -import py def pytest_addoption(parser): @@ -23,23 +22,27 @@ def pytest_configure(config): old = (pdb.set_trace, pytestPDB._pluginmanager) def fin(): pdb.set_trace, pytestPDB._pluginmanager = old + pytestPDB._config = None pdb.set_trace = pytest.set_trace pytestPDB._pluginmanager = config.pluginmanager + pytestPDB._config = config config._cleanup.append(fin) class pytestPDB: """ Pseudo PDB that defers to the real pdb. """ _pluginmanager = None + _config = None def set_trace(self): """ invoke PDB set_trace debugging, dropping any IO capturing. """ + import _pytest.config frame = sys._getframe().f_back capman = None if self._pluginmanager is not None: capman = self._pluginmanager.getplugin("capturemanager") if capman: capman.suspendcapture(in_=True) - tw = py.io.TerminalWriter() + tw = _pytest.config.create_terminal_writer(self._config) tw.line() tw.sep(">", "PDB set_trace (IO-capturing turned off)") self._pluginmanager.hook.pytest_enter_pdb() diff --git a/_pytest/python.py b/_pytest/python.py index 2a9fa4421..4623d3d04 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -983,9 +983,10 @@ def showfixtures(config): return wrap_session(config, _showfixtures_main) def _showfixtures_main(config, session): + import _pytest.config session.perform_collect() curdir = py.path.local() - tw = py.io.TerminalWriter() + tw = _pytest.config.create_terminal_writer(config) verbose = config.getvalue("verbose") fm = session._fixturemanager @@ -1924,10 +1925,13 @@ class FixtureDef: self.finish() assert not hasattr(self, "cached_result") + fixturefunc = self.func + if self.unittest: - result = self.func(request.instance, **kwargs) + if request.instance is not None: + # bind the unbound method to the TestCase instance + fixturefunc = self.func.__get__(request.instance) else: - fixturefunc = self.func # the fixture function needs to be bound to the actual # request.instance so that code working with "self" behaves # as expected. @@ -1935,12 +1939,13 @@ class FixtureDef: fixturefunc = getimfunc(self.func) if fixturefunc != self.func: fixturefunc = fixturefunc.__get__(request.instance) - try: - result = call_fixture_func(fixturefunc, request, kwargs, - self.yieldctx) - except Exception: - self.cached_result = (None, my_cache_key, sys.exc_info()) - raise + + try: + result = call_fixture_func(fixturefunc, request, kwargs, + self.yieldctx) + except Exception: + self.cached_result = (None, my_cache_key, sys.exc_info()) + raise self.cached_result = (result, my_cache_key, None) return result diff --git a/_pytest/terminal.py b/_pytest/terminal.py index 98ac5556b..5365b4300 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -89,6 +89,7 @@ class WarningReport: class TerminalReporter: def __init__(self, config, file=None): + import _pytest.config self.config = config self.verbosity = self.config.option.verbose self.showheader = self.verbosity >= 0 @@ -100,11 +101,8 @@ class TerminalReporter: self.startdir = py.path.local() if file is None: file = sys.stdout - self._tw = self.writer = py.io.TerminalWriter(file) - if self.config.option.color == 'yes': - self._tw.hasmarkup = True - if self.config.option.color == 'no': - self._tw.hasmarkup = False + self._tw = self.writer = _pytest.config.create_terminal_writer(config, + file) self.currentfspath = None self.reportchars = getreportopt(config) self.hasmarkup = self._tw.hasmarkup diff --git a/testing/python/fixture.py b/testing/python/fixture.py index efa0eb6af..8bf738c5d 100644 --- a/testing/python/fixture.py +++ b/testing/python/fixture.py @@ -622,6 +622,11 @@ class TestRequestBasic: *arg1* """) + def test_show_fixtures_color_yes(self, testdir): + testdir.makepyfile("def test_this(): assert 1") + result = testdir.runpytest('--color=yes', '--fixtures') + assert '\x1b[32mtmpdir' in result.stdout.str() + def test_newstyle_with_request(self, testdir): testdir.makepyfile(""" import pytest diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 3b9bd677b..b9ce7b5fa 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -605,18 +605,23 @@ def test_unittest_unexpected_failure(testdir): ]) - -def test_unittest_setup_interaction(testdir): +@pytest.mark.parametrize('fix_type, stmt', [ + ('fixture', 'return'), + ('yield_fixture', 'yield'), +]) +def test_unittest_setup_interaction(testdir, fix_type, stmt): testdir.makepyfile(""" import unittest import pytest class MyTestCase(unittest.TestCase): - @pytest.fixture(scope="class", autouse=True) + @pytest.{fix_type}(scope="class", autouse=True) def perclass(self, request): request.cls.hello = "world" - @pytest.fixture(scope="function", autouse=True) + {stmt} + @pytest.{fix_type}(scope="function", autouse=True) def perfunction(self, request): request.instance.funcname = request.function.__name__ + {stmt} def test_method1(self): assert self.funcname == "test_method1" @@ -627,7 +632,7 @@ def test_unittest_setup_interaction(testdir): def test_classattr(self): assert self.__class__.hello == "world" - """) + """.format(fix_type=fix_type, stmt=stmt)) result = testdir.runpytest() result.stdout.fnmatch_lines("*3 passed*") diff --git a/tox.ini b/tox.ini index d2faae652..c5dfa03f9 100644 --- a/tox.ini +++ b/tox.ini @@ -98,6 +98,7 @@ commands= make html [testenv:doctesting] +basepython = python3.4 changedir=doc/en deps=PyYAML commands= py.test -rfsxX {posargs}