Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use expect.soft() when you need later checks in the same test to run. The assertion is still recorded as a test failure, but Playwright continues executing the test body. If you mean “run the tests that follow a failed test,” keep those tests independent, avoid serial groups and fail-fast mode, and understand how retries and worker restarts affect the run.

First decide what “continue” means

Playwright has three different behaviors that are often described as “continue after failure.” Choose the one that matches your goal:

Goal Use What happens
Run more assertions in the current test await expect.soft(...) The test body continues, but the test is reported as failed if a soft assertion fails.
Run later test cases after one case fails Default mode or an appropriate parallel mode Playwright replaces the failed worker and can run subsequent independent tests.
Attempt the failed test again retries or --retries The failed test is rerun; this is not a general continue-on-error switch.

A normal assertion such as await expect(locator).toHaveText(...) stops the current test when it ultimately fails. Playwright’s web-first assertions still retry the condition until it passes or its timeout expires; soft assertions change what happens after that failure, not whether the matcher retries.

Continue inside the same test with soft assertions

Basic TypeScript example

import { test, expect } from '@playwright/test';

test('checkout summary', async ({ page }) => {
  await expect.soft(page.getByTestId('status')).toHaveText('Success');
  await expect.soft(page.getByTestId('eta')).toHaveText('1 day');

  // This action runs even if either check failed.
  await page.getByRole('link', { name: 'next page' }).click();
});

Each failed soft assertion is added to the test’s error collection. Playwright reports the test as failed at the end, so this pattern gives you multiple diagnostics without pretending that an incorrect result is acceptable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Guard actions whose preconditions failed

Continuing blindly can make a failure harder to understand. If a later action is safe only when the earlier check passed, inspect the accumulated errors and return before doing unsafe work:

import { test, expect } from '@playwright/test';

test('order details', async ({ page }) => {
  await expect.soft(page.getByTestId('order-state')).toHaveText('Paid');

  if (test.info().errors.length > 0) {
    return;
  }

  await page.getByRole('button', { name: 'Download invoice' }).click();
});

Use ordinary assertions when a failed precondition means the rest of the test cannot be trusted. Use soft assertions for independent checks—for example, validating several labels, totals and links on the same stable page.

Soft assertions and retries are different

  • Soft assertion: keeps the current test body moving after an assertion failure.
  • Retry: starts the failed test again in a fresh attempt.
  • Web-first assertion: repeatedly checks a condition until it passes or times out.

Combining them is possible, but deliberate: a test with soft failures is still a failed test and can be retried according to your configuration.

Run later tests after one test fails

Default mode and worker replacement

In ordinary Playwright Test execution, tests in a file run in order, while files can run in parallel. After a test failure, Playwright shuts down that worker to guarantee a pristine environment for following tests, then continues with a replacement worker when retries are not enabled. A worker restart is therefore not the same as aborting the entire run.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep tests isolated: each test should create or seed the state it needs rather than depending on in-memory variables or side effects from a preceding test.

Do not put independent tests in a serial group

import { test } from '@playwright/test';

test.describe.configure({ mode: 'serial' });

test('creates a project', async ({ page }) => {
  // ...
});

test('edits the project', async ({ page }) => {
  // ...
});

In serial mode, if one test fails, subsequent tests in that group are skipped. Retries rerun the serial group together. Serial mode is appropriate only when tests genuinely share an ordered dependency; it is the wrong setting when your requirement is to keep unrelated checks running.

Parallel execution requires independence

fullyParallel: true allows tests across files to run in parallel, and workers sets the maximum number of worker processes. A parallel test runs in its own worker, so shared mutable data, a single account, or order-dependent server state can create new failures. Parallelism can reduce wall-clock time for independent tests, but it does not turn a dependent test chain into a safe one.

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  fullyParallel: true,
  workers: process.env.CI ? 2 : undefined,
  retries: process.env.CI ? 1 : 0,
});

Do not treat workers: 1 as a continue-on-failure option. It limits concurrency; failure behavior is controlled by test isolation, execution mode, retries and fail-fast settings.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check for fail-fast settings

