All challenges · Expert & Verification

Challenge 28 of 29 · Expert authoring · Verification

Debug the Broken Test (Full Authoring)

You get a broken test with several bugs. Find and fix them, then write the assertions yourself: this is one of two challenges where you author the checks.

Skills you will practise

  • debugging
  • full test authoring
  • writing assertions

The concept

Most real automation work is not writing new tests; it is fixing ones that fail, flake or pass for the wrong reason. Debugging is a skill, and it follows a pattern: read the error, reproduce the failure, find the first wrong assumption, fix it, then make sure the test can actually fail.

Common culprits in broken Playwright tests are a missing await, a selector tied to markup that changed, a strict-mode violation, a fixed sleep that is too short in CI, a listener registered too late, and assertions that do not retry. Tools help: the HTML report, trace viewer, --debug mode, page.pause() and video of the run.

In this challenge you also write the assertions. A test without good assertions is not a test; it is a script that clicks things.

The fragile version

Fragile
test('adds to basket', async ({ page }) => {
  page.goto('/shop');
  await page.locator('div > button:nth-child(3)').click();
  await page.waitForTimeout(1000);
  expect(await page.locator('.count').textContent()).toBe('1');
});

Why it breaks: A missing await on goto, a positional selector, a fixed sleep and a non-retrying read: four bugs that may pass locally and fail in CI.

A robust Playwright version

Robust
test('adds to basket', async ({ page }) => {
  await page.goto('/shop');
  await page.getByRole('listitem')
    .filter({ hasText: 'Mechanical keyboard' })
    .getByRole('button', { name: 'Add to basket' })
    .click();
  await expect(page.getByRole('status', { name: 'Basket' })).toHaveText('1');
});

Every step is awaited, the locator describes the product and button, and the assertion retries.

This is a general example on a made-up page, not the challenge’s reference solution.

Common mistakes

  • Fixing the symptom (raising a timeout) instead of the cause.
  • Not checking the test fails when it should, for example by breaking the expected value temporarily.
  • Fixing one bug and stopping; broken tests rarely have just one.

FAQ

How do I debug a Playwright test?

Run with --debug or --ui, add page.pause(), and open the trace viewer for failed runs.

Why does my test pass locally but fail in CI?

Usually timing: fixed sleeps, missing awaits or non-retrying checks. CI machines are slower.

What makes a good assertion?

It checks the user-visible outcome, retries (web-first), and would fail if the feature broke.

Try it

Practise this in Challenge 28. You write the code in the browser editor with no setup. It runs in a fresh Chromium, a hidden validator checks what actually happened, and you get pass or fail, the logs and a video of the run. Create a free account to open the practice page and its hints. The reference solution and the hidden validator are shown only after you pass. We never publish solutions here.

Practise this challenge free