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:
- Fix the Control by hand — the UI likely changed shape; see Add Controls for locator style and where the file lives.
- 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.
- Have the Authoring Agent write a fix for you —
npx cc-testframework author --test 3_Cases/TC_YourTest.spec.tsre-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.expectis Playwright’s ownexpect— 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 aTS_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_MODEand 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