An expected failure still runs the test.
Keep expected defects, skipped cases and unexpected passes distinct in the report.


A team knows a narrow test currently fails. Someone skips it to keep the run quiet. The test body stops running, so the report cannot show whether that defect remains reproducible. Playwright offers a different annotation for a test that is expected to fail: the test runs, and a pass becomes an unexpected result.
The annotations guide distinguishes skip(), fail() and fixme(). A skipped test does not run. An expected-failure test runs and is expected to fail. The guide describes fixme for a case that should not run because doing so is slow or crashes. Pick the annotation from the case's meaning and operational limits.
Keep the specimen deliberately narrow
Our invented example compares two fixed strings. The mismatch is intentional. It represents an expected failing assertion without a real product defect, browser action or account. A separate specimen makes the strings equal and keeps the expected-failure annotation, producing an unexpected pass and a nonzero runner result.
import { test, expect } from '@playwright/test';
test('controlled expected mismatch', async () => {
test.fail(true, 'Invented mismatch for annotation demonstration');
expect('actual demo value').toBe('expected demo value');
});Run this through the Playwright test runner. It is not ordinary JavaScript executed without a runner. The report should retain the assertion failure and expected status. A successful runner exit in this specimen does not mean the two strings matched; it means the observed failure matched the declared expectation.
Review the failure that actually occurred
The annotation alone does not pin the failure to a specific assertion. If setup fails first, the expected failing status can still be met without reaching the intended defect check. Keep setup simple, inspect the error and record which assertion executed. Unexpected authentication or environment errors should not be dismissed as the known defect.
For a real issue, preserve the expected behavior in the assertion and include a reviewable issue reference and owner. Do not rewrite the assertion to accept the faulty behavior just because the test is currently marked as failing. Avoid invented issue links; this demonstration uses an explanatory description only.
Scope a conditional annotation to the affected configuration. If the defect exists only on one supported browser, an unconditional fail annotation can misclassify the others. The condition and expected status belong in the review alongside the test's inputs, not hidden in a distant helper.
Treat an unexpected pass as a review signal
A pass may indicate that the defect was fixed, the tested path changed or the assertion became weaker. Inspect it before removing the annotation. Preserve ordinary passing coverage once the expected behavior is verified, rather than leaving a permanent exception in the suite.
Our local runner checks three distinct outcomes: the intended mismatch runs as an expected failure; the equal-string variant runs and is reported as an unexpected pass; a skipped variant does not execute its body. These outcomes verify annotation mechanics, not a product's release readiness.
A test that is unsafe or too costly to execute needs a separate decision about whether to run at all. Expected failure is not permission to repeat destructive actions, incur charges or use production data. State the skipped coverage and the reason it remains unverified.
AnyTest describes end-to-end tests prepared for human review. Review exception annotations with the same care as assertions and setup. No specific AnyTest defect-tracking or expected-failure integration is claimed. Keep the issue owner and next review attached to any real exception.
Common questions
Does test.fail skip the body?
No. It runs the test and expects failure.
Does an expected failure prove the intended defect was reached?
No. Inspect the actual error and assertion reached.