@pzy560117/opentest 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/manifest.json +4 -1
- package/assets/skills/opentest/SKILL.md +7 -6
- package/assets/skills/opentest/references/android-app-testing.md +78 -0
- package/assets/skills/opentest/references/codex-harness-coverage-heuristics.md +2 -1
- package/assets/skills/opentest/references/complete-testing-workflow.md +3 -1
- package/assets/skills/opentest/references/test-surfaces.md +2 -2
- package/assets/skills/opentest/templates/android-app-acceptance-template.md +46 -0
- package/assets/skills/opentest/templates/matrix-template.md +1 -1
- package/assets/skills/opentest-accept/SKILL.md +4 -2
- package/assets/skills/opentest-android-app/SKILL.md +25 -0
- package/assets/skills/opentest-plan/SKILL.md +2 -1
- package/assets/skills/opentest-run/SKILL.md +2 -1
- package/assets/skills-zh/opentest/SKILL.md +6 -5
- package/assets/skills-zh/opentest/references/android-app-testing.md +78 -0
- package/assets/skills-zh/opentest/references/codex-harness-coverage-heuristics.md +2 -1
- package/assets/skills-zh/opentest/references/complete-testing-workflow.md +3 -1
- package/assets/skills-zh/opentest/references/test-surfaces.md +2 -2
- package/assets/skills-zh/opentest/templates/android-app-acceptance-template.md +46 -0
- package/assets/skills-zh/opentest/templates/matrix-template.md +1 -1
- package/assets/skills-zh/opentest-accept/SKILL.md +3 -1
- package/assets/skills-zh/opentest-android-app/SKILL.md +25 -0
- package/assets/skills-zh/opentest-plan/SKILL.md +2 -1
- package/assets/skills-zh/opentest-run/SKILL.md +2 -1
- package/package.json +1 -1
- package/scripts/smoke-test.js +48 -0
package/assets/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.1.
|
|
2
|
+
"version": "0.1.13",
|
|
3
3
|
"languages": [
|
|
4
4
|
{
|
|
5
5
|
"id": "en",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"localized": [
|
|
61
61
|
"opentest/SKILL.md",
|
|
62
62
|
"opentest/references/acceptance-evidence.md",
|
|
63
|
+
"opentest/references/android-app-testing.md",
|
|
63
64
|
"opentest/references/api-testing.md",
|
|
64
65
|
"opentest/references/codex-harness-coverage-heuristics.md",
|
|
65
66
|
"opentest/references/command-routing.md",
|
|
@@ -73,6 +74,7 @@
|
|
|
73
74
|
"opentest/references/test-surfaces.md",
|
|
74
75
|
"opentest/references/web-browser-testing.md",
|
|
75
76
|
"opentest/templates/acceptance-template.md",
|
|
77
|
+
"opentest/templates/android-app-acceptance-template.md",
|
|
76
78
|
"opentest/templates/api-acceptance-template.md",
|
|
77
79
|
"opentest/templates/archive-layout.md",
|
|
78
80
|
"opentest/templates/desktop-gui-acceptance-template.md",
|
|
@@ -82,6 +84,7 @@
|
|
|
82
84
|
"opentest/templates/report-template.md",
|
|
83
85
|
"opentest/templates/web-acceptance-template.md",
|
|
84
86
|
"opentest-accept/SKILL.md",
|
|
87
|
+
"opentest-android-app/SKILL.md",
|
|
85
88
|
"opentest-api/SKILL.md",
|
|
86
89
|
"opentest-archive/SKILL.md",
|
|
87
90
|
"opentest-author/SKILL.md",
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opentest
|
|
3
|
-
description: "OpenTest router
|
|
3
|
+
description: "OpenTest router."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# OpenTest
|
|
7
7
|
|
|
8
|
-
OpenTest
|
|
8
|
+
OpenTest is the single user entry. The AI routes phases and surface adapters.
|
|
9
9
|
|
|
10
10
|
## Required references
|
|
11
11
|
|
|
12
12
|
- `opentest/references/command-routing.md`
|
|
13
13
|
- `opentest/references/lifecycle.md`
|
|
14
14
|
- `opentest/references/complete-testing-workflow.md`
|
|
15
|
+
- `opentest/references/test-surfaces.md`
|
|
15
16
|
|
|
16
17
|
## Bootstrap
|
|
17
18
|
|
|
@@ -22,12 +23,12 @@ OPENTEST_GUARD="${OPENTEST_GUARD:-$(find "${OPENTEST_SEARCH_ROOTS[@]}" -path '*/
|
|
|
22
23
|
OPENTEST_DETECT="${OPENTEST_DETECT:-$(find "${OPENTEST_SEARCH_ROOTS[@]}" -path '*/opentest/scripts/opentest-detect.sh' -type f -print -quit 2>/dev/null)}"
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
Stop if scripts are missing.
|
|
26
27
|
|
|
27
28
|
## Route
|
|
28
29
|
|
|
29
30
|
1. If `.opentest.yaml` is missing, run `bash "$OPENTEST_STATE" init`.
|
|
30
31
|
2. Run `bash "$OPENTEST_STATE" check` and `bash "$OPENTEST_DETECT" summary`.
|
|
31
|
-
3.
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
32
|
+
3. Dispatch by `phase` to `opentest-plan`, `opentest-author`, `opentest-run`, `opentest-accept`, `opentest-verify`, `opentest-heal`, or `opentest-archive`.
|
|
33
|
+
4. `plan/run/accept` choose adapters from matrix surface: `web-browser` -> `opentest-web-browser`, `android-app` -> `opentest-android-app`, `desktop-gui` -> `opentest-desktop-gui`, `api` -> `opentest-api`.
|
|
34
|
+
5. Ask only when surface cannot be inferred. Use installed skill language.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Android App Testing
|
|
2
|
+
|
|
3
|
+
Use this reference for `android-app` execution-surface rows.
|
|
4
|
+
|
|
5
|
+
## Adapter Boundary
|
|
6
|
+
|
|
7
|
+
`opentest-android-app` is the OpenTest execution-surface adapter. It keeps Android app tests visible in installed OpenTest skills and routes detailed execution to `android-midscene-pytest` when available.
|
|
8
|
+
|
|
9
|
+
Do not duplicate the full Android Midscene SOP here. Use this reference to decide the OpenTest matrix, layout, evidence, and blocked rules.
|
|
10
|
+
|
|
11
|
+
## Default Layout
|
|
12
|
+
|
|
13
|
+
Durable Android assets follow `opentest/references/test-asset-layout.md`:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
tests/android/
|
|
17
|
+
tests_py/
|
|
18
|
+
midscene/
|
|
19
|
+
|
|
20
|
+
scripts/
|
|
21
|
+
opentest-run-android.ps1
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If a repository already has an Android harness, use the closest existing paths but keep the same logical slots: pytest wrapper, Midscene scripts, device preparation, and run entry.
|
|
25
|
+
|
|
26
|
+
The canonical Midscene slot is `tests/android/midscene/`.
|
|
27
|
+
|
|
28
|
+
## Default Route
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
opentest-android-app
|
|
32
|
+
-> android-midscene-pytest
|
|
33
|
+
-> pytest wrapper
|
|
34
|
+
-> npm/Vitest wrapper
|
|
35
|
+
-> @midscene/android
|
|
36
|
+
-> ADB + Android emulator/device
|
|
37
|
+
-> screenshots + logcat + Midscene HTML report
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
User-facing entry is pytest. Prefer `python -m pytest tests_py -v` in an existing Android harness, or `scripts/opentest-run-android.ps1` when the repository owns the fixed layout.
|
|
41
|
+
|
|
42
|
+
Run `npm run test:android` only when Midscene model environment variables are complete or when debugging Midscene directly.
|
|
43
|
+
|
|
44
|
+
## Required Evidence
|
|
45
|
+
|
|
46
|
+
`android-app` rows require:
|
|
47
|
+
|
|
48
|
+
- pytest report or command output
|
|
49
|
+
- ADB smoke result
|
|
50
|
+
- APK path, package name, emulator/device identity
|
|
51
|
+
- screenshot after key steps
|
|
52
|
+
- logcat or targeted Android logs
|
|
53
|
+
- Midscene HTML report when visual automation runs
|
|
54
|
+
- available `midscene_run/log/ai-call.log`, `agent.log`, `android-device.log`, and `midscene_run/report/*.html`
|
|
55
|
+
- read-after-write or persisted-state proof when the app writes data
|
|
56
|
+
|
|
57
|
+
## Blocking Rules
|
|
58
|
+
|
|
59
|
+
Record `blocked` when any required prerequisite is missing:
|
|
60
|
+
|
|
61
|
+
- ADB
|
|
62
|
+
- emulator or real device
|
|
63
|
+
- APK path
|
|
64
|
+
- package name or launch activity
|
|
65
|
+
- Midscene model credentials when visual automation is required
|
|
66
|
+
- fixture data, reset path, or stable result surface
|
|
67
|
+
|
|
68
|
+
Do not mark Android app acceptance as PASS from a static screenshot alone.
|
|
69
|
+
|
|
70
|
+
## Matrix Requirements
|
|
71
|
+
|
|
72
|
+
`android-app` rows must include:
|
|
73
|
+
|
|
74
|
+
- `Execution surface`: `android-app`
|
|
75
|
+
- `Acceptance mode`: `n/a`
|
|
76
|
+
- `Evidence layer`: `visual-acceptance`, `e2e`, `integration`, or `smoke`
|
|
77
|
+
- `Framework/command`: `opentest-android-app`, `android-midscene-pytest`, `python -m pytest tests_py -v`, or `scripts/opentest-run-android.ps1`
|
|
78
|
+
- `Required evidence`: pytest, ADB smoke, Midscene HTML report when used, screenshots, logcat, device/app metadata, `midscene_run` logs, and blocked prerequisites when unavailable
|
|
@@ -13,6 +13,7 @@ This reference extracts short rules from the local Codex Harness knowledge base,
|
|
|
13
13
|
- `tdd-workflow`
|
|
14
14
|
- `e2e-runner`
|
|
15
15
|
- `browser-e2e-testing`
|
|
16
|
+
- `opentest-android-app`
|
|
16
17
|
- `android-midscene-pytest`
|
|
17
18
|
- `opentest-desktop-gui`
|
|
18
19
|
- `opentest-api`
|
|
@@ -38,7 +39,7 @@ Choose the execution surface separately from the evidence layer:
|
|
|
38
39
|
| Surface | Default route |
|
|
39
40
|
| --- | --- |
|
|
40
41
|
| `web-browser` | Chrome DevTools MCP, Playwright CLI, or browser acceptance |
|
|
41
|
-
| `android-app` | `android-midscene-pytest` when available
|
|
42
|
+
| `android-app` | `opentest-android-app`; routes to `android-midscene-pytest` when available, with `python -m pytest tests_py -v` driving Midscene Android through ADB |
|
|
42
43
|
| `desktop-gui` | `opentest-desktop-gui`; project GUI automation first, `@midscene/computer` for visual/native/RDP GUI flows, or scripted manual GUI acceptance when automation is unavailable |
|
|
43
44
|
| `api` | `opentest-api`; project API/integration command first, otherwise `pytest` with `httpx`/`requests`, schema checks, fixtures, read-after-write, and cleanup/teardown |
|
|
44
45
|
|
|
@@ -27,10 +27,12 @@ Primary execution surfaces are:
|
|
|
27
27
|
- `desktop-gui`: native desktop GUI, Electron, Tauri, or similar app UI
|
|
28
28
|
- `api`: HTTP API, RPC, backend workflow, contract, or service endpoint
|
|
29
29
|
|
|
30
|
-
Do not use unit, component, integration, contract, smoke, or security review as the execution surface. Those are evidence layers or run gates. If an Android GUI requirement is present, route acceptance through
|
|
30
|
+
Do not use unit, component, integration, contract, smoke, or security review as the execution surface. Those are evidence layers or run gates. If an Android GUI requirement is present, route acceptance through `opentest-android-app`, which uses `android-midscene-pytest` when available, and require pytest/Midscene/screenshot/logcat evidence. If native desktop GUI behavior is present, route acceptance through `opentest-desktop-gui` and require project GUI automation or `@midscene/computer` evidence plus screenshots, GUI action logs, window/app metadata, and deterministic read-back. If API behavior is present, route acceptance through `opentest-api` and require contract, status code, payload/schema, auth/permission, read-after-write, and cleanup/teardown evidence when applicable.
|
|
31
31
|
|
|
32
32
|
For `web-browser`, choose an acceptance mode from `opentest/references/web-browser-testing.md`. MCP and Playwright CLI are immediate acceptance routes; durable regression requires a committed repeatable test such as `@playwright/test`.
|
|
33
33
|
|
|
34
|
+
For `android-app`, use `opentest/references/android-app-testing.md`. Durable Android assets stay in `tests/android/tests_py/`, `tests/android/midscene/`, and `scripts/opentest-run-android.ps1` or an existing Android harness.
|
|
35
|
+
|
|
34
36
|
For `desktop-gui`, use `opentest/references/desktop-gui-testing.md`. Electron/Tauri DOM-verifiable flows can stay in `web-browser`; native shell, tray, file picker, menu, OS dialog, installer, updater, RDP, and multi-window behavior stay in `desktop-gui`.
|
|
35
37
|
|
|
36
38
|
For `api`, use `opentest/references/api-testing.md`. Project API/integration commands are preferred; without them, use `pytest` with `httpx` or `requests`, schema checks, fixtures, and deterministic read-back.
|
|
@@ -11,7 +11,7 @@ Keep the primary execution surface to one of these four values:
|
|
|
11
11
|
| Surface | Use when | Default acceptance path | Required artifacts |
|
|
12
12
|
| --- | --- | --- | --- |
|
|
13
13
|
| `web-browser` | Browser-rendered web pages, web apps, admin consoles, SaaS, dashboards | Use `opentest-web-browser`: Playwright MCP first, Playwright CLI fallback, `@playwright/test` for durable regression, Midscene only for visual assist | screenshots, snapshots, post-submit assertions, console/network notes, trace/report when durable |
|
|
14
|
-
| `android-app` | Android APK or Android app GUI on emulator/device | Use
|
|
14
|
+
| `android-app` | Android APK or Android app GUI on emulator/device | Use `opentest-android-app`, which routes to `android-midscene-pytest` when available: pytest orchestrates, `@midscene/android` executes visual automation, ADB/emulator controls device | pytest report, ADB smoke, Midscene HTML report, screenshots, logcat, device/app metadata, `midscene_run` logs |
|
|
15
15
|
| `desktop-gui` | Native desktop GUI or Electron/Tauri/Windows/macOS/Linux app UI | Use `opentest-desktop-gui`: project GUI automation first; `@midscene/computer` for visual desktop automation, weak selectors, native controls, multi-window flows, or RDP; scripted manual GUI acceptance only when automation is unavailable | screenshots or recording, GUI action log, window/app metadata, deterministic read-back, failure capture |
|
|
16
16
|
| `api` | HTTP API, RPC, backend workflow, contract, service endpoint | Use `opentest-api`: project API/integration command first; otherwise `pytest` with `httpx` or `requests`, schema checks, fixtures, and read-after-write evidence | request/response records, status codes, payload/schema assertions, auth/permission results, data consistency, cleanup/teardown, logs |
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ Examples:
|
|
|
30
30
|
|
|
31
31
|
## Android App Surface
|
|
32
32
|
|
|
33
|
-
For
|
|
33
|
+
For `android-app`, read `opentest/references/android-app-testing.md` or use `opentest-android-app`. It routes through `android-midscene-pytest` when installed:
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
36
|
python -m pytest tests_py -v
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Android App Acceptance
|
|
2
|
+
|
|
3
|
+
## ACC-Android-001
|
|
4
|
+
|
|
5
|
+
- execution surface: android-app
|
|
6
|
+
- acceptance mode: n/a
|
|
7
|
+
- tool route: opentest-android-app | android-midscene-pytest | pytest wrapper | @midscene/android
|
|
8
|
+
- evidence layer: visual-acceptance | e2e | integration | smoke
|
|
9
|
+
- APK path:
|
|
10
|
+
- package name:
|
|
11
|
+
- emulator/device:
|
|
12
|
+
- fixture/reset:
|
|
13
|
+
- status: pending
|
|
14
|
+
|
|
15
|
+
### Environment
|
|
16
|
+
|
|
17
|
+
- ADB status:
|
|
18
|
+
- model env status:
|
|
19
|
+
- app version/build:
|
|
20
|
+
- device/app metadata:
|
|
21
|
+
|
|
22
|
+
### Steps
|
|
23
|
+
|
|
24
|
+
1.
|
|
25
|
+
|
|
26
|
+
### Expected Outcome
|
|
27
|
+
|
|
28
|
+
-
|
|
29
|
+
|
|
30
|
+
### Read-Back Contract
|
|
31
|
+
|
|
32
|
+
- app result surface:
|
|
33
|
+
- persisted state:
|
|
34
|
+
- refresh/reopen check:
|
|
35
|
+
- cleanup assertion:
|
|
36
|
+
|
|
37
|
+
### Evidence
|
|
38
|
+
|
|
39
|
+
- status:
|
|
40
|
+
- pytest report:
|
|
41
|
+
- ADB smoke:
|
|
42
|
+
- screenshots:
|
|
43
|
+
- logcat:
|
|
44
|
+
- Midscene HTML report:
|
|
45
|
+
- midscene_run logs:
|
|
46
|
+
- blockers:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
| ACC-001 | REQ-001 / user story | create succeeds in web UI | web-browser | instant-acceptance | create | valid fixture entity | entity is created and visible in list/detail | high | browser-acceptance + integration | Playwright MCP / Playwright CLI + project command | create evidence, UI/API/DB assertion, fixture used | none | pending |
|
|
6
6
|
| ACC-002 | REQ-WEB-REG-001 / regression need | web CRUD has durable regression | web-browser | durable-regression | read/list/detail + end-to-end CRUD | committed E2E test | create -> list -> detail -> update -> read back -> delete is repeatable | high | e2e | `npx playwright test` or project E2E command | test file, trace/report, stable locator assertions | none | pending |
|
|
7
7
|
| ACC-003 | REQ-WEB-VIS-001 / visual risk | visual web state is verified | web-browser | visual-ai-assist | visual behavior | weak selector or canvas UI | Midscene helps locate UI and deterministic read-back proves result | medium | visual-acceptance | Midscene + Playwright route | Midscene report, screenshot, read/assert result | none | pending |
|
|
8
|
-
| ACC-004 | REQ-ANDROID-001 / mobile flow | create succeeds in Android app | android-app | n/a | create | APK installed on emulator/device | task is created and visible after app refresh | high | visual-acceptance + e2e | `android-midscene-pytest` / `python -m pytest tests_py -v` | pytest report, ADB smoke, Midscene HTML report, screenshot, logcat, `midscene_run` logs | missing ADB/APK/device/package/model env if unavailable | pending |
|
|
8
|
+
| ACC-004 | REQ-ANDROID-001 / mobile flow | create succeeds in Android app | android-app | n/a | create | APK installed on emulator/device | task is created and visible after app refresh | high | visual-acceptance + e2e | `opentest-android-app` / `android-midscene-pytest` / `python -m pytest tests_py -v` | pytest report, ADB smoke, Midscene HTML report, screenshot, logcat, device/app metadata, `midscene_run` logs | missing ADB/APK/device/package/model env/result surface if unavailable | pending |
|
|
9
9
|
| ACC-005 | REQ-DESKTOP-001 / settings workflow | desktop setting saves | desktop-gui | n/a | update | desktop app window is open | setting persists after save and reopen | high | gui-acceptance + integration | `opentest-desktop-gui` / project GUI automation / `@midscene/computer` | screenshot or recording, GUI action log, app/window metadata, deterministic read-back, Midscene/computer report when used | missing display/RDP/app launch/window identity/model env/result surface if unavailable | pending |
|
|
10
10
|
| ACC-006 | REQ-API-001 / contract | API create succeeds | api | n/a | create | valid request payload | response status and payload confirm created entity | high | contract + integration | `opentest-api` / project API command / `python -m pytest tests/api -v` | request/response record, status code, payload/schema assertion, read-after-write, data consistency, cleanup/teardown | missing base URL/auth/fixture/seed/teardown/dependency/schema/result surface if unavailable | pending |
|
|
11
11
|
| ACC-007 | Risk: invalid and unauthorized input | failure and boundary paths are handled | api | n/a | failure/boundary | invalid, empty, duplicate, unauthorized, expired, forbidden, or stale fixture data | clear error contract without corrupting data | high | contract + security-review | `opentest-api` / project command / `python -m pytest tests/api -v` | validation, auth/permission, duplicate/idempotency, stale-state, error schema, sensitive-field evidence | none | pending |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opentest-accept
|
|
3
|
-
description: "OpenTest phase 4: execute
|
|
3
|
+
description: "OpenTest phase 4: execute acceptance and write back evidence."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# OpenTest Accept
|
|
@@ -12,10 +12,12 @@ Write PASS, FAIL, or blocked evidence to cases and matrix.
|
|
|
12
12
|
- `opentest/references/acceptance-evidence.md`
|
|
13
13
|
- `opentest/references/complete-testing-workflow.md`
|
|
14
14
|
- `opentest/references/test-surfaces.md`
|
|
15
|
+
- `opentest/references/android-app-testing.md`
|
|
15
16
|
- `opentest/references/web-browser-testing.md`
|
|
16
17
|
- `opentest/references/desktop-gui-testing.md`
|
|
17
18
|
- `opentest/references/api-testing.md`
|
|
18
19
|
- `opentest/templates/acceptance-template.md`
|
|
20
|
+
- `opentest/templates/android-app-acceptance-template.md`
|
|
19
21
|
- `opentest/templates/desktop-gui-acceptance-template.md`
|
|
20
22
|
- `opentest/templates/api-acceptance-template.md`
|
|
21
23
|
|
|
@@ -24,7 +26,7 @@ Write PASS, FAIL, or blocked evidence to cases and matrix.
|
|
|
24
26
|
1. Read the matrix, fixtures, and `docs/opentest/acceptance/`.
|
|
25
27
|
2. Select the acceptance tool from the matrix execution surface.
|
|
26
28
|
3. For `web-browser`, use `opentest-web-browser`: Playwright MCP/CLI, `@playwright/test` for durable regression, Midscene only for visual assist.
|
|
27
|
-
4. For `android-app`, use `android-midscene-pytest`: `python -m pytest tests_py -v`, ADB smoke, Midscene HTML, logcat, and `midscene_run`; block missing prerequisites.
|
|
29
|
+
4. For `android-app`, use `opentest-android-app` and `android-midscene-pytest`: `python -m pytest tests_py -v`, ADB smoke, Midscene HTML, logcat, and `midscene_run`; block missing prerequisites.
|
|
28
30
|
5. For `desktop-gui`, use `opentest-desktop-gui`: project GUI automation or `@midscene/computer`, screenshot/recording, metadata, and read-back.
|
|
29
31
|
6. For `api`, use `opentest-api`: project API command or `pytest` with `httpx`/`requests`, schema checks, fixtures, read-after-write, and cleanup/teardown.
|
|
30
32
|
7. For CRUD/data changes, execute the full chain from the workflow reference.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opentest-android-app
|
|
3
|
+
description: "OpenTest Android app execution surface adapter. Use when planning, authoring, running, or accepting Android APK/app GUI workflows through android-midscene-pytest, ADB, emulator/device setup, screenshots, logcat, and Midscene reports."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenTest Android App
|
|
7
|
+
|
|
8
|
+
Use this adapter for `android-app` matrix rows.
|
|
9
|
+
|
|
10
|
+
## Required references
|
|
11
|
+
|
|
12
|
+
- `opentest/references/android-app-testing.md`
|
|
13
|
+
- `opentest/templates/android-app-acceptance-template.md`
|
|
14
|
+
|
|
15
|
+
## Route
|
|
16
|
+
|
|
17
|
+
1. Use `android-midscene-pytest` as the detailed Android execution skill when available.
|
|
18
|
+
2. Keep durable Android assets in the fixed layout from `test-asset-layout.md`: `tests/android/tests_py/`, `tests/android/midscene/`, and `scripts/opentest-run-android.ps1` or an existing Android harness command.
|
|
19
|
+
3. User-facing execution should enter through pytest, normally `python -m pytest tests_py -v` in an existing harness or the repository's Android test entry.
|
|
20
|
+
4. Run `npm run test:android` only when model environment variables are ready or when debugging the Midscene layer.
|
|
21
|
+
5. Mark blocked when ADB, emulator/device, APK path, package name, model credentials, fixture data, or stable result surface is missing.
|
|
22
|
+
|
|
23
|
+
## Evidence Contract
|
|
24
|
+
|
|
25
|
+
PASS requires pytest result, ADB smoke, Midscene HTML report when visual automation runs, screenshots, logcat, device/app metadata, and any available `midscene_run` logs. Static screenshots alone are not Android app acceptance.
|
|
@@ -14,6 +14,7 @@ Create plan, matrix, and fixtures before implementation.
|
|
|
14
14
|
- `opentest/references/complete-testing-workflow.md`
|
|
15
15
|
- `opentest/references/test-asset-layout.md`
|
|
16
16
|
- `opentest/references/test-surfaces.md`
|
|
17
|
+
- `opentest/references/android-app-testing.md`
|
|
17
18
|
- `opentest/references/web-browser-testing.md`
|
|
18
19
|
- `opentest/references/desktop-gui-testing.md`
|
|
19
20
|
- `opentest/references/api-testing.md`
|
|
@@ -23,7 +24,7 @@ Create plan, matrix, and fixtures before implementation.
|
|
|
23
24
|
1. Read rules, requirements/diff, commands, and detection output.
|
|
24
25
|
2. Treat requirements and risks as sources; inspect current code only for project facts.
|
|
25
26
|
3. Apply CRUD baseline and test data rules for data-writing/API/form/file/stateful changes.
|
|
26
|
-
4. Classify execution surface and evidence layer separately: `web-browser`, `android-app`, `desktop-gui`, or `api`; use web modes, `opentest-desktop-gui`, and `opentest-api` where applicable.
|
|
27
|
+
4. Classify execution surface and evidence layer separately: `web-browser`, `android-app`, `desktop-gui`, or `api`; use `opentest-android-app`, web modes, `opentest-desktop-gui`, and `opentest-api` where applicable.
|
|
27
28
|
5. Produce a requirement-first matrix with source, behavior, surface, mode, evidence, command, gap/blocker, status, and fixed layout.
|
|
28
29
|
6. Write `.opentest.yaml` fields: `plan`, `matrix`, `fixtures`.
|
|
29
30
|
7. Update handoff if present, then run `bash "$OPENTEST_GUARD" plan --apply`.
|
|
@@ -13,6 +13,7 @@ Run matrix-driven commands and write reports under `docs/opentest/runs/`.
|
|
|
13
13
|
- `opentest/references/complete-testing-workflow.md`
|
|
14
14
|
- `opentest/references/test-asset-layout.md`
|
|
15
15
|
- `opentest/references/test-surfaces.md`
|
|
16
|
+
- `opentest/references/android-app-testing.md`
|
|
16
17
|
- `opentest/references/web-browser-testing.md`
|
|
17
18
|
- `opentest/references/desktop-gui-testing.md`
|
|
18
19
|
- `opentest/references/api-testing.md`
|
|
@@ -28,7 +29,7 @@ Run matrix-driven commands and write reports under `docs/opentest/runs/`.
|
|
|
28
29
|
## Steps
|
|
29
30
|
|
|
30
31
|
1. Read `run_mode`, matrix, fixtures, required evidence, and fixed asset layout.
|
|
31
|
-
2. Choose by matrix execution surface: MCP/CLI or `npx playwright test` for `web-browser`; `python -m pytest tests_py -v` for `android-app`, with `npm run test:android` only when model env is ready or debugging Midscene; `opentest-desktop-gui` for `desktop-gui`; `opentest-api` or `python -m pytest tests/api -v` for `api`.
|
|
32
|
+
2. Choose by matrix execution surface: MCP/CLI or `npx playwright test` for `web-browser`; `opentest-android-app` or `python -m pytest tests_py -v` for `android-app`, with `npm run test:android` only when model env is ready or debugging Midscene; `opentest-desktop-gui` for `desktop-gui`; `opentest-api` or `python -m pytest tests/api -v` for `api`.
|
|
32
33
|
3. Prefer explicit project commands; otherwise use `python -m pytest` for code-level tests.
|
|
33
34
|
4. For coverage, prefer `python -m pytest --cov=. --cov-report=term-missing`.
|
|
34
35
|
5. Smoke evidence is required unless the matrix says not applicable.
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: opentest
|
|
3
|
-
description: "OpenTest
|
|
3
|
+
description: "OpenTest 路由:状态检测、阶段分发和执行面 adapter 选择。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# OpenTest
|
|
7
7
|
|
|
8
|
-
OpenTest
|
|
8
|
+
OpenTest 把需求转成测试证据生命周期。用户只触发 OpenTest;AI 自动选择阶段 skill 和执行面 adapter。
|
|
9
9
|
|
|
10
10
|
## 必读引用
|
|
11
11
|
|
|
12
12
|
- `opentest/references/command-routing.md`
|
|
13
13
|
- `opentest/references/lifecycle.md`
|
|
14
14
|
- `opentest/references/complete-testing-workflow.md`
|
|
15
|
+
- `opentest/references/test-surfaces.md`
|
|
15
16
|
|
|
16
17
|
## 启动
|
|
17
18
|
|
|
@@ -28,6 +29,6 @@ OPENTEST_DETECT="${OPENTEST_DETECT:-$(find "${OPENTEST_SEARCH_ROOTS[@]}" -path '
|
|
|
28
29
|
|
|
29
30
|
1. 若 `.opentest.yaml` 不存在,运行 `bash "$OPENTEST_STATE" init`。
|
|
30
31
|
2. 运行 `bash "$OPENTEST_STATE" check` 和 `bash "$OPENTEST_DETECT" summary`。
|
|
31
|
-
3.
|
|
32
|
-
4.
|
|
33
|
-
5.
|
|
32
|
+
3. 按 `phase` 分发到 `opentest-plan`、`opentest-author`、`opentest-run`、`opentest-accept`、`opentest-verify`、`opentest-heal` 或 `opentest-archive`。
|
|
33
|
+
4. `plan/run/accept` 按矩阵执行面自动选择 adapter:`web-browser` -> `opentest-web-browser`,`android-app` -> `opentest-android-app`,`desktop-gui` -> `opentest-desktop-gui`,`api` -> `opentest-api`。
|
|
34
|
+
5. 除非无法推断执行面,不要让用户手动选择 adapter。使用已安装的 skill 语言。
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Android App 测试
|
|
2
|
+
|
|
3
|
+
用于 `android-app` 执行面的矩阵行。
|
|
4
|
+
|
|
5
|
+
## 适配边界
|
|
6
|
+
|
|
7
|
+
`opentest-android-app` 是 OpenTest 的执行面适配器。它让 Android App 测试在安装后的 OpenTest skills 中可见,并在可用时把详细执行路由到 `android-midscene-pytest`。
|
|
8
|
+
|
|
9
|
+
这里不复制完整 Android Midscene SOP。本文只定义 OpenTest 矩阵、目录、证据和阻塞规则。
|
|
10
|
+
|
|
11
|
+
## 默认目录
|
|
12
|
+
|
|
13
|
+
稳定 Android 资产遵循 `opentest/references/test-asset-layout.md`:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
tests/android/
|
|
17
|
+
tests_py/
|
|
18
|
+
midscene/
|
|
19
|
+
|
|
20
|
+
scripts/
|
|
21
|
+
opentest-run-android.ps1
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
如果仓库已有 Android harness,优先使用最接近的现有路径,但逻辑槽位必须保持一致:pytest wrapper、Midscene 脚本、设备准备和运行入口。
|
|
25
|
+
|
|
26
|
+
标准 Midscene 槽位是 `tests/android/midscene/`。
|
|
27
|
+
|
|
28
|
+
## 默认路线
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
opentest-android-app
|
|
32
|
+
-> android-midscene-pytest
|
|
33
|
+
-> pytest wrapper
|
|
34
|
+
-> npm/Vitest wrapper
|
|
35
|
+
-> @midscene/android
|
|
36
|
+
-> ADB + Android emulator/device
|
|
37
|
+
-> screenshots + logcat + Midscene HTML report
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
面向用户的入口是 pytest。优先使用现有 Android harness 中的 `python -m pytest tests_py -v`,或仓库采用固定目录时的 `scripts/opentest-run-android.ps1`。
|
|
41
|
+
|
|
42
|
+
只有 Midscene 模型环境变量齐全,或需要直接排查 Midscene 层时,才运行 `npm run test:android`。
|
|
43
|
+
|
|
44
|
+
## 必需证据
|
|
45
|
+
|
|
46
|
+
`android-app` 行需要:
|
|
47
|
+
|
|
48
|
+
- pytest 报告或命令输出
|
|
49
|
+
- ADB 冒烟结果
|
|
50
|
+
- APK 路径、package name、模拟器/真机标识
|
|
51
|
+
- 关键步骤后的截图
|
|
52
|
+
- logcat 或定向 Android 日志
|
|
53
|
+
- 执行视觉自动化时的 Midscene HTML 报告
|
|
54
|
+
- 可用的 `midscene_run/log/ai-call.log`、`agent.log`、`android-device.log` 和 `midscene_run/report/*.html`
|
|
55
|
+
- App 写数据时的写后读或持久化状态证明
|
|
56
|
+
|
|
57
|
+
## 阻塞规则
|
|
58
|
+
|
|
59
|
+
缺少任一必需前置条件时记录 `blocked`:
|
|
60
|
+
|
|
61
|
+
- ADB
|
|
62
|
+
- 模拟器或真机
|
|
63
|
+
- APK 路径
|
|
64
|
+
- package name 或 launch activity
|
|
65
|
+
- 需要视觉自动化时的 Midscene 模型凭据
|
|
66
|
+
- fixture 数据、reset 路径或稳定结果面
|
|
67
|
+
|
|
68
|
+
不得只凭静态截图把 Android App 验收标为 PASS。
|
|
69
|
+
|
|
70
|
+
## 矩阵要求
|
|
71
|
+
|
|
72
|
+
`android-app` 行必须包含:
|
|
73
|
+
|
|
74
|
+
- `执行面`:`android-app`
|
|
75
|
+
- `验收模式`:`n/a`
|
|
76
|
+
- `证据层级`:`visual-acceptance`、`e2e`、`integration` 或 `smoke`
|
|
77
|
+
- `框架/命令`:`opentest-android-app`、`android-midscene-pytest`、`python -m pytest tests_py -v` 或 `scripts/opentest-run-android.ps1`
|
|
78
|
+
- `必需证据`:pytest、ADB 冒烟、使用时的 Midscene HTML 报告、截图、logcat、设备/App 元数据、`midscene_run` 日志,以及不可用时的 blocked 前置条件
|
|
@@ -13,6 +13,7 @@ OpenTest 应根据变更类型、风险和项目事实选择适用覆盖面。
|
|
|
13
13
|
- `tdd-workflow`
|
|
14
14
|
- `e2e-runner`
|
|
15
15
|
- `browser-e2e-testing`
|
|
16
|
+
- `opentest-android-app`
|
|
16
17
|
- `android-midscene-pytest`
|
|
17
18
|
- `opentest-desktop-gui`
|
|
18
19
|
- `opentest-api`
|
|
@@ -38,7 +39,7 @@ OpenTest 应根据变更类型、风险和项目事实选择适用覆盖面。
|
|
|
38
39
|
| 执行面 | 默认路由 |
|
|
39
40
|
| --- | --- |
|
|
40
41
|
| `web-browser` | Chrome DevTools MCP、Playwright CLI 或浏览器验收 |
|
|
41
|
-
| `android-app` |
|
|
42
|
+
| `android-app` | `opentest-android-app`;已安装时路由到 `android-midscene-pytest`,由 `python -m pytest tests_py -v` 通过 ADB 驱动 Midscene Android |
|
|
42
43
|
| `desktop-gui` | `opentest-desktop-gui`;优先项目 GUI 自动化,视觉/原生/RDP GUI 流程用 `@midscene/computer`,无自动化时才用脚本化人工 GUI 验收 |
|
|
43
44
|
| `api` | `opentest-api`;优先项目 API/integration 命令,否则用 `pytest` + `httpx`/`requests`、schema 校验、fixtures、写后读和 cleanup/teardown |
|
|
44
45
|
|
|
@@ -27,10 +27,12 @@ unit、component、integration、contract、E2E、smoke、browser acceptance 都
|
|
|
27
27
|
- `desktop-gui`:原生桌面 GUI、Electron、Tauri 或类似 App UI
|
|
28
28
|
- `api`:HTTP API、RPC、后端工作流、契约或服务端点
|
|
29
29
|
|
|
30
|
-
不得把 unit、component、integration、contract、smoke 或 security review 当成执行面;它们是证据层级或运行门禁。如果存在 Android GUI
|
|
30
|
+
不得把 unit、component、integration、contract、smoke 或 security review 当成执行面;它们是证据层级或运行门禁。如果存在 Android GUI 需求,用 `opentest-android-app` 执行验收,并在可用时路由到 `android-midscene-pytest`,要求 pytest/Midscene/截图/logcat 证据。如果存在原生桌面 GUI 行为,用 `opentest-desktop-gui` 执行验收,并要求项目 GUI 自动化或 `@midscene/computer` 证据,加上截图、GUI 操作日志、窗口/App 元数据和确定性回读。如果存在 API 行为,用 `opentest-api` 执行验收,并按适用性要求契约、状态码、payload/schema、鉴权/权限、写后读和 cleanup/teardown 证据。
|
|
31
31
|
|
|
32
32
|
`web-browser` 必须按 `opentest/references/web-browser-testing.md` 选择验收模式。MCP 和 Playwright CLI 是现场验收路径;稳定回归必须有已提交、可重复运行的测试,例如 `@playwright/test`。
|
|
33
33
|
|
|
34
|
+
`android-app` 使用 `opentest/references/android-app-testing.md`。稳定 Android 资产放在 `tests/android/tests_py/`、`tests/android/midscene/` 和 `scripts/opentest-run-android.ps1`,或现有 Android harness 的等价位置。
|
|
35
|
+
|
|
34
36
|
`desktop-gui` 使用 `opentest/references/desktop-gui-testing.md`。Electron/Tauri 的 DOM 可验证流程可以保留在 `web-browser`;原生外壳、托盘、文件选择器、菜单、系统弹窗、安装器、更新器、RDP 和多窗口行为保留在 `desktop-gui`。
|
|
35
37
|
|
|
36
38
|
`api` 使用 `opentest/references/api-testing.md`。优先项目 API/integration 命令;没有项目命令时,用 `pytest` + `httpx` 或 `requests`、schema 校验、fixtures 和确定性回读。
|
|
@@ -11,7 +11,7 @@ OpenTest 同时按执行面和证据层级分类验收:
|
|
|
11
11
|
| 执行面 | 适用场景 | 默认验收路径 | 必需产物 |
|
|
12
12
|
| --- | --- | --- | --- |
|
|
13
13
|
| `web-browser` | 浏览器渲染的 Web 页面、Web App、后台、SaaS、仪表盘 | 使用 `opentest-web-browser`:优先 Playwright MCP,失败时降级 Playwright CLI;稳定回归用 `@playwright/test`;视觉补充才用 Midscene | 截图、snapshot、提交后断言、console/network 记录、稳定回归的 trace/report |
|
|
14
|
-
| `android-app` | Android APK 或模拟器/真机上的 Android App GUI |
|
|
14
|
+
| `android-app` | Android APK 或模拟器/真机上的 Android App GUI | 使用 `opentest-android-app`,并在可用时路由到 `android-midscene-pytest`:pytest 编排,`@midscene/android` 执行视觉自动化,ADB/模拟器控制设备 | pytest 报告、ADB 冒烟、Midscene HTML 报告、截图、logcat、设备/App 元数据、`midscene_run` 日志 |
|
|
15
15
|
| `desktop-gui` | 原生桌面 GUI 或 Electron/Tauri/Windows/macOS/Linux App UI | 使用 `opentest-desktop-gui`:优先项目 GUI 自动化;视觉桌面自动化、弱选择器、原生控件、多窗口流程或 RDP 用 `@midscene/computer`;没有自动化时才用脚本化人工 GUI 验收 | 截图或录屏、GUI 操作日志、窗口/App 元数据、确定性回读、失败截图 |
|
|
16
16
|
| `api` | HTTP API、RPC、后端工作流、契约、服务端点 | 使用 `opentest-api`:优先项目 API/integration 命令;否则用 `pytest` + `httpx` 或 `requests`、schema 校验、fixtures 和写后读证据 | 请求/响应记录、状态码、payload/schema 断言、鉴权/权限结果、数据一致性、cleanup/teardown、日志 |
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ OpenTest 同时按执行面和证据层级分类验收:
|
|
|
30
30
|
|
|
31
31
|
## Android App 执行面
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
`android-app` 行读取 `opentest/references/android-app-testing.md`,或调用 `opentest-android-app`。它会在已安装时路由到 `android-midscene-pytest`:
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
36
|
python -m pytest tests_py -v
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Android App 验收
|
|
2
|
+
|
|
3
|
+
## ACC-Android-001
|
|
4
|
+
|
|
5
|
+
- 执行面: android-app
|
|
6
|
+
- 验收模式: n/a
|
|
7
|
+
- 工具路线: opentest-android-app | android-midscene-pytest | pytest wrapper | @midscene/android
|
|
8
|
+
- 证据层级: visual-acceptance | e2e | integration | smoke
|
|
9
|
+
- APK 路径:
|
|
10
|
+
- package name:
|
|
11
|
+
- 模拟器/真机:
|
|
12
|
+
- fixture/reset:
|
|
13
|
+
- 状态: pending
|
|
14
|
+
|
|
15
|
+
### 环境
|
|
16
|
+
|
|
17
|
+
- ADB 状态:
|
|
18
|
+
- 模型环境状态:
|
|
19
|
+
- App 版本/build:
|
|
20
|
+
- 设备/App 元数据:
|
|
21
|
+
|
|
22
|
+
### 步骤
|
|
23
|
+
|
|
24
|
+
1.
|
|
25
|
+
|
|
26
|
+
### 期望结果
|
|
27
|
+
|
|
28
|
+
-
|
|
29
|
+
|
|
30
|
+
### 回读契约
|
|
31
|
+
|
|
32
|
+
- App 结果面:
|
|
33
|
+
- 持久化状态:
|
|
34
|
+
- 刷新/重开检查:
|
|
35
|
+
- cleanup 断言:
|
|
36
|
+
|
|
37
|
+
### 证据
|
|
38
|
+
|
|
39
|
+
- 状态:
|
|
40
|
+
- pytest 报告:
|
|
41
|
+
- ADB 冒烟:
|
|
42
|
+
- 截图:
|
|
43
|
+
- logcat:
|
|
44
|
+
- Midscene HTML 报告:
|
|
45
|
+
- midscene_run 日志:
|
|
46
|
+
- 阻塞项:
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
| ACC-001 | REQ-001 / 用户故事 | Web UI 新增成功 | web-browser | instant-acceptance | 新增 | 有效 fixture 实体 | 创建成功,并能在列表/详情中看到 | high | browser-acceptance + integration | Playwright MCP / Playwright CLI + 项目命令 | 新增证据、UI/API/DB 断言、使用的测试数据 | 无 | pending |
|
|
6
6
|
| ACC-002 | REQ-WEB-REG-001 / 回归需求 | Web CRUD 有稳定回归 | web-browser | durable-regression | 查询/列表/详情 + 端到端 CRUD | 已提交 E2E 测试 | 新增 -> 列表 -> 详情 -> 修改 -> 回读 -> 删除 可重复验证 | high | e2e | `npx playwright test` 或项目 E2E 命令 | 测试文件、trace/report、稳定 locator 断言 | 无 | pending |
|
|
7
7
|
| ACC-003 | REQ-WEB-VIS-001 / 视觉风险 | Web 视觉状态可验证 | web-browser | visual-ai-assist | 视觉行为 | 弱选择器或 canvas UI | Midscene 辅助定位 UI,确定性回读证明结果 | medium | visual-acceptance | Midscene + Playwright 路由 | Midscene 报告、截图、回读断言结果 | 无 | pending |
|
|
8
|
-
| ACC-004 | REQ-ANDROID-001 / 移动端流程 | Android App 新增成功 | android-app | n/a | 新增 | APK 已安装到模拟器/真机 | 任务创建成功,刷新后仍可见 | high | visual-acceptance + e2e | `android-midscene-pytest` / `python -m pytest tests_py -v` | pytest 报告、ADB 冒烟、Midscene HTML 报告、截图、logcat
|
|
8
|
+
| ACC-004 | REQ-ANDROID-001 / 移动端流程 | Android App 新增成功 | android-app | n/a | 新增 | APK 已安装到模拟器/真机 | 任务创建成功,刷新后仍可见 | high | visual-acceptance + e2e | `opentest-android-app` / `android-midscene-pytest` / `python -m pytest tests_py -v` | pytest 报告、ADB 冒烟、Midscene HTML 报告、截图、logcat、设备/App 元数据、`midscene_run` 日志 | 缺 ADB/APK/设备/package/模型环境变量/结果面时阻塞 | pending |
|
|
9
9
|
| ACC-005 | REQ-DESKTOP-001 / 设置流程 | 桌面设置保存成功 | desktop-gui | n/a | 修改 | 桌面应用窗口已打开 | 设置保存并在重开后仍生效 | high | gui-acceptance + integration | `opentest-desktop-gui` / 项目 GUI 自动化 / `@midscene/computer` | 截图或录屏、GUI 操作日志、App/窗口元数据、确定性回读、使用 Midscene/computer 时的报告 | 缺 display/RDP/App 启动/窗口标识/模型环境变量/结果面时阻塞 | pending |
|
|
10
10
|
| ACC-006 | REQ-API-001 / 契约 | API 新增成功 | api | n/a | 新增 | 合法请求 payload | 响应状态码和 payload 证明实体已创建 | high | contract + integration | `opentest-api` / 项目 API 命令 / `python -m pytest tests/api -v` | 请求/响应记录、状态码、payload/schema 断言、写后读、数据一致性、cleanup/teardown | 缺 base URL/auth/fixture/seed/teardown/依赖/schema/结果面时阻塞 | pending |
|
|
11
11
|
| ACC-007 | 风险:非法和无权限输入 | 失败/边界路径可控 | api | n/a | 失败/边界 | 非法、空、重复、未登录、无权限、过期或 stale fixture 数据 | 给出清晰错误契约且不污染数据 | high | contract + security-review | `opentest-api` / 项目命令 / `python -m pytest tests/api -v` | 校验、鉴权/权限、重复/幂等、stale-state、错误 schema、敏感字段证据 | 无 | pending |
|
|
@@ -12,10 +12,12 @@ description: "OpenTest 阶段 4:执行自然语言验收、MCP 验收或真实
|
|
|
12
12
|
- `opentest/references/acceptance-evidence.md`
|
|
13
13
|
- `opentest/references/complete-testing-workflow.md`
|
|
14
14
|
- `opentest/references/test-surfaces.md`
|
|
15
|
+
- `opentest/references/android-app-testing.md`
|
|
15
16
|
- `opentest/references/web-browser-testing.md`
|
|
16
17
|
- `opentest/references/desktop-gui-testing.md`
|
|
17
18
|
- `opentest/references/api-testing.md`
|
|
18
19
|
- `opentest/templates/acceptance-template.md`
|
|
20
|
+
- `opentest/templates/android-app-acceptance-template.md`
|
|
19
21
|
- `opentest/templates/desktop-gui-acceptance-template.md`
|
|
20
22
|
- `opentest/templates/api-acceptance-template.md`
|
|
21
23
|
|
|
@@ -24,7 +26,7 @@ description: "OpenTest 阶段 4:执行自然语言验收、MCP 验收或真实
|
|
|
24
26
|
1. 读取矩阵、fixtures 和 `docs/opentest/acceptance/`。
|
|
25
27
|
2. 根据矩阵里的执行面选择验收工具。
|
|
26
28
|
3. `web-browser` 使用 `opentest-web-browser`:优先 Playwright MCP,失败时降级 Playwright CLI;稳定回归证据用 `@playwright/test`;视觉补充才用 Midscene。
|
|
27
|
-
4. `android-app`
|
|
29
|
+
4. `android-app` 使用 `opentest-android-app` 和 `android-midscene-pytest`;入口是 `python -m pytest tests_py -v`,收集 pytest、ADB 冒烟、Midscene HTML、截图、logcat、设备/App 元数据和可用的 `midscene_run` 日志。缺前置条件时标为 blocked。
|
|
28
30
|
5. `desktop-gui` 使用 `opentest-desktop-gui`:优先项目 GUI 自动化,视觉桌面/原生/RDP 流程用 `@midscene/computer`,并收集截图或录屏、GUI 操作日志、窗口/App 元数据和确定性回读。缺 display/RDP、App 启动、目标窗口标识、模型凭据或稳定结果面时标为 blocked。
|
|
29
31
|
6. `api` 使用 `opentest-api`:优先项目 API 命令;否则用 `pytest` + `httpx`/`requests`、schema 校验、fixtures、写后读和 cleanup/teardown 证据。
|
|
30
32
|
7. CRUD/数据变更执行 workflow 引用中的完整链路。
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: opentest-android-app
|
|
3
|
+
description: "OpenTest 的 Android App 执行面适配器。用于通过 android-midscene-pytest、ADB、模拟器/真机、截图、logcat 和 Midscene 报告规划、编写、运行与验收 Android APK/App GUI 工作流。"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenTest Android App
|
|
7
|
+
|
|
8
|
+
用于矩阵中的 `android-app` 执行面。
|
|
9
|
+
|
|
10
|
+
## 必读引用
|
|
11
|
+
|
|
12
|
+
- `opentest/references/android-app-testing.md`
|
|
13
|
+
- `opentest/templates/android-app-acceptance-template.md`
|
|
14
|
+
|
|
15
|
+
## 路由
|
|
16
|
+
|
|
17
|
+
1. 已安装 `android-midscene-pytest` 时,用它作为详细 Android 执行 skill。
|
|
18
|
+
2. 稳定 Android 资产放入 `test-asset-layout.md` 的固定目录:`tests/android/tests_py/`、`tests/android/midscene/`,以及 `scripts/opentest-run-android.ps1` 或现有 Android harness 命令。
|
|
19
|
+
3. 面向用户的执行入口应通过 pytest,通常是现有 harness 中的 `python -m pytest tests_py -v` 或仓库 Android 测试入口。
|
|
20
|
+
4. 只有模型环境变量齐全或排查 Midscene 层时,才运行 `npm run test:android`。
|
|
21
|
+
5. 缺 ADB、模拟器/真机、APK 路径、package name、模型凭据、fixture 数据或稳定结果面时,记录 `blocked`。
|
|
22
|
+
|
|
23
|
+
## 证据契约
|
|
24
|
+
|
|
25
|
+
PASS 必须包含 pytest 结果、ADB 冒烟、执行视觉自动化时的 Midscene HTML 报告、截图、logcat、设备/App 元数据,以及可用的 `midscene_run` 日志。静态截图本身不等于 Android App 验收。
|
|
@@ -14,6 +14,7 @@ description: "OpenTest 阶段 1:分析变更、风险和项目事实,生成
|
|
|
14
14
|
- `opentest/references/complete-testing-workflow.md`
|
|
15
15
|
- `opentest/references/test-asset-layout.md`
|
|
16
16
|
- `opentest/references/test-surfaces.md`
|
|
17
|
+
- `opentest/references/android-app-testing.md`
|
|
17
18
|
- `opentest/references/web-browser-testing.md`
|
|
18
19
|
- `opentest/references/desktop-gui-testing.md`
|
|
19
20
|
- `opentest/references/api-testing.md`
|
|
@@ -23,7 +24,7 @@ description: "OpenTest 阶段 1:分析变更、风险和项目事实,生成
|
|
|
23
24
|
1. 读取规则、需求/设计/请求/diff、现有命令和 detect 输出。
|
|
24
25
|
2. 把需求、流程、业务规则和风险当成验收来源;读取当前代码只用于发现项目事实,例如命令、路由、框架、fixtures 和 helper。
|
|
25
26
|
3. 数据写入、API、表单、文件或有状态流程默认套用 CRUD 基线和测试数据要求。
|
|
26
|
-
4. 分开判定执行面和证据层级。执行面只能是 `web-browser`、`android-app`、`desktop-gui` 或 `api`;Web 行必须写验收模式,原生桌面行用 `opentest-desktop-gui`,API 行用 `opentest-api`。
|
|
27
|
+
4. 分开判定执行面和证据层级。执行面只能是 `web-browser`、`android-app`、`desktop-gui` 或 `api`;Android 行用 `opentest-android-app`,Web 行必须写验收模式,原生桌面行用 `opentest-desktop-gui`,API 行用 `opentest-api`。
|
|
27
28
|
5. 生成需求先行矩阵,包含来源、行为、执行面、验收模式、证据层级、命令/工具、证据、缺口/阻塞、状态和固定资产目录。
|
|
28
29
|
6. 写入 `.opentest.yaml` 的 `plan`、`matrix`、`fixtures`。
|
|
29
30
|
7. 如存在 handoff,同步 plan/matrix/fixtures 路径,然后运行 `bash "$OPENTEST_GUARD" plan --apply`。
|
|
@@ -13,6 +13,7 @@ description: "OpenTest 阶段 3:按 targeted、fast、full、ci-like 或 pre-p
|
|
|
13
13
|
- `opentest/references/complete-testing-workflow.md`
|
|
14
14
|
- `opentest/references/test-asset-layout.md`
|
|
15
15
|
- `opentest/references/test-surfaces.md`
|
|
16
|
+
- `opentest/references/android-app-testing.md`
|
|
16
17
|
- `opentest/references/web-browser-testing.md`
|
|
17
18
|
- `opentest/references/desktop-gui-testing.md`
|
|
18
19
|
- `opentest/references/api-testing.md`
|
|
@@ -28,7 +29,7 @@ description: "OpenTest 阶段 3:按 targeted、fast、full、ci-like 或 pre-p
|
|
|
28
29
|
## 步骤
|
|
29
30
|
|
|
30
31
|
1. 读取 `run_mode`、矩阵、fixtures、必需证据和固定资产目录。
|
|
31
|
-
2. 根据矩阵执行面和验收模式选择命令/工具:`web-browser` 走 MCP/CLI 或 `npx playwright test`,`android-app` 走 `python -m pytest tests_py -v`;只有模型环境变量齐全或排查 Midscene 层时才跑 `npm run test:android`;`desktop-gui` 走 `opentest-desktop-gui
|
|
32
|
+
2. 根据矩阵执行面和验收模式选择命令/工具:`web-browser` 走 MCP/CLI 或 `npx playwright test`,`android-app` 走 `opentest-android-app` 或 `python -m pytest tests_py -v`;只有模型环境变量齐全或排查 Midscene 层时才跑 `npm run test:android`;`desktop-gui` 走 `opentest-desktop-gui`,`api` 走 `opentest-api` 或 `python -m pytest tests/api -v`。
|
|
32
33
|
3. 优先使用项目命令;没有代码级命令时用 `python -m pytest`。
|
|
33
34
|
4. 覆盖率优先用 `python -m pytest --cov=. --cov-report=term-missing`。
|
|
34
35
|
5. 除非矩阵写明不适用,否则必须有冒烟证据。
|
package/package.json
CHANGED
package/scripts/smoke-test.js
CHANGED
|
@@ -222,6 +222,8 @@ function assertRequirementFirstAcceptanceContracts() {
|
|
|
222
222
|
|
|
223
223
|
function assertTestSurfaceContracts() {
|
|
224
224
|
const manifestText = readFileSync('assets/manifest.json', 'utf8');
|
|
225
|
+
const englishRouter = readFileSync('assets/skills/opentest/SKILL.md', 'utf8');
|
|
226
|
+
const chineseRouter = readFileSync('assets/skills-zh/opentest/SKILL.md', 'utf8');
|
|
225
227
|
const englishSurfaces = readRequiredText('assets/skills/opentest/references/test-surfaces.md', '[SURFACE] missing English test-surfaces reference');
|
|
226
228
|
const chineseSurfaces = readRequiredText('assets/skills-zh/opentest/references/test-surfaces.md', '[SURFACE] missing Chinese test-surfaces reference');
|
|
227
229
|
const englishMatrixFormat = readFileSync('assets/skills/opentest/references/matrix-format.md', 'utf8');
|
|
@@ -245,6 +247,8 @@ function assertTestSurfaceContracts() {
|
|
|
245
247
|
const surfaces = ['web-browser', 'android-app', 'desktop-gui', 'api'];
|
|
246
248
|
|
|
247
249
|
assert(manifestText.includes('opentest/references/test-surfaces.md'), '[SURFACE] manifest must ship test-surfaces reference');
|
|
250
|
+
assert(englishRouter.includes('single user entry') && englishRouter.includes('matrix surface') && englishRouter.includes('Ask only when') && englishRouter.includes('surface cannot be inferred'), '[SURFACE] English router must keep single-entry automatic adapter routing');
|
|
251
|
+
assert(chineseRouter.includes('用户只触发 OpenTest') && chineseRouter.includes('按矩阵执行面自动选择 adapter') && chineseRouter.includes('不要让用户手动选择 adapter'), '[SURFACE] Chinese router must keep single-entry automatic adapter routing');
|
|
248
252
|
|
|
249
253
|
for (const surface of surfaces) {
|
|
250
254
|
assert(englishSurfaces.includes(surface), `[SURFACE] English test-surfaces missing ${surface}`);
|
|
@@ -253,6 +257,8 @@ function assertTestSurfaceContracts() {
|
|
|
253
257
|
assert(chineseMatrixFormat.includes(surface), `[SURFACE] Chinese matrix-format missing ${surface}`);
|
|
254
258
|
assert(englishMatrix.includes(surface), `[SURFACE] English matrix template missing ${surface}`);
|
|
255
259
|
assert(chineseMatrix.includes(surface), `[SURFACE] Chinese matrix template missing ${surface}`);
|
|
260
|
+
assert(englishRouter.includes(surface), `[SURFACE] English router missing ${surface}`);
|
|
261
|
+
assert(chineseRouter.includes(surface), `[SURFACE] Chinese router missing ${surface}`);
|
|
256
262
|
}
|
|
257
263
|
|
|
258
264
|
assert(englishSurfaces.includes('Do not invent a fifth primary surface'), '[SURFACE] English reference must forbid fifth primary surface');
|
|
@@ -263,18 +269,24 @@ function assertTestSurfaceContracts() {
|
|
|
263
269
|
assert(chineseSurfaces.includes('Midscene YAML runner') && chineseSurfaces.includes('MIDSCENE_MCP_ANDROID_MODE=true') && chineseSurfaces.includes('midscene-python'), '[SURFACE] Chinese Android route must document YAML, MCP, and midscene-python boundaries');
|
|
264
270
|
assert(englishSurfaces.includes('npm run test:android') && englishSurfaces.includes('midscene_run/log/ai-call.log') && englishSurfaces.includes('midscene_run/report/*.html'), '[SURFACE] English Android route must document layered run and failure artifacts');
|
|
265
271
|
assert(chineseSurfaces.includes('npm run test:android') && chineseSurfaces.includes('midscene_run/log/ai-call.log') && chineseSurfaces.includes('midscene_run/report/*.html'), '[SURFACE] Chinese Android route must document layered run and failure artifacts');
|
|
272
|
+
assert(englishSurfaces.includes('opentest-android-app') && englishSurfaces.includes('android-app-testing.md'), '[SURFACE] English Android route must expose opentest-android-app adapter');
|
|
273
|
+
assert(chineseSurfaces.includes('opentest-android-app') && chineseSurfaces.includes('android-app-testing.md'), '[SURFACE] Chinese Android route must expose opentest-android-app adapter');
|
|
266
274
|
assert(englishSurfaces.includes('opentest-desktop-gui') && englishSurfaces.includes('@midscene/computer') && englishSurfaces.includes('deterministic read/assert changed result'), '[SURFACE] English desktop route must document opentest-desktop-gui and deterministic read-back');
|
|
267
275
|
assert(chineseSurfaces.includes('opentest-desktop-gui') && chineseSurfaces.includes('@midscene/computer') && chineseSurfaces.includes('确定性 read/assert changed result'), '[SURFACE] Chinese desktop route must document opentest-desktop-gui and deterministic read-back');
|
|
268
276
|
assert(englishSurfaces.includes('opentest-api') && englishSurfaces.includes('httpx') && englishSurfaces.includes('read-after-write'), '[SURFACE] English API route must document opentest-api and read-after-write');
|
|
269
277
|
assert(chineseSurfaces.includes('opentest-api') && chineseSurfaces.includes('httpx') && chineseSurfaces.includes('写后读'), '[SURFACE] Chinese API route must document opentest-api and read-after-write');
|
|
270
278
|
assert(englishWorkflow.includes('Execution Surfaces') && englishWorkflow.includes('android-midscene-pytest'), '[SURFACE] English workflow must include execution surface rules');
|
|
271
279
|
assert(chineseWorkflow.includes('执行面') && chineseWorkflow.includes('android-midscene-pytest'), '[SURFACE] Chinese workflow must include execution surface rules');
|
|
280
|
+
assert(englishWorkflow.includes('opentest-android-app') && englishWorkflow.includes('android-app-testing.md'), '[SURFACE] English workflow must include Android app adapter route');
|
|
281
|
+
assert(chineseWorkflow.includes('opentest-android-app') && chineseWorkflow.includes('android-app-testing.md'), '[SURFACE] Chinese workflow must include Android app adapter route');
|
|
272
282
|
assert(englishWorkflow.includes('opentest-desktop-gui') && englishWorkflow.includes('@midscene/computer'), '[SURFACE] English workflow must include desktop GUI route');
|
|
273
283
|
assert(chineseWorkflow.includes('opentest-desktop-gui') && chineseWorkflow.includes('@midscene/computer'), '[SURFACE] Chinese workflow must include desktop GUI route');
|
|
274
284
|
assert(englishWorkflow.includes('opentest-api') && englishWorkflow.includes('httpx'), '[SURFACE] English workflow must include API route');
|
|
275
285
|
assert(chineseWorkflow.includes('opentest-api') && chineseWorkflow.includes('httpx'), '[SURFACE] Chinese workflow must include API route');
|
|
276
286
|
assert(englishHeuristics.includes('Execution Surface Selection') && englishHeuristics.includes('android-midscene-pytest'), '[SURFACE] English heuristics must include surface selection');
|
|
277
287
|
assert(chineseHeuristics.includes('执行面选择') && chineseHeuristics.includes('android-midscene-pytest'), '[SURFACE] Chinese heuristics must include surface selection');
|
|
288
|
+
assert(englishHeuristics.includes('opentest-android-app'), '[SURFACE] English heuristics must include Android app adapter');
|
|
289
|
+
assert(chineseHeuristics.includes('opentest-android-app'), '[SURFACE] Chinese heuristics must include Android app adapter');
|
|
278
290
|
assert(englishHeuristics.includes('opentest-desktop-gui') && englishHeuristics.includes('@midscene/computer'), '[SURFACE] English heuristics must include desktop GUI route');
|
|
279
291
|
assert(chineseHeuristics.includes('opentest-desktop-gui') && chineseHeuristics.includes('@midscene/computer'), '[SURFACE] Chinese heuristics must include desktop GUI route');
|
|
280
292
|
assert(englishHeuristics.includes('opentest-api') && englishHeuristics.includes('httpx'), '[SURFACE] English heuristics must include API route');
|
|
@@ -292,6 +304,8 @@ function assertTestSurfaceContracts() {
|
|
|
292
304
|
assert(chineseRun.includes('npm run test:android') && chineseRun.includes('模型环境变量'), '[SURFACE] Chinese run must gate npm run test:android behind model env/debugging');
|
|
293
305
|
assert(englishAccept.includes('android-midscene-pytest') && englishAccept.includes('ADB smoke') && englishAccept.includes('midscene_run'), '[SURFACE] English accept must route Android through android-midscene-pytest');
|
|
294
306
|
assert(chineseAccept.includes('android-midscene-pytest') && chineseAccept.includes('ADB 冒烟') && chineseAccept.includes('midscene_run'), '[SURFACE] Chinese accept must route Android through android-midscene-pytest');
|
|
307
|
+
assert(englishAccept.includes('opentest-android-app'), '[SURFACE] English accept must route Android through opentest-android-app');
|
|
308
|
+
assert(chineseAccept.includes('opentest-android-app'), '[SURFACE] Chinese accept must route Android through opentest-android-app');
|
|
295
309
|
assert(englishAccept.includes('opentest-desktop-gui') && englishAccept.includes('@midscene/computer'), '[SURFACE] English accept must route desktop GUI through opentest-desktop-gui');
|
|
296
310
|
assert(chineseAccept.includes('opentest-desktop-gui') && chineseAccept.includes('@midscene/computer'), '[SURFACE] Chinese accept must route desktop GUI through opentest-desktop-gui');
|
|
297
311
|
assert(englishAccept.includes('opentest-api') && englishAccept.includes('httpx') && englishAccept.includes('cleanup/teardown'), '[SURFACE] English accept must route API through opentest-api');
|
|
@@ -299,6 +313,8 @@ function assertTestSurfaceContracts() {
|
|
|
299
313
|
|
|
300
314
|
assert(englishMatrix.includes('Execution surface') && englishMatrix.includes('Evidence layer') && englishMatrix.includes('Midscene HTML report') && englishMatrix.includes('python -m pytest tests_py -v') && englishMatrix.includes('ADB smoke') && englishMatrix.includes('midscene_run'), '[SURFACE] English matrix template must include execution surface and Android artifacts');
|
|
301
315
|
assert(chineseMatrix.includes('执行面') && chineseMatrix.includes('证据层级') && chineseMatrix.includes('Midscene HTML 报告') && chineseMatrix.includes('python -m pytest tests_py -v') && chineseMatrix.includes('ADB 冒烟') && chineseMatrix.includes('midscene_run'), '[SURFACE] Chinese matrix template must include execution surface and Android artifacts');
|
|
316
|
+
assert(englishMatrix.includes('opentest-android-app'), '[SURFACE] English matrix template must include Android app adapter');
|
|
317
|
+
assert(chineseMatrix.includes('opentest-android-app'), '[SURFACE] Chinese matrix template must include Android app adapter');
|
|
302
318
|
assert(englishMatrix.includes('opentest-desktop-gui') && englishMatrix.includes('@midscene/computer') && englishMatrix.includes('deterministic read-back'), '[SURFACE] English matrix template must include desktop GUI artifacts');
|
|
303
319
|
assert(chineseMatrix.includes('opentest-desktop-gui') && chineseMatrix.includes('@midscene/computer') && chineseMatrix.includes('确定性回读'), '[SURFACE] Chinese matrix template must include desktop GUI artifacts');
|
|
304
320
|
assert(englishMatrix.includes('opentest-api') && englishMatrix.includes('python -m pytest tests/api -v') && englishMatrix.includes('payload/schema assertion') && englishMatrix.includes('cleanup/teardown'), '[SURFACE] English matrix template must include API artifacts');
|
|
@@ -309,6 +325,37 @@ function assertTestSurfaceContracts() {
|
|
|
309
325
|
assert(chineseAcceptance.includes('执行面: web-browser | android-app | desktop-gui | api') && chineseAcceptance.includes('证据层级'), '[SURFACE] Chinese acceptance template must include surface and evidence layer fields');
|
|
310
326
|
}
|
|
311
327
|
|
|
328
|
+
function assertAndroidAppContracts() {
|
|
329
|
+
const manifestText = readFileSync('assets/manifest.json', 'utf8');
|
|
330
|
+
const englishSkill = readRequiredText('assets/skills/opentest-android-app/SKILL.md', '[ANDROID] missing English Android app skill');
|
|
331
|
+
const chineseSkill = readRequiredText('assets/skills-zh/opentest-android-app/SKILL.md', '[ANDROID] missing Chinese Android app skill');
|
|
332
|
+
const englishReference = readRequiredText('assets/skills/opentest/references/android-app-testing.md', '[ANDROID] missing English Android app reference');
|
|
333
|
+
const chineseReference = readRequiredText('assets/skills-zh/opentest/references/android-app-testing.md', '[ANDROID] missing Chinese Android app reference');
|
|
334
|
+
const englishTemplate = readRequiredText('assets/skills/opentest/templates/android-app-acceptance-template.md', '[ANDROID] missing English Android app template');
|
|
335
|
+
const chineseTemplate = readRequiredText('assets/skills-zh/opentest/templates/android-app-acceptance-template.md', '[ANDROID] missing Chinese Android app template');
|
|
336
|
+
const englishPlan = readFileSync('assets/skills/opentest-plan/SKILL.md', 'utf8');
|
|
337
|
+
const chinesePlan = readFileSync('assets/skills-zh/opentest-plan/SKILL.md', 'utf8');
|
|
338
|
+
const englishRun = readFileSync('assets/skills/opentest-run/SKILL.md', 'utf8');
|
|
339
|
+
const chineseRun = readFileSync('assets/skills-zh/opentest-run/SKILL.md', 'utf8');
|
|
340
|
+
const englishAccept = readFileSync('assets/skills/opentest-accept/SKILL.md', 'utf8');
|
|
341
|
+
const chineseAccept = readFileSync('assets/skills-zh/opentest-accept/SKILL.md', 'utf8');
|
|
342
|
+
|
|
343
|
+
assert(manifestText.includes('opentest-android-app/SKILL.md'), '[ANDROID] manifest must ship opentest-android-app skill');
|
|
344
|
+
assert(manifestText.includes('opentest/references/android-app-testing.md'), '[ANDROID] manifest must ship Android app reference');
|
|
345
|
+
assert(manifestText.includes('opentest/templates/android-app-acceptance-template.md'), '[ANDROID] manifest must ship Android app acceptance template');
|
|
346
|
+
|
|
347
|
+
assert(englishSkill.includes('android-midscene-pytest') && englishSkill.includes('tests/android/tests_py/') && englishSkill.includes('npm run test:android'), '[ANDROID] English Android skill must route layout and Midscene');
|
|
348
|
+
assert(chineseSkill.includes('android-midscene-pytest') && chineseSkill.includes('tests/android/tests_py/') && chineseSkill.includes('npm run test:android'), '[ANDROID] Chinese Android skill must route layout and Midscene');
|
|
349
|
+
assert(englishReference.includes('Adapter Boundary') && englishReference.includes('tests/android/midscene/') && englishReference.includes('Do not mark Android app acceptance as PASS from a static screenshot alone'), '[ANDROID] English reference must define adapter boundary, layout, and no-static-screenshot rule');
|
|
350
|
+
assert(chineseReference.includes('适配边界') && chineseReference.includes('tests/android/midscene/') && chineseReference.includes('不得只凭静态截图'), '[ANDROID] Chinese reference must define adapter boundary, layout, and no-static-screenshot rule');
|
|
351
|
+
assert(englishTemplate.includes('tool route: opentest-android-app | android-midscene-pytest') && englishTemplate.includes('ADB smoke'), '[ANDROID] English template must include route and ADB evidence');
|
|
352
|
+
assert(chineseTemplate.includes('工具路线: opentest-android-app | android-midscene-pytest') && chineseTemplate.includes('ADB 冒烟'), '[ANDROID] Chinese template must include route and ADB evidence');
|
|
353
|
+
|
|
354
|
+
for (const content of [englishPlan, chinesePlan, englishRun, chineseRun, englishAccept, chineseAccept]) {
|
|
355
|
+
assert(content.includes('opentest/references/android-app-testing.md'), '[ANDROID] plan/run/accept skills must read Android app reference');
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
312
359
|
function assertWebBrowserContracts() {
|
|
313
360
|
const manifestText = readFileSync('assets/manifest.json', 'utf8');
|
|
314
361
|
const englishSkill = readRequiredText('assets/skills/opentest-web-browser/SKILL.md', '[WEB] missing English web-browser skill');
|
|
@@ -879,6 +926,7 @@ assertPrepublishGateCoversManifestAssets();
|
|
|
879
926
|
assertDefaultPytestContracts();
|
|
880
927
|
assertRequirementFirstAcceptanceContracts();
|
|
881
928
|
assertTestSurfaceContracts();
|
|
929
|
+
assertAndroidAppContracts();
|
|
882
930
|
assertWebBrowserContracts();
|
|
883
931
|
assertDesktopGuiContracts();
|
|
884
932
|
assertApiContracts();
|