Run and Debug

Run a TestCase locally, read what it produced, and work through a failure — locator, timeout, or otherwise.

← Back to overview · 🇩🇪 Deutsch · ← Compose your TestCase · Persistent Debug Session →


Run a single TestCase

All commands on this page run from inside pm/ (see Quickstart — Step 5):

npx playwright test 3_Cases/TC_YourTest.spec.ts

Add --grep "<pattern>" to filter by test title, or --repeat-each 3 to run the same TestCase multiple times while chasing a flaky failure. Omit the path entirely to run every TestCase under testDir; add --last-failed to only re-run the ones that failed last time.


Run only one browser / project

npx playwright test 3_Cases/TC_YourTest.spec.ts --project=chromium

--project matches a name from your playwright.config.ts’s projects array — useful once your project also runs firefox/webkit, or a Desktop project alongside Web, and you only want to reproduce a failure on one of them.


Run in headed mode to watch the test

npx playwright test 3_Cases/TC_YourTest.spec.ts --headed

--headed overrides both your playwright.config.ts’s use.headless and a Web AUT’s headless field in GlobalConfig.apps (see Add a New App) for this run only — nothing to edit back afterwards.


Choose a run mode: fail fast, or keep going past a failed check (CC_RUN_MODE)

By default, a TestCase aborts at the very first failed step — failfast, unchanged, no setup needed.

Set failsafe to keep a TestCase running past a failed assertion — a Core.expect(...)/Check.* content check that found the element but the content or state didn’t match — instead of aborting immediately. The failed check is still logged ([FAIL] TS_x: ..., same line you already see today) and the overall run still ends with status failed; only the remaining, independent steps in the same TestCase get a chance to run too, instead of being reported as Unexecuted. Anything that is NOT a content mismatch — an element that can’t be found, a timeout, or any other execution error — still aborts the TestCase immediately, in either mode; only assertion failures are ever soft.

CC_RUN_MODE=failsafe npx playwright test 3_Cases/TC_YourTest.spec.ts

Persist a default across shells/sessions instead of setting the environment variable every time, following the same priority chain as every other framework toggle (see Self-Healing — Persisting the setup across sessions): the environment variable, when set, always wins over the persisted config file, which wins over the default (failfast).

npx cc-testframework set-run-mode failsafe   # persist the default for this project
npx cc-testframework set-run-mode            # show the resolved value + where it came from (env|config|default)
npx cc-testframework set-run-mode failfast   # back to the default (first failure aborts)

Read the HTML report

The framework’s baseConfig keeps Playwright’s default ['html'] reporter (see API Reference — baseConfig), so every run writes a report to pm/playwright-report/. Open it with:

npx playwright show-report

baseConfig also turns on screenshot: 'on' and video: 'on' for every test (not just failures) and trace: 'on-first-retry' — so a failing step almost always has a screenshot and video attached in the report, plus a full Playwright trace once a retry has happened. Open the trace via the report’s “Trace” tab, or directly with npx playwright show-trace <path-to-trace.zip>, to step through the exact DOM/network state at the moment of failure.


Debug a failing locator

A locator that finds nothing throws a message like this once its search window expires:

search timeout reached. (timeout:20s / timetaken:20.0s). No child element was found by the given locators [...]

Three ways forward, roughly in order of effort:

  1. Fix the Control by hand — the UI likely changed shape; see Add Controls for locator style and where the file lives.
  2. Let Self-Healing repair it automatically — bind a reference screenshot once, and a future run can heal a broken locator on its own; see Self-Healing Locators for setup.
  3. Have the Authoring Agent write a fix for younpx cc-testframework author --test 3_Cases/TC_YourTest.spec.ts re-runs the failing TestCase and dispatches a fix for classes of failure it recognizes; see Custom Steps — Running the agent from the command line.

Debug a hanging test

A test that never finishes usually falls into one of these buckets:

  • The App never became reachable. Playwright’s own navigation timeout fires (page.goto: Timeout ... exceeded) — see Add a New App — Verify your App is reachable for the common causes.
  • A Core.expect(...) assertion keeps retrying. Core.expect is Playwright’s own expect — web-first matchers like .toBeVisible() auto-retry until they pass or Playwright’s test timeout elapses, rather than failing on the first check. A long-hanging assertion here is usually retrying against an element that will never appear, not a framework bug:
// Retries internally for up to the test timeout — not an immediate pass/fail
await Core.expect(page.getByText('Success')).toBeVisible();
  • A blocking dialog or overlay. A native browser dialog (alert/confirm) or an app-level modal that Playwright can’t dismiss on its own stalls every subsequent locator search until something handles it — check whether a TS_Dialog_*/TS_Message_* step is missing from the flow (see Build TestSteps).

Core.Constant.searchTimeout (20 seconds by default) bounds how long a single Core.findLocators call waits before giving up — raise or lower it per call via a Control’s own searchTimeout parameter rather than globally, if one specific screen is unusually slow.


Iterate faster with the Inspector

await Core.Inspector.pause();

Drop this line into a TestStep or TestCase body and the running test pauses, spawns the Inspector Web UI (npm install @meintest/cc-testframework-inspector-ui inside pm/ if it’s not installed yet), and opens it in your system browser against the live App state — inspect the current DOM, try locators, and capture a reference screenshot for Self-Healing, then click “Resume Test” to continue exactly where you left off. A dedicated deep-dive page is planned; this is the short version to unblock you today.

Pass options when the default auto-detection needs a hint — e.g. more than one App registered and none currently bound, or a hard ceiling on how long the pause may block a CI job:

await Core.Inspector.pause({ appId: 'YourApp', timeoutMs: 120_000 });

Common error patterns and their fixes

Error Likely cause Fix
defineExecutionStep: unknown appName 'YourApp' Typo, or missing GlobalConfig.apps entry See Add a New App
search timeout reached ... No child element was found Locator no longer matches the current UI See Debug a failing locator above
page.goto: Timeout ... exceeded App unreachable from the test machine See Add a New App
browser executable not found Playwright browsers not installed npx playwright install — see FAQ
Custom Step throws not yet automated An @custom-tagged step has no implementation yet See Custom Steps
Test passes locally, fails in CI only Missing env-var/credential, or a CI-only timing difference Check SELF_HEALING_WRITEBACK and an AI API key (AI_API_KEY, set-ai-key, or ANTHROPIC_API_KEY) are set if the run depends on them; see Self-Healing — Cost and BYOK and Credential Management

Where to go next

  • Persistent Debug Session — leave the AUT open between runs while you iterate on a failing TestCase
  • CI Integration — run the same TestCase in a pipeline, with CC_RUN_MODE and the rest set as CI secrets
  • Self-Healing Locators — stop fixing the same locator by hand every time the UI changes
  • Custom Steps — write (or generate) an implementation for a step that isn’t automated yet
  • Add Controls — extend or fix a Control directly
  • FAQ — troubleshooting for setup issues that show up before a test even runs

📧 Questions? Contact: jens.szelag@itsbusiness.ch

itsbusiness AG · Bern · Switzerland