Skip to content

feat: add per-step duration to JUnit XML system-out#332

Closed
Willem-Jan Spoel (willemjanspoelphilips) wants to merge 1 commit into
philips-software:mainfrom
willemjanspoelphilips:feat/add-step-timing-to-junit-xml
Closed

feat: add per-step duration to JUnit XML system-out#332
Willem-Jan Spoel (willemjanspoelphilips) wants to merge 1 commit into
philips-software:mainfrom
willemjanspoelphilips:feat/add-step-timing-to-junit-xml

Conversation

@willemjanspoelphilips
Copy link
Copy Markdown

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +108 to +109
const auto durationMs = util::DurationToMilliseconds(query.FindTestStepDurationByTestStepId(testStepFinished->test_step_id));
return FormatStep(gherkinStep, pickleStep, testStepFinished->test_step_result.status, durationMs);
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to 84
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)
{
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants