From 671684be5c40ff70b57c53fa4c01bd60a992511b Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 5 May 2009 21:24:47 +0200 Subject: [PATCH] a new plugin for asserting that warnings have been shown to a user. --HG-- branch : trunk --- py/test/defaultconftest.py | 2 +- py/test/plugin/pytest_recwarn.py | 94 ++++++++++++++++++++++++++++++++ py/test/testing/test_collect.py | 5 +- 3 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 py/test/plugin/pytest_recwarn.py diff --git a/py/test/defaultconftest.py b/py/test/defaultconftest.py index 4b0b09c22..5de496c17 100644 --- a/py/test/defaultconftest.py +++ b/py/test/defaultconftest.py @@ -10,5 +10,5 @@ Generator = py.test.collect.Generator Function = py.test.collect.Function Instance = py.test.collect.Instance -pytest_plugins = "default terminal xfail tmpdir execnetcleanup monkeypatch pdb".split() +pytest_plugins = "default terminal xfail tmpdir execnetcleanup monkeypatch recwarn pdb".split() diff --git a/py/test/plugin/pytest_recwarn.py b/py/test/plugin/pytest_recwarn.py new file mode 100644 index 000000000..8b1f56036 --- /dev/null +++ b/py/test/plugin/pytest_recwarn.py @@ -0,0 +1,94 @@ +""" + +"recwarn" funcarg plugin that helps to assert +that warnings are shown to a user. See the test +at the bottom for an example. + +""" +import py +import os + +class RecwarnPlugin: + def pytest_funcarg__recwarn(self, request): + """ check that warnings have been raised. """ + warnings = WarningsRecorder() + request.addfinalizer(warnings.finalize) + return warnings + +class RecordedWarning: + def __init__(self, message, category, filename, lineno, line): + self.message = message + self.category = category + self.filename = filename + self.lineno = lineno + self.line = line + +class WarningsRecorder: + def __init__(self): + warningmodule = py.std.warnings + self.list = [] + def showwarning(message, category, filename, lineno, line=0): + self.list.append(RecordedWarning( + message, category, filename, lineno, line)) + try: + self.old_showwarning(message, category, + filename, lineno, line=line) + except TypeError: + # < python2.6 + self.old_showwarning(message, category, filename, lineno) + self.old_showwarning = warningmodule.showwarning + warningmodule.showwarning = showwarning + + def pop(self, cls=Warning): + """ pop the first recorded warning, raise exception if not exists.""" + for i, w in py.builtin.enumerate(self.list): + if issubclass(w.category, cls): + return self.list.pop(i) + assert 0, "%r not found in %r" %(cls, self.list) + + #def resetregistry(self): + # import warnings + # warnings.onceregistry.clear() + # warnings.__warningregistry__.clear() + + def reset(self): + self.list[:] = [] + + def finalize(self): + py.std.warnings.showwarning = self.old_showwarning + +def test_WarningRecorder(): + showwarning = py.std.warnings.showwarning + rec = WarningsRecorder() + assert py.std.warnings.showwarning != showwarning + assert not rec.list + py.std.warnings.warn_explicit("hello", UserWarning, "xyz", 13) + assert len(rec.list) == 1 + py.std.warnings.warn(DeprecationWarning("hello")) + assert len(rec.list) == 2 + warn = rec.pop() + assert str(warn.message) == "hello" + l = rec.list + rec.reset() + assert len(rec.list) == 0 + assert l is rec.list + py.test.raises(AssertionError, "rec.pop()") + rec.finalize() + assert showwarning == py.std.warnings.showwarning + +def test_recwarn_functional(testdir): + sorter = testdir.inline_runsource(""" + pytest_plugins = 'pytest_recwarn', + import warnings + oldwarn = warnings.showwarning + def test_method(recwarn): + assert warnings.showwarning != oldwarn + warnings.warn("hello") + warn = recwarn.pop() + assert isinstance(warn.message, UserWarning) + def test_finalized(): + assert warnings.showwarning == oldwarn + """) + res = sorter.countoutcomes() + assert tuple(res) == (2, 0, 0), res + diff --git a/py/test/testing/test_collect.py b/py/test/testing/test_collect.py index 954207ed4..ae7084752 100644 --- a/py/test/testing/test_collect.py +++ b/py/test/testing/test_collect.py @@ -131,9 +131,10 @@ class TestCollectFS: names = [x.name for x in col.collect()] assert names == ["dir1", "dir2", "test_one.py", "test_two.py", "x"] - def test_collector_deprecated_run_method(self, testdir): + def test_collector_deprecated_run_method(self, testdir, recwarn): modcol = testdir.getmodulecol("pass") - res1 = py.test.deprecated_call(modcol.run) + res1 = modcol.run() + recwarn.pop(DeprecationWarning) res2 = modcol.collect() assert res1 == [x.name for x in res2]