Merge pull request #1196 from nicoddemus/deprecated-call-1190

Make deprecated_call() use monkey-patching again , fixes #1190
This commit is contained in:
Ronny Pfannschmidt 2015-11-27 22:09:09 +01:00
commit 604a021a2a
3 changed files with 83 additions and 33 deletions

View File

@ -1,3 +1,11 @@
2.8.4.dev
---------
- fix #1190: ``deprecated_call()`` now works when the deprecated
function has been already called by another test in the same
module. Thanks Mikhail Chernykh for the report and Bruno Oliveira for the
PR.
2.8.3
-----

View File

@ -29,18 +29,39 @@ def pytest_namespace():
def deprecated_call(func, *args, **kwargs):
"""Assert that ``func(*args, **kwargs)`` triggers a DeprecationWarning.
"""
wrec = WarningsRecorder()
with wrec:
warnings.simplefilter('always') # ensure all warnings are triggered
ret = func(*args, **kwargs)
""" assert that calling ``func(*args, **kwargs)`` triggers a
``DeprecationWarning`` or ``PendingDeprecationWarning``.
depwarnings = (DeprecationWarning, PendingDeprecationWarning)
if not any(r.category in depwarnings for r in wrec):
Note: we cannot use WarningsRecorder here because it is still subject
to the mechanism that prevents warnings of the same type from being
triggered twice for the same module. See #1190.
"""
categories = []
def warn_explicit(message, category, *args, **kwargs):
categories.append(category)
old_warn_explicit(message, category, *args, **kwargs)
def warn(message, category=None, **kwargs):
if isinstance(message, Warning):
categories.append(message.__class__)
else:
categories.append(category)
old_warn(message, category, *args, **kwargs)
old_warn = warnings.warn
old_warn_explicit = warnings.warn_explicit
warnings.warn_explicit = warn_explicit
warnings.warn = warn
try:
ret = func(*args, **kwargs)
finally:
warnings.warn_explicit = old_warn_explicit
warnings.warn = old_warn
deprecation_categories = (DeprecationWarning, PendingDeprecationWarning)
if not any(issubclass(c, deprecation_categories) for c in categories):
__tracebackhide__ = True
raise AssertionError("%r did not produce DeprecationWarning" % (func,))
return ret

View File

@ -63,32 +63,30 @@ class TestWarningsRecorderChecker(object):
with rec:
pass # can't enter twice
#
# ============ test pytest.deprecated_call() ==============
#
def dep(i):
if i == 0:
py.std.warnings.warn("is deprecated", DeprecationWarning)
return 42
reg = {}
def dep_explicit(i):
if i == 0:
py.std.warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
filename="hello", lineno=3)
class TestDeprecatedCall(object):
"""test pytest.deprecated_call()"""
def dep(self, i):
if i == 0:
py.std.warnings.warn("is deprecated", DeprecationWarning)
return 42
def dep_explicit(self, i):
if i == 0:
py.std.warnings.warn_explicit("dep_explicit", category=DeprecationWarning,
filename="hello", lineno=3)
def test_deprecated_call_raises(self):
excinfo = pytest.raises(AssertionError,
"pytest.deprecated_call(dep, 3)")
with pytest.raises(AssertionError) as excinfo:
pytest.deprecated_call(self.dep, 3)
assert str(excinfo).find("did not produce") != -1
def test_deprecated_call(self):
pytest.deprecated_call(dep, 0)
pytest.deprecated_call(self.dep, 0)
def test_deprecated_call_ret(self):
ret = pytest.deprecated_call(dep, 0)
ret = pytest.deprecated_call(self.dep, 0)
assert ret == 42
def test_deprecated_call_preserves(self):
@ -104,25 +102,48 @@ class TestDeprecatedCall(object):
assert warn_explicit is py.std.warnings.warn_explicit
def test_deprecated_explicit_call_raises(self):
pytest.raises(AssertionError,
"pytest.deprecated_call(dep_explicit, 3)")
with pytest.raises(AssertionError):
pytest.deprecated_call(self.dep_explicit, 3)
def test_deprecated_explicit_call(self):
pytest.deprecated_call(dep_explicit, 0)
pytest.deprecated_call(dep_explicit, 0)
pytest.deprecated_call(self.dep_explicit, 0)
pytest.deprecated_call(self.dep_explicit, 0)
def test_deprecated_call_pending(self):
f = lambda: py.std.warnings.warn(PendingDeprecationWarning("hi"))
def f():
py.std.warnings.warn(PendingDeprecationWarning("hi"))
pytest.deprecated_call(f)
def test_deprecated_call_specificity(self):
other_warnings = [Warning, UserWarning, SyntaxWarning, RuntimeWarning,
FutureWarning, ImportWarning, UnicodeWarning]
for warning in other_warnings:
f = lambda: py.std.warnings.warn(warning("hi"))
def f():
py.std.warnings.warn(warning("hi"))
with pytest.raises(AssertionError):
pytest.deprecated_call(f)
def test_deprecated_function_already_called(self, testdir):
"""deprecated_call should be able to catch a call to a deprecated
function even if that function has already been called in the same
module. See #1190.
"""
testdir.makepyfile("""
import warnings
import pytest
def deprecated_function():
warnings.warn("deprecated", DeprecationWarning)
def test_one():
deprecated_function()
def test_two():
pytest.deprecated_call(deprecated_function)
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines('*=== 2 passed in *===')
class TestWarns(object):
def test_strings(self):