diff --git a/changelog/344.bugfix b/changelog/344.bugfix new file mode 100644 index 0000000..a88fca2 --- /dev/null +++ b/changelog/344.bugfix @@ -0,0 +1 @@ +Fix issue where Warnings could cause pytest to fail if they do not set the args attribute correctly. diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index dcf717d..987dbe6 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -429,6 +429,35 @@ class TestTerminalReporting: result = testdir.runpytest(n) result.stdout.fnmatch_lines(["*this is a warning*", "*1 passed, 1 warnings*"]) + @pytest.mark.parametrize("n", ["-n0", "-n1"]) + def test_custom_subclass(self, testdir, n): + """Check that warning subclasses that don't honor the args attribute don't break + pytest-xdist (#344) + """ + from pkg_resources import parse_version + + if parse_version(pytest.__version__) < parse_version("3.1"): + pytest.skip("pytest warnings requires >= 3.1") + + testdir.makepyfile( + """ + import warnings, py, pytest + + class MyWarning(UserWarning): + + def __init__(self, p1, p2): + self.p1 = p1 + self.p2 = p2 + self.args = () + + def test_func(request): + warnings.warn(MyWarning("foo", 1)) + """ + ) + testdir.syspathinsert() + result = testdir.runpytest(n) + result.stdout.fnmatch_lines(["*MyWarning*", "*1 passed, 1 warnings*"]) + def test_logfinish_hook(self, testdir): """Ensure the pytest_runtest_logfinish hook is being properly handled""" from _pytest import hookspec diff --git a/xdist/remote.py b/xdist/remote.py index 091bde8..bee3471 100644 --- a/xdist/remote.py +++ b/xdist/remote.py @@ -182,7 +182,7 @@ def serialize_warning_message(warning_message): message_module = type(warning_message.message).__module__ message_class_name = type(warning_message.message).__name__ message_args = warning_message.message.args - message_str = None + message_str = str(warning_message.message) else: message_str = warning_message.message message_module = None diff --git a/xdist/workermanage.py b/xdist/workermanage.py index b607d4e..9eb6418 100644 --- a/xdist/workermanage.py +++ b/xdist/workermanage.py @@ -426,7 +426,15 @@ def unserialize_warning_message(data): if data["message_module"]: mod = importlib.import_module(data["message_module"]) cls = getattr(mod, data["message_class_name"]) - message = cls(*data["message_args"]) + try: + message = cls(*data["message_args"]) + except TypeError: + message_text = "{mod}.{cls}: {msg}".format( + mod=data["message_module"], + cls=data["message_class_name"], + msg=data["message_str"], + ) + message = Warning(message_text) else: message = data["message_str"]