summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_pytest/compat.py7
-rw-r--r--changelog/2707.bugfix1
-rw-r--r--testing/test_compat.py27
3 files changed, 32 insertions, 3 deletions
diff --git a/_pytest/compat.py b/_pytest/compat.py
index 45f9f86d4..54271ce4f 100644
--- a/_pytest/compat.py
+++ b/_pytest/compat.py
@@ -11,6 +11,7 @@ import functools
import py
import _pytest
+from _pytest.outcomes import TEST_OUTCOME
try:
@@ -221,14 +222,16 @@ def getimfunc(func):
def safe_getattr(object, name, default):
- """ Like getattr but return default upon any Exception.
+ """ Like getattr but return default upon any Exception or any OutcomeException.
Attribute access can potentially fail for 'evil' Python objects.
See issue #214.
+ It catches OutcomeException because of #2490 (issue #580), new outcomes are derived from BaseException
+ instead of Exception (for more details check #2707)
"""
try:
return getattr(object, name, default)
- except Exception:
+ except TEST_OUTCOME:
return default
diff --git a/changelog/2707.bugfix b/changelog/2707.bugfix
new file mode 100644
index 000000000..55af3e2a7
--- /dev/null
+++ b/changelog/2707.bugfix
@@ -0,0 +1 @@
+`compat.safe_getattr` now catches OutcomeExceptions too \ No newline at end of file
diff --git a/testing/test_compat.py b/testing/test_compat.py
index 7b2251ef6..c74801c6c 100644
--- a/testing/test_compat.py
+++ b/testing/test_compat.py
@@ -2,7 +2,8 @@ from __future__ import absolute_import, division, print_function
import sys
import pytest
-from _pytest.compat import is_generator, get_real_func
+from _pytest.compat import is_generator, get_real_func, safe_getattr
+from _pytest.outcomes import OutcomeException
def test_is_generator():
@@ -74,3 +75,27 @@ def test_is_generator_async_syntax(testdir):
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(['*1 passed*'])
+
+
+class ErrorsHelper(object):
+ @property
+ def raise_exception(self):
+ raise Exception('exception should be catched')
+
+ @property
+ def raise_fail(self):
+ pytest.fail('fail should be catched')
+
+
+def test_helper_failures():
+ helper = ErrorsHelper()
+ with pytest.raises(Exception):
+ helper.raise_exception
+ with pytest.raises(OutcomeException):
+ helper.raise_fail
+
+
+def test_safe_getattr():
+ helper = ErrorsHelper()
+ assert safe_getattr(helper, 'raise_exception', 'default') == 'default'
+ assert safe_getattr(helper, 'raise_fail', 'default') == 'default'