From e391314f8a40041f134a195bf1d32651b275c2bd Mon Sep 17 00:00:00 2001 From: Zoltan Kozma Date: Tue, 4 Oct 2016 13:29:12 +0100 Subject: [PATCH 1/3] Implementing no_cov feature for #131 --- README.rst | 13 +++++++++++++ src/pytest_cov/plugin.py | 25 +++++++++++++++++++++++++ tests/test_pytest_cov.py | 13 +++++++++++++ 3 files changed, 51 insertions(+) diff --git a/README.rst b/README.rst index f2416e2f..4e0e0345 100644 --- a/README.rst +++ b/README.rst @@ -312,6 +312,19 @@ subprocess. The python used by the subprocess must have pytest-cov installed. do normal site initialisation so that the environment variables can be detected and coverage started. +Coverage and debuggers +---------------------- + +When it comes to TDD one obviously would like to debug tests. Debuggers in Python use mostly the sys.settrace function +to gain access to context. Coverage uses the same technique to get access to the lines executed. Coverage does not play +well with other tracers simultaneously running. This manifests itself in behaviour that PyCharm might not hit a +breakpoint no matter what the user does. Since it is common practice to have coverage configuration in the pytest.ini +file and pytest does not support removeopts or similar the `--no-cov` flag can disable coverage completely. + +At the reporting part a warning message will show on screen + + WARNING: Coverage disabled by user! + Acknowledgements ================ diff --git a/src/pytest_cov/plugin.py b/src/pytest_cov/plugin.py index 1f7c5a92..5ef69b33 100644 --- a/src/pytest_cov/plugin.py +++ b/src/pytest_cov/plugin.py @@ -68,6 +68,9 @@ def pytest_addoption(parser): group.addoption('--no-cov-on-fail', action='store_true', default=False, help='do not report coverage if test run fails, ' 'default: False') + group.addoption('--no-cov', action='store_true', default=False, + help='Disable coverage report completely (useful for debuggers) ' + 'default: False') group.addoption('--cov-fail-under', action='store', metavar='MIN', type=int, help='Fail if the total coverage is less than MIN.') group.addoption('--cov-append', action='store_true', default=False, @@ -131,11 +134,16 @@ def __init__(self, options, pluginmanager, start=True): self.cov_total = None self.failed = False self._started = False + self._disabled = False self.options = options is_dist = (getattr(options, 'numprocesses', False) or getattr(options, 'distload', False) or getattr(options, 'dist', 'no') != 'no') + if options.no_cov: + self._disabled = True + return + if is_dist and start: self.start(engine.DistMaster) elif start: @@ -144,6 +152,7 @@ def __init__(self, options, pluginmanager, start=True): # slave is started in pytest hook def start(self, controller_cls, config=None, nodeid=None): + if config is None: # fake config option for engine class Config(object): @@ -170,6 +179,12 @@ def _is_slave(self, session): def pytest_sessionstart(self, session): """At session start determine our implementation and delegate to it.""" + + if self.options.no_cov: + # Coverage can be disabled because it does not cooperate with debuggers well.py + self._disabled = True + return + self.pid = os.getpid() if self._is_slave(session): nodeid = session.config.slaveinput.get('slaveid', @@ -207,6 +222,9 @@ def _failed_cov_total(self): def pytest_runtestloop(self, session): yield + if self._disabled: + return + compat_session = compat.SessionWrapper(session) self.failed = bool(compat_session.testsfailed) @@ -226,6 +244,13 @@ def pytest_runtestloop(self, session): compat_session.testsfailed += 1 def pytest_terminal_summary(self, terminalreporter): + if self._disabled: + markup = {'red': True, 'bold': True} + msg = ( + 'WARNING: Coverage disabled by user!' + ) + terminalreporter.write(msg, **markup) + return if self.cov_controller is None: return diff --git a/tests/test_pytest_cov.py b/tests/test_pytest_cov.py index 6cbf3414..2070089f 100644 --- a/tests/test_pytest_cov.py +++ b/tests/test_pytest_cov.py @@ -420,6 +420,19 @@ def test_no_cov_on_fail(testdir): result.stdout.fnmatch_lines(['*1 failed*']) +def test_no_cov(testdir): + script = testdir.makepyfile(SCRIPT) + + result = testdir.runpytest('-v', + '--cov=%s' % script.dirpath(), + '--cov-report=term-missing', + '--no-cov', + script) + + assert 'WARNING: Coverage disabled by user!' in result.stdout.str() + assert result.ret == 0 + + def test_cov_and_failure_report_on_fail(testdir): script = testdir.makepyfile(SCRIPT + SCRIPT_FAIL) From e78d309e359841ac81a61f7c2a04de6dcec83dfd Mon Sep 17 00:00:00 2001 From: Zoltan Kozma Date: Tue, 4 Oct 2016 15:15:29 +0100 Subject: [PATCH 2/3] tests don't want to work --- README.rst | 2 +- src/pytest_cov/plugin.py | 5 ++--- tests/test_pytest_cov.py | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 4e0e0345..49eb5bda 100644 --- a/README.rst +++ b/README.rst @@ -323,7 +323,7 @@ file and pytest does not support removeopts or similar the `--no-cov` flag can d At the reporting part a warning message will show on screen - WARNING: Coverage disabled by user! + Coverage disabled via --no-cov switch! Acknowledgements ================ diff --git a/src/pytest_cov/plugin.py b/src/pytest_cov/plugin.py index 5ef69b33..1e4b65a1 100644 --- a/src/pytest_cov/plugin.py +++ b/src/pytest_cov/plugin.py @@ -245,11 +245,10 @@ def pytest_runtestloop(self, session): def pytest_terminal_summary(self, terminalreporter): if self._disabled: - markup = {'red': True, 'bold': True} msg = ( - 'WARNING: Coverage disabled by user!' + 'Coverage disabled via --no-cov switch!' ) - terminalreporter.write(msg, **markup) + terminalreporter.config.warn(code='COV-U1', message=msg) return if self.cov_controller is None: return diff --git a/tests/test_pytest_cov.py b/tests/test_pytest_cov.py index 2070089f..61b94beb 100644 --- a/tests/test_pytest_cov.py +++ b/tests/test_pytest_cov.py @@ -429,7 +429,7 @@ def test_no_cov(testdir): '--no-cov', script) - assert 'WARNING: Coverage disabled by user!' in result.stdout.str() + assert 'WCOV-U1 None Coverage disabled via --no-cov switch!' in result.stderr.str() assert result.ret == 0 From c6478ce3de88321331ac6a3c359bfb41a55c6501 Mon Sep 17 00:00:00 2001 From: Zoltan Kozma Date: Wed, 5 Oct 2016 12:07:22 +0100 Subject: [PATCH 3/3] rw flag does not work either --- tests/test_pytest_cov.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_pytest_cov.py b/tests/test_pytest_cov.py index 61b94beb..244ff4ce 100644 --- a/tests/test_pytest_cov.py +++ b/tests/test_pytest_cov.py @@ -427,9 +427,10 @@ def test_no_cov(testdir): '--cov=%s' % script.dirpath(), '--cov-report=term-missing', '--no-cov', + '-rw', script) - assert 'WCOV-U1 None Coverage disabled via --no-cov switch!' in result.stderr.str() + assert 'WCOV-U1 None Coverage disabled via --no-cov switch!' in result.stdout.str() assert result.ret == 0