Skip to content

Build/Test Tools: Flag slow PHPUnit tests with annotations - #13212

Open
lancewillett wants to merge 1 commit into
WordPress:trunkfrom
lancewillett:feat/65887-flag-slow-phpunit-tests
Open

Build/Test Tools: Flag slow PHPUnit tests with annotations#13212
lancewillett wants to merge 1 commit into
WordPress:trunkfrom
lancewillett:feat/65887-flag-slow-phpunit-tests

Conversation

@lancewillett

Copy link
Copy Markdown
Member

Trac ticket: https://core.trac.wordpress.org/ticket/65887

What this changes

Adds a Flag slow PHPUnit tests step to the canonical PHP 8.5 report job. It parses the JUnit report and, for tests over a threshold (default 1s), emits GitHub Actions warning annotations and a run-summary table naming the slowest tests. Runs on pull requests and pushes to trunk.

This complements #13083: those six CodeVitals aggregates store the trend but cannot name a test. This one names the slow ones, so a PR author can spot a slow test they added.

Behavior

  • Advisory only: runs even on failed test runs (always()) and never fails the build (continue-on-error).
  • Inline annotations capped at 10 (GitHub's per-step limit); the summary table lists more.
  • Container-absolute paths normalized to repository-relative so annotations resolve.
  • A testcase without timing data (e.g. a skipped test) is ignored, not an error.

Use of AI Tools

AI assistance: Yes
Tool(s): Codex (via Claude Code), hardened with an adversarial multi-lens review
Used for: drafting the workflow step and PHP script, and reviewing it before submission.

Parse the JUnit report from the canonical PHP 8.5 report job and emit GitHub
Actions warning annotations plus a run-summary table for tests over a
threshold, on pull requests and pushes to trunk. Advisory only: the step runs
even on failed test runs and never fails the build itself.

This names the slow tests, complementing the aggregate CodeVitals trend that
stores them without naming any one test.

See #65887.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @lance.willett@a8c.com.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds CI tooling to surface individual slow PHPUnit tests during GitHub Actions runs by parsing the generated JUnit report and emitting GitHub Actions warning annotations plus a step-summary Markdown table, targeting the canonical PHP 8.5 reporting job context.

Changes:

  • Added a new PHP CLI script to parse junit.xml, identify tests exceeding a configurable threshold, and emit warning annotations and a run summary.
  • Integrated a new “Flag slow PHPUnit tests” step into the reusable PHPUnit workflow (gated to PHP 8.5 + reporting-enabled runs on PRs and trunk pushes).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/phpunit/prepare-slow-test-annotations.php New CLI parser that finds slow testcases in JUnit XML and outputs GitHub Actions annotations + a step summary table.
.github/workflows/reusable-phpunit-tests-v3.yml Adds a workflow step that runs the new parser after the main PHPUnit run under the intended conditions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +276 to +279
if: >-
always() && inputs.report && inputs.php == '8.5' &&
( github.event_name == 'pull_request' ||
( github.event_name == 'push' && github.ref == 'refs/heads/trunk' ) )

@adimoldovan adimoldovan left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

One PHPCS error fails the build. The rest are small.

Two points that map to no line in the diff:

  1. #13083 adds class-wp-phpunit-timing-metrics.php, which streams the same junit.xml at the same point in the same workflow. Once it lands, this script should reuse it rather than walk the file a second time.
  2. The job's # Performs the following steps: list (lines 110-129) omits this step. #13083 updates that list for its own step.

Comment on lines +112 to +113
"Usage: php tests/phpunit/prepare-slow-test-annotations.php <junit-file> "
. "[threshold-seconds] [max-annotations]\n"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This fails the build. The string holds no variable and no escape, so Squiz.Strings.DoubleQuoteUsage rejects the double quotes. Coding standards / PHP checks is the only red check on the PR.

Suggested change
"Usage: php tests/phpunit/prepare-slow-test-annotations.php <junit-file> "
. "[threshold-seconds] [max-annotations]\n"
'Usage: php tests/phpunit/prepare-slow-test-annotations.php <junit-file> '
. "[threshold-seconds] [max-annotations]\n"

}
);

$slow_tests = array_slice( $slow_tests, 0, $max_annotations );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The max-annotations argument caps the summary table, not the annotations, which line 214 caps separately at 10. The name says the opposite of what the value does. The table then stops at 20 rows with no marker, so it reads as complete when it is not.

Comment on lines +217 to +223
if ( '' !== $test['file'] ) {
$properties[] = 'file=' . wp_phpunit_escape_command_property( $test['file'] );
}

if ( '' !== $test['line'] ) {
$properties[] = 'line=' . wp_phpunit_escape_command_property( $test['line'] );
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

A testcase with line and no file emits ::warning line=60,..., which GitHub ignores. PHPUnit sets both together from reflection, so this branch never fires on a real report — tidying only.

Suggested change
if ( '' !== $test['file'] ) {
$properties[] = 'file=' . wp_phpunit_escape_command_property( $test['file'] );
}
if ( '' !== $test['line'] ) {
$properties[] = 'line=' . wp_phpunit_escape_command_property( $test['line'] );
}
if ( '' !== $test['file'] ) {
$properties[] = 'file=' . wp_phpunit_escape_command_property( $test['file'] );
if ( '' !== $test['line'] ) {
$properties[] = 'line=' . wp_phpunit_escape_command_property( $test['line'] );
}
}

# Runs even when the test step failed (always()), so the signal still
# surfaces on red runs, and never fails the job itself (continue-on-error),
# because this is advisory only.
if: >-

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

always() also runs the step on cancelled jobs, and phpunit-tests.yml sets cancel-in-progress: true, so PR runs are cancelled often. !cancelled() matches the intent.

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.

3 participants