feat: add per-step duration to JUnit XML system-out#332
Conversation
There was a problem hiding this comment.
Pull request overview
Adds per-step wall-clock duration (ms) to each step line emitted in the JUnit XML <system-out> block, leveraging timing already tracked in Query.
Changes:
- Extend step formatting to append
(<duration> ms)after the step status in JUnit XML system-out output. - Plumb test-step duration from
Query::FindTestStepDurationByTestStepId()into the step formatter.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const auto durationMs = util::DurationToMilliseconds(query.FindTestStepDurationByTestStepId(testStepFinished->test_step_id)); | ||
| return FormatStep(gherkinStep, pickleStep, testStepFinished->test_step_result.status, durationMs); |
There was a problem hiding this comment.
MakeOutput() now calls Query::FindTestStepDurationByTestStepId() unconditionally. That query method uses .at() on testStepStartedByTestStepId/testStepFinishedByTestStepId and will throw std::out_of_range if a test_step_started event was never recorded (e.g., for SKIPPED / UNDEFINED / AMBIGUOUS steps). Consider guarding duration lookup based on status (similar to UsageFormatter's HasExecuted()), or falling back to 0 ms / n/a when the duration can’t be computed, to avoid formatter crashes when generating JUnit XML.
| std::string FormatStep(const cucumber::messages::step& gherkinStep, const cucumber::messages::pickle_step& pickleStep, cucumber::messages::test_step_result_status status, std::chrono::milliseconds duration) | ||
| { |
There was a problem hiding this comment.
This file now names std::chrono::milliseconds in the FormatStep signature, but it doesn’t include <chrono> directly (it currently relies on transitive inclusion via util/Duration.hpp). Consider adding an explicit #include <chrono> here to follow include hygiene / IWYU and avoid brittle builds if headers change.
Summary
Currently the JUnit XML output records timing at the scenario level () but the block only shows step name and status, with no indication of how long each step took.
This change adds the wall-clock duration in milliseconds to each step line in .
Before
Then the system starts the application within "3" seconds...................failed
After
Then the system starts the application within "3" seconds...................failed (3001 ms)
Details
The duration is recorded independently of pass/fail status — on a failure the value reflects the actual measured time until the step threw (e.g. an RPP timeout), which is the real observed latency. This makes it possible to harvest performance data (e.g. app start time) from the XML artifact in CI without any changes to step implementations.
The timing data is already tracked by Query::FindTestStepDurationByTestStepId — this change simply surfaces it in the formatter output.