Test Status
Playwright and Cypress Test Status - detailed guide and explanation
Playwright and Cypress test status is mostly straightforward to interpret, however, there are a few confusing concepts that can be tricky to figure out.
Playwright Test Status
Playwright test status is a composition of:
the status of its attempts
its expected status
The final status is determined after a test has finished all its retries, test.afterEach() hook and fixtures and depends on the expected status and the status of all the retries.
See Playwright Test Status - Summary Table for reference of how Playwright statuses appear in Currents.
Playwright Test Attempt Status
Each test attempt can be in one of the following statuses:
passed - means that the test attempt didn't encounter any error or exception while executing the test body or the associated
test.beforeEach
ortest.afterEach
hooksfailed - means that the test attempt failed due to an assertion error, exception in the test's body or the associated
test.beforeEach
ortest.afterEach
hooks. An exception or failure oftest.beforeAll
hooks will cause afailed
status in the first test attempt according to the execution order.interrupted - means that the execution of a test attempt was halted before it could be completed. This interruption could occur due to a variety of reasons, such as:
Uncaught Exception.
Unhandled Rejection.
Interrupted by a system signal like SIGINT (CTRL / CMD + C).
maxFailures limit reached (the rest of the tests get stats interrupted).
timedOut - indicates that the test attempt did not finish within a specified time limit, leading to its automatic termination. Each test's timeout depends on testConfig.timeout, testProject.timeout, test.setTimeout(), test.slow() and testInfo.setTimeout().
skipped - indicates that the test retry was not executed. This can happen for several reasons:
If you programmatically skip tests based on certain conditions.
If you explicitly skip a test with test.skip() or test.fixme().
If you're using a feature like
.only
to focus on specific test.If a previous test in a test group failed or timed out (see below).
Playwright Expected Status
Playwright tests have expected status, you can set the expected status as follows:
Tests marked as test.skip() or test.fixme() are expected to be
skipped
.Tests marked as test. fail() are expected to be
failed
.Other tests are expected to be
passed
.
Playwright Test Outcome
Combining the expected status with test retries status defines Playwright test outcome:
skipped
- means all the attempts were skipped (because the test was marked as test.skip() or test.fixme())expected
- means all the attempts' status matches theexpectedStatus
a test has
expectedStatus=failed
all attempts werefailed
(but nottimedOut
)a test has
expectedStatus=passed
and all attempts have a statuspassed
unexpected
- all attempts' status does not match theexpectedStatus
flaky
- some attempts' status matches the expected status, and some do not. See below.
Playwright Flaky Tests
Playwright marks a test as flaky if some attempts match the expected status and some don't. For example:
there are multiple test attempts and
there is at least one
passed
attempt andthere's at least one
failed
ortimedOut
attempt
It can be tricky to interpret the result depending on the expected status. For example, all the tests below will be considered flaky:
import { expect, test } from "@playwright/test";
const wait = (ms: number) => new Promise((r) => setTimeout(r, ms));
test.describe.configure({ timeout: 500 });
test("expectedStatus=passed; failed, passed", async ({ page }, { retry }) => {
if (retry === 0) {
throw new Error("oh!");
}
expect(true).toBe(true);
});
test("expectedStatus=failed; timedOut, passed", async ({ page }, { retry }) => {
if (retry === 0) {
await wait(1000);
}
expect(true).toBe(true);
});
test("expectedStatus=failed; passed, failed", async ({ page }, { retry }) => {
test.fail();
if (retry === 0) {
expect(true).toBe(true);
}
if (retry === 1) {
expect(true).toBe(false);
}
});
test("expectedStatus=failed; timedOut, failed", async ({ page }, { retry }) => {
test.fail();
if (retry === 0) {
await wait(1000);
}
if (retry === 1) {
expect(true).toBe(false);
}
});
See Flaky Testsfor more details about learning how to use Currents Dashboard when dealing with flaky tests.
Serial Mode and Playwright Test Status
Enabling Serial Mode for Playwright Tests changes the default behaviour: a group of tests designated to run serially always run together, one after another. A failure or a timeout in a test causes all the subsequent tests in the group to become skipped
. Depending on the number of retries left, all the tests will run again until completion.
Use test.describe.serial() to group dependent tests to ensure they will always run together and in order. If one of the tests fails, all subsequent tests are skipped. All tests in the group are retried together.
Determining test status for serial tests follows the same principles as for other tests, however, you should be aware of that behaviour and interpret the results accordingly.
Console Output
The Playwright Console Output has a precise and accurate presentation of the execution workflow.
Each attempt has its start and end timestamps, status details, detected errors, stdout and stderr output.
Clear separation between tests flakiness and outcome status - determining a test's "status" and flakiness requires considering the outcome of all the attempts, the expected status and the execution mode (e.g. "serial" mode can generate extra attempts).

Moreover, inline links to individual test results is part of console output:

Playwright Test Status - Summary Table
Refer to the table below to determine how a certain combination of expectedStatus
and outcome
affects the status reported to Currents Dashboard.
failed
passed
unexpected
failed
failed
timedOut
unexpected
failed
failed
failed
expected
passed
passed
passed
expected
passed
passed
timedOut
unexpected
failed
passed
failed
unexpected
failed
skipped
skipped
expected
ignored
Last updated
Was this helpful?