Review: Adopting assertEqualHTML() in WordPress Tests (Migration Patterns)
· 3 min read
The Hook
WordPress 6.9 added assertEqualHTML(), which removes a lot of brittle test failures caused by formatting-only HTML differences.
Why I Built It In plugin and theme suites, many HTML tests still use strict string equality and fail on whitespace, indentation, or equivalent tag formatting instead of real behavior regressions.
The Solution
Adopt assertEqualHTML() for semantic HTML equivalence checks, keep assertSame() where byte-for-byte output matters, and phase migration by risk and signal quality.
The Code No standalone project repo for this task. This is migration guidance for WordPress/PHPUnit test suites.
Recommendation
- Adopt now if your suite has frequent brittle failures from HTML formatting differences.
- Use it for rendered markup assertions where DOM meaning matters more than exact serialization.
- Do not replace assertions that intentionally verify exact escaping, spacing, or deterministic serialization.
Concrete Migration Patterns
1) Direct string comparison to semantic HTML comparison
Before:
$this->assertSame(
'<p class="notice">Saved</p>',
$actual_html
);
After:
$this->assertEqualHTML(
'<p class="notice">Saved</p>',
$actual_html
);
2) Remove ad-hoc whitespace normalization
Before:
$normalize = static fn( $html ) => preg_replace( '/\s+/', ' ', trim( $html ) );
$this->assertSame( $normalize( $expected ), $normalize( $actual ) );
After:
$this->assertEqualHTML( $expected, $actual );
3) Output-buffer render tests
Before:
ob_start();
render_banner_block( array( 'message' => 'Hi' ) );
$actual = ob_get_clean();
$this->assertSame(
'<section class="banner"><p>Hi</p></section>',
$actual
);
After:
ob_start();
render_banner_block( array( 'message' => 'Hi' ) );
$actual = ob_get_clean();
$this->assertEqualHTML(
'<section class="banner"><p>Hi</p></section>',
$actual
);
4) Attribute/order formatting noise
Before:
$expected = '<a class="btn primary" href="/docs">Docs</a>';
$actual = '<a href="/docs" class="btn primary">Docs</a>';
$this->assertSame( $expected, $actual );
After:
$this->assertEqualHTML( $expected, $actual );
5) Version-safe bridge for mixed core baselines
If your suite runs against WordPress versions older than 6.9:
private function assertHtmlEquivalent( string $expected, string $actual ): void {
if ( method_exists( $this, 'assertEqualHTML' ) ) {
$this->assertEqualHTML( $expected, $actual );
return;
}
$this->assertSame( trim( $expected ), trim( $actual ) );
}
Rollout Guidance
- Start with render-heavy tests (
render_callback, shortcode output, template helpers). - Convert only tests currently compensating for formatting differences.
- Keep
assertSame()for escaping/security assertions and exact output contracts. - Add a short team note: "Use
assertEqualHTML()for semantic markup checks."
What I Learned
assertEqualHTML()landed in WordPress core test tools in 6.9 and is intended to compare HTML equivalence, not raw string identity.- Most migration wins come from deleting custom normalization code and reducing flaky failures.
- A two-lane assertion policy (
assertEqualHTML()for semantics,assertSame()for exactness) keeps intent explicit and avoids over-migration.
