|
| 1 | +# AI-native UI Testing Framework |
| 2 | + |
| 3 | +Midscene helps teams build UI tests around user intent instead of fragile selectors. Natural-language steps describe what a user wants to do, while scripts, setup code, CLI execution, and reports keep the workflow maintainable enough for real projects. |
| 4 | + |
| 5 | +This guide introduces the framework-level view. If you want to run your first test immediately, start with [Write UI tests with YAML](./ui-testing-yaml-quick-start). |
| 6 | + |
| 7 | +## Why UI testing needs a new shape |
| 8 | + |
| 9 | +Traditional UI testing frameworks such as Playwright and Puppeteer are stable and programmable, but they require teams to maintain selectors, waits, fixtures, browser contexts, device access, and report pipelines. AI-driven automation lowers the authoring cost by letting people write steps such as "open the first product" or "confirm the cart contains one item", but a prompt alone is not enough for production testing. |
| 10 | + |
| 11 | +Real UI tests still need: |
| 12 | + |
| 13 | +- login state, SSO, accounts, cookies, and environment setup; |
| 14 | +- deterministic checks for APIs, databases, analytics events, and business rules; |
| 15 | +- Web, Android, iOS, desktop, and other runtime environments; |
| 16 | +- command-line execution, CI integration, reports, screenshots, and debugging artifacts. |
| 17 | + |
| 18 | +Midscene's testing framework is the layer that connects those pieces. |
| 19 | + |
| 20 | +| Pain point | What it looks like | Midscene's approach | |
| 21 | +| --- | --- | --- | |
| 22 | +| Simple smoke tests require too much framework code | A business path needs fixtures, waits, selectors, and runner setup before it can run | Express the path in YAML with natural-language steps | |
| 23 | +| Prompt demos do not scale into test projects | Login, data setup, CI, and debugging remain outside the prompt | Keep setup and deterministic checks in scripts, while AI handles UI intent | |
| 24 | + |
| 25 | +## Adoption path |
| 26 | + |
| 27 | +Midscene should be adopted gradually: first make the business path runnable, then connect environment setup, and only move into a fully custom project when the team needs control over the runner, fixtures, assertions, and orchestration. |
| 28 | + |
| 29 | +| Stage | Best for | Recommended shape | |
| 30 | +| --- | --- | --- | |
| 31 | +| Smoke test | Verify a key business path quickly | YAML + case. Write the entry point, steps, and assertions in YAML, then run it from the CLI and inspect the report | |
| 32 | +| Simple customization | Tests need login state, accounts, cookies, devices, or a small amount of environment preparation | YAML + `setup.js`. Keep the business path in YAML and put pre-run preparation in setup | |
| 33 | +| Fully custom | The team needs to integrate an existing test project, CI, internal tools, data checks, or a custom runner | Use `midscene emit` to export an independent Rstest project, then maintain it like a standard test project | |
| 34 | + |
| 35 | +### Smoke test: YAML + case |
| 36 | + |
| 37 | +This stage is about one thing: make the core path easy to express, run, and review. The test author writes YAML for the entry point, actions, and expected result. Midscene executes the flow, captures screenshots, and generates the report. |
| 38 | + |
| 39 | +```yaml |
| 40 | +web: |
| 41 | + url: https://shop.example.com |
| 42 | + |
| 43 | +tasks: |
| 44 | + - name: Guest checkout smoke test |
| 45 | + flow: |
| 46 | + - aiAct: Search for "running shoes" |
| 47 | + - aiAct: Open the first product |
| 48 | + - aiAssert: The cart page shows one product and the checkout button |
| 49 | +``` |
| 50 | +
|
| 51 | +### Simple customization: YAML + setup.js |
| 52 | +
|
| 53 | +Once tests become part of daily work, they usually need login state, test accounts, cookies, device preparation, staging lanes, or other environment details. Those concerns should not be squeezed into natural-language steps. They belong in `setup.js`. |
| 54 | + |
| 55 | +Here, `setup.js` means the pre-run setup script for the test project. It runs before YAML cases and prepares the browser, device, account, or backend data for the test. A simple customized project can look like this: |
| 56 | + |
| 57 | +```text |
| 58 | +. |
| 59 | + setup.js |
| 60 | + midscene.config.yaml |
| 61 | + e2e/ |
| 62 | + dashboard.yaml |
| 63 | + checkout.yaml |
| 64 | +``` |
| 65 | + |
| 66 | +`midscene.config.yaml` manages model settings, runtime options, report output, and selected cases. `setup.js` manages project-specific preparation. `e2e/*.yaml` only describes the business path. |
| 67 | + |
| 68 | +YAML still describes the business path: |
| 69 | + |
| 70 | +```yaml |
| 71 | +web: |
| 72 | + url: https://internal.example.com/dashboard |
| 73 | +
|
| 74 | +tasks: |
| 75 | + - name: Check dashboard |
| 76 | + flow: |
| 77 | + - aiAssert: The dashboard is loaded and user information is visible |
| 78 | +``` |
| 79 | + |
| 80 | +`setup.js` gets the test to the right starting point, such as logging in, injecting cookies, preparing data, or connecting a device. Its value is giving deterministic preparation logic a clear home while the YAML case stays lightweight: |
| 81 | + |
| 82 | +```js |
| 83 | +export default async function setup({ browser, context, device }) { |
| 84 | + const cookies = await loginByTestAccount(process.env.TEST_ACCOUNT); |
| 85 | + await context.addCookies(cookies); |
| 86 | +
|
| 87 | + await prepareTestData({ |
| 88 | + user: process.env.TEST_ACCOUNT, |
| 89 | + scenario: 'dashboard-smoke', |
| 90 | + }); |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +The code above shows the boundary: login, accounts, data, and devices belong in setup. What the user should accomplish after the page opens stays in YAML. |
| 95 | + |
| 96 | +### Fully custom: emit an independent Rstest project |
| 97 | + |
| 98 | +When a team already has a test platform, CI rules, internal fixtures, data checks, and report systems, Midscene should not force everything through a fixed YAML runner. The core capability for fully custom projects is `emit`: export a lightweight Midscene project into an independent Rstest project. |
| 99 | + |
| 100 | +```bash |
| 101 | +midscene emit ./project-folder |
| 102 | +``` |
| 103 | + |
| 104 | +The emitted project can look like this: |
| 105 | + |
| 106 | +```text |
| 107 | +project-folder/ |
| 108 | + package.json |
| 109 | + rstest.config.ts |
| 110 | + setup.ts |
| 111 | + e2e/ |
| 112 | + dashboard.test.ts |
| 113 | + checkout.test.ts |
| 114 | + fixtures/ |
| 115 | + account.ts |
| 116 | + device.ts |
| 117 | + reports/ |
| 118 | + midscene-report/ |
| 119 | +``` |
| 120 | + |
| 121 | +At this stage, YAML is no longer the boundary of what the framework can do. It is the migration entry point. Teams can keep the business expression from YAML cases, or move complex logic into Rstest test files, fixtures, and internal tools. Midscene handles UI actions and visual assertions, while your own code handles environment orchestration, API checks, database checks, and failure analysis. |
| 122 | + |
| 123 | +The point of this stage is not to write everything in YAML. The point is to let Midscene generate a standard test project that the team can fully own. |
| 124 | + |
| 125 | +## Next steps |
| 126 | + |
| 127 | +- Run your first test: [Write UI tests with YAML](./ui-testing-yaml-quick-start) |
| 128 | +- Add setup, CI, reports, and deterministic checks: [Engineering UI tests with Midscene](./ui-testing-engineering) |
| 129 | +- Look up every YAML field: [Workflow in YAML format](./automate-with-scripts-in-yaml) |
| 130 | +- Look up every CLI flag: [YAML script runner](./yaml-script-runner) |
0 commit comments