diff --git a/locust/html.py b/locust/html.py index 34ecfcd3bf..49f4ebb97e 100644 --- a/locust/html.py +++ b/locust/html.py @@ -35,10 +35,9 @@ def get_html_report(environment, show_download_link=True): requests_statistics = list(chain(sort_stats(stats.entries), [stats.total])) failures_statistics = sort_stats(stats.errors) - exceptions_statistics = [] - for exc in environment.runner.exceptions.values(): - exc["nodes"] = ", ".join(exc["nodes"]) - exceptions_statistics.append(exc) + exceptions_statistics = [ + {**exc, "nodes": ", ".join(exc["nodes"])} for exc in environment.runner.exceptions.values() + ] history = stats.history diff --git a/locust/test/test_web.py b/locust/test/test_web.py index b6c522c8bc..f7d7cf20d2 100644 --- a/locust/test/test_web.py +++ b/locust/test/test_web.py @@ -356,6 +356,14 @@ def test_report_exceptions(self): # self.assertEqual(200, r.status_code) self.assertIn("

Exceptions Statistics

", r.text) + # Prior to 088a98bf8ff4035a0de3becc8cd4e887d618af53, the "nodes" field for each exception in + # "self.runner.exceptions" was accidentally mutated in "get_html_report" to a string. + # This assertion reproduces the issue and it is left there to make sure there's no + # regression in the future. + self.assertTrue( + isinstance(next(iter(self.runner.exceptions.values()))["nodes"], set), "exception object has been mutated" + ) + class TestWebUIAuth(LocustTestCase): def setUp(self):