diff --git a/doc/changelog.d/3943.added.md b/doc/changelog.d/3943.added.md new file mode 100644 index 0000000000..7460dafca2 --- /dev/null +++ b/doc/changelog.d/3943.added.md @@ -0,0 +1 @@ +refactor: enhance error reporting in pytest output for better debugging \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 991257c6f7..62bc488569 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -315,24 +315,106 @@ class MyReporter(TerminalReporter): def short_test_summary(self): # your own impl goes here, for example: self.write_sep("=", "PyMAPDL Pytest short summary") + markup = self._tw.markup + + if self.hasmarkup: + color = True + else: + color = False + + ERROR_COLOR = {"Red": color, "bold": True} + FAILED_COLOR = {"red": color, "bold": True} + PASSED_COLOR = {"green": color} + SKIPPED_COLOR = {"green": color, "bold": True} + XPASSED_COLOR = {"Yellow": color, "bold": True} + XFAILED_COLOR = {"yellow": color} + + # self._tw.markup("asdf", Red=True) + + def get_normal_message(rep, header, message): + location = rep.location + if message: + message = f" - {message}" + + if location[0] == location[2]: + return f"{header} {rep.head_line}{message}" + else: + path = f"{location[0]}:{location[1]}" + return f"{header} {rep.head_line} - {path}{message}" + + def get_failure_message(rep, header, message): + location = rep.location + path = f"{location[0]}:{location[1]}" + cause = message.splitlines() + cause = " ".join( + [ + each[2:].strip() if each.startswith("E ") else each.strip() + for each in cause + ] + ) + + return f"{header} {rep.head_line} - {path}: {cause}" + + def get_skip_message(rep): + message = rep.longrepr[2] + header = markup("[SKIPPED]", **SKIPPED_COLOR) + return get_normal_message(rep, header, message) + + def get_passed_message(rep): + message = rep.longreprtext + header = markup("[PASSED]", **PASSED_COLOR) + return get_normal_message(rep, header, message) + + def get_xfailed_message(rep): + message = " ".join(rep.longrepr.reprcrash.message.split(":")[1:]).strip() + header = markup("[XFAILED]", **XFAILED_COLOR) + return get_normal_message(rep, header, message) + + def get_xpassed_message(rep): + message = rep.longreprtext + header = markup("[XPASSED]", **XPASSED_COLOR) + return get_normal_message(rep, header, message) + + def get_error_message(rep): + message = rep.longrepr.reprcrash.message + header = markup("[ERROR]", **ERROR_COLOR) + return get_failure_message(rep, header, message) + + def get_failed_message(rep): + message = rep.longrepr.reprcrash.message + header = markup("[FAILED]", **FAILED_COLOR) + return get_failure_message(rep, header, message) failed = self.stats.get("failed", []) for rep in failed: - self.write_line( - f"[FAILED] {rep.head_line} - {rep.longreprtext.splitlines()[-3]}" - ) + self.write_line(get_failed_message(rep)) + + skipped = self.stats.get("skipped", []) + for rep in skipped: + self.write_line(get_skip_message(rep)) errored = self.stats.get("error", []) for rep in errored: - self.write_line( - f"[ERROR] {rep.head_line} - {rep.longreprtext.splitlines()[-3]}" - ) + self.write_line(get_error_message(rep)) + + passed = self.stats.get("passed", []) + for rep in passed: + self.write_line(get_passed_message(rep)) + + xpassed = self.stats.get("xpassed", []) + for rep in xpassed: + self.write_line(get_xpassed_message(rep)) + + xfailed = self.stats.get("xfailed", []) + for rep in xfailed: + self.write_line(get_xfailed_message(rep)) @pytest.hookimpl(trylast=True) def pytest_configure(config): vanilla_reporter = config.pluginmanager.getplugin("terminalreporter") my_reporter = MyReporter(config) + my_reporter._tw.fullwidth = 160 config.pluginmanager.unregister(vanilla_reporter) config.pluginmanager.register(my_reporter, "terminalreporter") diff --git a/tests/test_krylov.py b/tests/test_krylov.py index 9a3c83c456..898d7a2144 100644 --- a/tests/test_krylov.py +++ b/tests/test_krylov.py @@ -31,7 +31,10 @@ if not has_dependency("ansys-math-core"): # Needs ansys-math-core - pytest.skip(allow_module_level=True) + pytest.skip( + allow_module_level=True, + reason="Skipping because 'ansys-math-core' is not installed", + ) PATH = os.path.dirname(os.path.abspath(__file__)) diff --git a/tests/test_launcher_remote.py b/tests/test_launcher_remote.py index fa5e937085..1b7e2d10ee 100644 --- a/tests/test_launcher_remote.py +++ b/tests/test_launcher_remote.py @@ -26,7 +26,10 @@ from conftest import has_dependency if not has_dependency("ansys-platform-instancemanagement"): - pytest.skip(allow_module_level=True) + pytest.skip( + allow_module_level=True, + reason="Skipping because 'ansys-platform-instancemanagement' is not installed", + ) from unittest.mock import create_autospec diff --git a/tests/test_plotting.py b/tests/test_plotting.py index f597f7e8e8..f20778f048 100644 --- a/tests/test_plotting.py +++ b/tests/test_plotting.py @@ -30,7 +30,9 @@ from conftest import has_dependency, requires if not has_dependency("pyvista"): - pytest.skip(allow_module_level=True) + pytest.skip( + allow_module_level=True, reason="Skipping because 'pyvista' is not installed" + ) from ansys.mapdl.core.errors import ComponentDoesNotExits, MapdlRuntimeError from ansys.mapdl.core.plotting import GraphicsBackend diff --git a/tests/test_pool.py b/tests/test_pool.py index 7f8b5a1042..7799cf3e55 100644 --- a/tests/test_pool.py +++ b/tests/test_pool.py @@ -51,7 +51,9 @@ # skipping if ON_STUDENT and ON_LOCAL because we cannot spawn that many instances. if ON_STUDENT: - pytest.skip(allow_module_level=True) + pytest.skip( + allow_module_level=True, reason="Skipping Pool tests on student version." + ) skip_if_ignore_pool = pytest.mark.skipif( diff --git a/tests/test_theme.py b/tests/test_theme.py index 25073c34ee..06b646d91a 100644 --- a/tests/test_theme.py +++ b/tests/test_theme.py @@ -25,7 +25,9 @@ from conftest import has_dependency if not has_dependency("pyvista"): - pytest.skip(allow_module_level=True) + pytest.skip( + allow_module_level=True, reason="Skipping because 'pyvista' is not installed" + ) import matplotlib import numpy as np