The command-line option -x stops the run after the first failure. Remove it when later tests must execute:

npx playwright test

Use fail-fast intentionally for a quick smoke check, not for a diagnostic run in which you need a complete failure list. Also check scripts in package.json and CI configuration; a wrapper may be adding -x even when your local command does not show it.

Retry a failed test without confusing it with continuation

Configure retries

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  retries: 2,
});

Or set the maximum number of additional attempts for one run:

npx playwright test --retries=3

The documented default is zero. A test that fails initially and passes on a retry is classified as flaky. Retries add runtime and can conceal a persistent defect, so use them to investigate intermittent failures while still fixing the underlying cause. There is no universally correct retry count.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What happens with a retry

After failure, the worker is replaced. With retries enabled, the replacement worker retries the failed test before proceeding. In a serial group, the group is rerun together, which can multiply runtime and repeat setup or side effects.

Reliable patterns for “continue” behavior

Independent page checks

test('account page content', async ({ page }) => {
  await page.goto('/account');

  await expect.soft(page.getByRole('heading', { name: 'Account' })).toBeVisible();
  await expect.soft(page.getByTestId('plan')).toHaveText('Pro');
  await expect.soft(page.getByRole('link', { name: 'Billing' })).toBeVisible();
});

These checks examine the same page and do not require one assertion to make the next assertion safe.

Dependent workflow

test('publish article', async ({ page }) => {
  await page.goto('/editor');
  await page.getByLabel('Title').fill('Release notes');
  await page.getByRole('button', { name: 'Save draft' }).click();

  await expect(page.getByRole('status')).toHaveText('Draft saved');
  await page.getByRole('button', { name: 'Publish' }).click();
});

Here a normal assertion is preferable: publishing after a failed save would test an invalid state and produce misleading evidence.

Troubleshooting continuation problems

“The next assertion never ran”

  • Replace the first assertion with expect.soft if the checks are independent.
  • Look for a thrown error, failed navigation, timeout or actionability failure; soft assertions do not make arbitrary exceptions disappear.
  • Check whether your code returned early after inspecting test.info().errors.

“Tests after the failure are skipped”

  • Remove -x from the command or CI script.
  • Check for test.describe.configure({ mode: 'serial' }) or a serial project.
  • Confirm that a global setup, fixture or external test runner is not aborting the process.

“Retries made the suite much slower”

  • Set retries only where intermittent failures are plausible, commonly in CI rather than local development.
  • Inspect trace, video, screenshot and error output instead of increasing the count indefinitely.
  • Remember that serial groups rerun as a unit.

“Parallel tests interfere with one another”

Give each test unique records or accounts, reset server state through fixtures or APIs, and avoid sharing process-local variables. Reduce workers temporarily to diagnose a race, but fix the shared-state design rather than relying permanently on one worker.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is to capture a page for a test artifact, visual review or CI report rather than exercise the page interactively, ScreenshotNeo can return a screenshot or PDF through one request. Its cleanup steps accept cookie-consent banners and remove more than 60 known consent platforms, newsletter popups and chat widgets before capture; each step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. It also offers an MCP server for Claude, Cursor and other MCP clients with take_screenshot, get_page_info and capture_pdf.

Use the ScreenshotNeo API documentation for the available options:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan. Sign up free for ScreenshotNeo.

FAQ

Does a soft assertion make the test pass?

No. A soft assertion allows execution to continue, but its failure remains recorded and the test is reported as failed.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Will Playwright always run the next test after a failure?

Not if the tests are in a serial group or the run uses -x. Independent tests in the normal runner flow can continue after Playwright replaces the failed worker.

Should I use retries to ignore a known failure?

No. Retries are for detecting intermittent failures and labeling tests that pass on a later attempt; they do not replace fixing a deterministic defect.

Frequently Asked Questions

Can I continue after a failed click or navigation, not just an assertion?

No setting guarantees that. A click, navigation or fixture exception can leave the page or fixture unusable. Catch only errors you can safely handle, then explicitly verify the state before continuing.

Does setting workers to one prevent the suite from stopping?

No. It changes concurrency, not fail-fast, serial-group or retry behavior.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.