@educa-corp/sdd-framework 0.9.6 → 0.9.8
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/bin/lint-trace.js +4 -4
- package/bin/qc-base-map.json +13 -11
- package/bin/self-check.js +497 -16
- package/bin/trace-schema.json +3226 -2656
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/amend-prd.md +7 -1
- package/core/commands/debug.md +8 -2
- package/core/commands/define-product.md +38 -1
- package/core/commands/dev-gen-test.md +9 -3
- package/core/commands/dev-run-test.md +8 -2
- package/core/commands/dev-smoke-test.md +7 -1
- package/core/commands/extend-prd.md +7 -1
- package/core/commands/fix-bug.md +11 -5
- package/core/commands/generate-architecture.md +9 -1
- package/core/commands/generate-bdd.md +45 -5
- package/core/commands/generate-code.md +43 -4
- package/core/commands/generate-design-spec.md +7 -1
- package/core/commands/generate-prd.md +9 -1
- package/core/commands/generate-spec-manifest.md +7 -1
- package/core/commands/generate-tech-docs.md +41 -1
- package/core/commands/learn.md +7 -1
- package/core/commands/map-testids.md +11 -5
- package/core/commands/propose-scenario.md +7 -1
- package/core/commands/qc-analyze.md +12 -6
- package/core/commands/qc-automation-assess.md +356 -0
- package/core/commands/qc-design-script.md +430 -0
- package/core/commands/qc-design-test.md +98 -20
- package/core/commands/qc-plan.md +9 -3
- package/core/commands/qc-report.md +92 -77
- package/core/commands/qc-review-script.md +342 -0
- package/core/commands/{qc-review.md → qc-review-testcase.md} +86 -54
- package/core/commands/qc-run-manualtest.md +401 -0
- package/core/commands/qc-run-script.md +421 -0
- package/core/commands/refine-prd.md +7 -1
- package/core/commands/report-bug.md +9 -3
- package/core/commands/review-code.md +9 -3
- package/core/commands/review-context.md +11 -3
- package/core/commands/review-tech-docs.md +11 -3
- package/core/commands/setup-ai-first.md +7 -1
- package/core/commands/validate-traces.md +10 -4
- package/core/modules/qc-playwright-ts/module.yaml +13 -0
- package/core/modules/qc-playwright-ts/stack-profile.yaml +99 -0
- package/core/modules/qc-wdio-appium/module.yaml +20 -0
- package/core/modules/qc-wdio-appium/stack-profile.yaml +107 -0
- package/core/rules/workflow.md +2 -2
- package/core/skills/qc/_shared/self-review-principles.md +2 -2
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
- package/core/skills/qc/qa-analyst/data-flow.md +1 -1
- package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
- package/core/skills/qc/qa-automation-assess/matrix.md +123 -0
- package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
- package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
- package/core/skills/qc/{qa-runner → qa-designer}/exploratory/session.md +8 -2
- package/core/skills/qc/qa-designer/functional/api.md +2 -2
- package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
- package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
- package/core/skills/qc/qa-designer/functional/job.md +128 -0
- package/core/skills/qc/qa-designer/integration/api.md +2 -2
- package/core/skills/qc/qa-designer/integration/db.md +2 -2
- package/core/skills/qc/qa-designer/integration/gui.md +1 -1
- package/core/skills/qc/qa-designer/integration/{kafka.md → queue.md} +21 -5
- package/core/skills/qc/qa-designer/non-functional.md +1 -1
- package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +17 -0
- package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +28 -6
- package/core/skills/qc/qa-reviewer/script/_shared/review-rules.md +121 -0
- package/core/skills/qc/qa-reviewer/script/api/auth.md +49 -0
- package/core/skills/qc/qa-reviewer/script/api/endpoint.md +89 -0
- package/core/skills/qc/qa-reviewer/script/api/security.md +46 -0
- package/core/skills/qc/qa-reviewer/script/exploratory.md +3 -3
- package/core/skills/qc/qa-reviewer/script/mobile/e2e.md +41 -0
- package/core/skills/qc/qa-reviewer/script/mobile/functional.md +90 -0
- package/core/skills/qc/qa-reviewer/script/mobile/integration.md +41 -0
- package/core/skills/qc/qa-reviewer/script/mobile/non-functional.md +43 -0
- package/core/skills/qc/qa-reviewer/script/web/e2e.md +46 -0
- package/core/skills/qc/qa-reviewer/script/web/functional.md +111 -0
- package/core/skills/qc/qa-reviewer/script/web/integration.md +46 -0
- package/core/skills/qc/qa-reviewer/script/web/non-functional.md +49 -0
- package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +1 -1
- package/core/skills/qc/qa-reviewer/shared/review-file-template.md +29 -10
- package/core/skills/qc/qa-reviewer/test-case/e2e.md +2 -2
- package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/functional.md +2 -2
- package/core/skills/qc/qa-reviewer/test-case/integration.md +2 -2
- package/core/skills/qc/qa-reviewer/test-case/non-functional.md +2 -2
- package/core/skills/qc/qa-script-designer/_shared/api-conventions.md +94 -0
- package/core/skills/qc/qa-script-designer/_shared/file-naming-and-folders.md +109 -0
- package/core/skills/qc/qa-script-designer/_shared/mobile-conventions.md +196 -0
- package/core/skills/qc/qa-script-designer/_shared/web-conventions.md +257 -0
- package/core/skills/qc/qa-script-designer/api/auth.md +43 -0
- package/core/skills/qc/qa-script-designer/api/endpoint.md +61 -0
- package/core/skills/qc/qa-script-designer/api/security.md +41 -0
- package/core/skills/qc/qa-script-designer/mobile/e2e.md +35 -0
- package/core/skills/qc/qa-script-designer/mobile/functional/feature.md +32 -0
- package/core/skills/qc/qa-script-designer/mobile/functional/screen.md +42 -0
- package/core/skills/qc/qa-script-designer/mobile/integration.md +39 -0
- package/core/skills/qc/qa-script-designer/mobile/non-functional.md +39 -0
- package/core/skills/qc/qa-script-designer/web/e2e.md +36 -0
- package/core/skills/qc/qa-script-designer/web/functional/api.md +39 -0
- package/core/skills/qc/qa-script-designer/web/functional/gui-feature.md +34 -0
- package/core/skills/qc/qa-script-designer/web/functional/gui-screen.md +42 -0
- package/core/skills/qc/qa-script-designer/web/integration.md +43 -0
- package/core/skills/qc/qa-script-designer/web/non-functional.md +42 -0
- package/core/skills/qc/qa-script-runner/mobile/run.md +38 -0
- package/core/skills/qc/qa-script-runner/report.md +41 -0
- package/core/skills/qc/qa-script-runner/web/run.md +48 -0
- package/core/steps/context-loader.md +1 -1
- package/core/steps/gate.md +7 -1
- package/core/steps/qc-scope.md +45 -2
- package/core/steps/qc-stamp.md +4 -4
- package/core/steps/report-footer.md +10 -9
- package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +13 -12
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
- package/docs/02-concepts/traceability.md +1 -1
- package/docs/03-guides/developer.md +1 -1
- package/docs/03-guides/tester-qa.md +40 -11
- package/docs/04-reference/commands.md +4 -2
- package/docs/04-reference/modules.md +2 -1
- package/docs/04-reference/trace-schema.md +4 -4
- package/docs/explain/17-qc-design-test.md +5 -5
- package/docs/explain/18-qc-review.md +42 -20
- package/docs/explain/19-qc-run-test.md +13 -10
- package/docs/explain/20-qc-report.md +3 -3
- package/docs/explain/23-fix-bug.md +2 -2
- package/docs/explain/README.md +2 -2
- package/docs/plans/qc-surgery/01-checklist.md +86 -21
- package/docs/plans/qc-surgery/PLAN_v2.md +295 -0
- package/docs/plans/qc-surgery/exec-S-ap-stack-typescript.md +420 -0
- package/docs/plans/qc-surgery/exec-S0-guard-cam-stack-cu.md +400 -0
- package/docs/plans/qc-surgery/exec-S1-hai-module-thay-qc-playwright.md +267 -0
- package/docs/plans/qc-surgery/exec-S2-qa-runner-thanh-script-designer-runner.md +340 -0
- package/docs/plans/qc-surgery/exec-S3-viet-lai-tieu-chi-review-script.md +322 -0
- package/docs/plans/qc-surgery/exec-S5-an-theo-don-dau-vet-stack-cu.md +292 -0
- package/package.json +1 -1
- package/core/commands/qc-run-test.md +0 -561
- package/core/modules/qc-playwright/stack-profile.yaml +0 -66
- package/core/skills/qc/qa-reviewer/script/e2e.md +0 -95
- package/core/skills/qc/qa-reviewer/script/functional.md +0 -109
- package/core/skills/qc/qa-reviewer/script/integration.md +0 -99
- package/core/skills/qc/qa-reviewer/script/non-functional.md +0 -134
- package/core/skills/qc/qa-runner/e2e.md +0 -49
- package/core/skills/qc/qa-runner/functional/api.md +0 -35
- package/core/skills/qc/qa-runner/functional/gui-feature.md +0 -57
- package/core/skills/qc/qa-runner/functional/gui-screen.md +0 -61
- package/core/skills/qc/qa-runner/integration.md +0 -47
- package/core/skills/qc/qa-runner/non-functional.md +0 -49
- package/core/skills/qc/qa-runner/report/report.md +0 -37
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gen Script — API (dùng chung mọi platform)
|
|
7
|
+
|
|
8
|
+
Skill sinh script test API thuần (không qua UI), dùng `@playwright/test` `APIRequestContext`.
|
|
9
|
+
Test API **không phân biệt platform gọi nó là web hay mobile** — backend là một, nên file này
|
|
10
|
+
dùng chung cho cả pipeline web và mobile (không có bản mobile riêng).
|
|
11
|
+
|
|
12
|
+
## Khi nào trigger
|
|
13
|
+
- Convert TC API (output `qa-designer/functional/api.md`), TC Automatable=Y, `TC_<FEATURE>.md` đã approve.
|
|
14
|
+
|
|
15
|
+
## Khi KHÔNG trigger
|
|
16
|
+
- Test qua UI → `functional/gui-screen.md`/mobile tương ứng · tích hợp đa thành phần → `integration.md`
|
|
17
|
+
|
|
18
|
+
## Quy ước riêng (ngoài Locator/Wait/Assertion chung — API không có locator)
|
|
19
|
+
- Client API gói trong fixture Playwright (`test.extend`) — base URL + auth header từ
|
|
20
|
+
`process.env.*`, KHÔNG rải request rời rạc trong test.
|
|
21
|
+
- Assertion: status code **và** field response (JSON path) — không chỉ status code.
|
|
22
|
+
- Test độc lập: tạo data qua API → dùng → cleanup qua API (`test.afterEach`), không phụ thuộc
|
|
23
|
+
thứ tự chạy.
|
|
24
|
+
|
|
25
|
+
## Phase 1 — Clarify
|
|
26
|
+
Base URL/auth/role theo `TEST_DATA_PLAN.md`; client fixture đã có chưa.
|
|
27
|
+
|
|
28
|
+
## Phase 2 — Generate
|
|
29
|
+
Mỗi TC Automatable=Y → 1 test gọi endpoint với request từ `TEST_DATA_PLAN.md`; assert status +
|
|
30
|
+
field. Nhóm `test.describe`: happy → validation → auth → not-found → edge.
|
|
31
|
+
|
|
32
|
+
## Phase 3 — Self-Verify
|
|
33
|
+
```bash
|
|
34
|
+
npx tsc --noEmit
|
|
35
|
+
npx playwright test automation/tests/{TICKET-ID}/functional/api/<feature>-<scenario>.spec.ts --list
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Output
|
|
39
|
+
`automation/tests/{TICKET-ID}/functional/api/<feature>-<scenario>.spec.ts` + client fixture (`fixtures/api-client.ts`) nếu mới.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gen Script — Web Functional GUI Feature (đa màn hình)
|
|
7
|
+
|
|
8
|
+
Skill sinh script cho feature span ≥2 màn. **Đọc `_shared/web-conventions.md` trước.**
|
|
9
|
+
|
|
10
|
+
## Khi nào trigger
|
|
11
|
+
- Convert TC feature đa-màn (output `qa-designer/functional/gui-feature.md`), TC Automatable=Y,
|
|
12
|
+
`TC_<FEATURE>.md` đã approve.
|
|
13
|
+
|
|
14
|
+
## Khi KHÔNG trigger
|
|
15
|
+
- Gọn 1 màn → `functional/gui-screen.md` · đầu-cuối xuyên hệ thống ngoài → `e2e.md`
|
|
16
|
+
|
|
17
|
+
## Phase 1 — Clarify
|
|
18
|
+
Liệt kê các màn/Page Object cần; state truyền giữa màn (giá trị nhập màn A hiển thị đúng ở
|
|
19
|
+
màn B); data từ `TEST_DATA_PLAN.md`.
|
|
20
|
+
|
|
21
|
+
## Phase 2 — Generate
|
|
22
|
+
Mỗi Page Object action điều hướng **trả về PO màn kế tiếp** (`return new NextPage(this.page)`)
|
|
23
|
+
— test chuỗi `const p2 = await p1.doAction()`. Phủ đúng TC Automatable=Y (đếm khớp
|
|
24
|
+
`AUTOMATION_ASSESSMENT.md`). Assert **sau mỗi chặng có side-effect**, không chỉ ở bước cuối
|
|
25
|
+
(xem Common Pitfall #4 trong `_shared/web-conventions.md`).
|
|
26
|
+
|
|
27
|
+
## Phase 3 — Self-Verify
|
|
28
|
+
```bash
|
|
29
|
+
npx tsc --noEmit
|
|
30
|
+
npx playwright test automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts --list
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Output
|
|
34
|
+
Script + nhiều Page Object (mỗi màn) trong `automation/pages/{TICKET-ID}/...`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gen Script — Web Functional GUI Screen (1 màn hình)
|
|
7
|
+
|
|
8
|
+
Skill sinh script cho 1 màn hình đơn. **Đọc `_shared/web-conventions.md` trước** (Locator
|
|
9
|
+
Strategy, Page Object, Wait/Assertion, Common Pitfalls) — file này chỉ có phần sinh-script
|
|
10
|
+
riêng của layer.
|
|
11
|
+
|
|
12
|
+
## Khi nào trigger
|
|
13
|
+
- Convert TC functional 1 màn (output `qa-designer/functional/gui-screen.md`), TC đã
|
|
14
|
+
`Automatable: Y` (từ `AUTOMATION_ASSESSMENT.md`) và `TC_<FEATURE>.md` đã approve.
|
|
15
|
+
|
|
16
|
+
## Khi KHÔNG trigger
|
|
17
|
+
- Feature đa-màn → `functional/gui-feature.md` · API thuần → `functional/api.md`
|
|
18
|
+
|
|
19
|
+
## Phase 1 — Clarify
|
|
20
|
+
Đọc `TC_<FEATURE>.md` (chỉ TC Automatable=Y) + `TEST_DATA_PLAN.md`. Page Object cho màn này đã có
|
|
21
|
+
chưa → tạo mới nếu chưa. Đọc bảng test-id §4.5.6 tech-doc gộp cho màn này.
|
|
22
|
+
|
|
23
|
+
## Phase 2 — Generate
|
|
24
|
+
**Phủ đúng các TC Automatable=Y** — đếm TC trong `AUTOMATION_ASSESSMENT.md` có `Y` cho màn
|
|
25
|
+
này = số `test(...)` phải sinh (không hơn, không kém). TC Automatable=Y nhưng phát hiện rào
|
|
26
|
+
cản kỹ thuật lúc viết → `test.fixme('TC_xxx — {lý do}')` + ghi `IMPROVE-xxx` (xem command
|
|
27
|
+
`/qc-design-script` §Testability Improvement List), không âm thầm bỏ qua.
|
|
28
|
+
|
|
29
|
+
Nhóm theo `test.describe`: GUI (hiển thị/enable-disable) → Functional (input/validation/action).
|
|
30
|
+
Data lấy từ `TEST_DATA_PLAN.md` (theo `TD-xxx` map ở cột "Dùng bởi").
|
|
31
|
+
|
|
32
|
+
## Phase 3 — Self-Verify (trước khi báo Human approve)
|
|
33
|
+
```bash
|
|
34
|
+
npx tsc --noEmit
|
|
35
|
+
npx playwright test automation/tests/{TICKET-ID}/<screen>.spec.ts --list
|
|
36
|
+
```
|
|
37
|
+
Số test liệt kê = số TC Automatable=Y của màn này. Thiếu → quay lại Phase 2.
|
|
38
|
+
|
|
39
|
+
## Output
|
|
40
|
+
`automation/tests/{TICKET-ID}/<screen-slug>.spec.ts` +
|
|
41
|
+
`automation/pages/{TICKET-ID}/<screen-slug>.page.ts` (mới nếu cần —
|
|
42
|
+
xem quy tắc slug/kiểm tra tồn tại trước khi tạo ở `_shared/file-naming-and-folders.md`).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gen Script — Web Integration (API↔DB↔service↔queue↔UI)
|
|
7
|
+
|
|
8
|
+
**Đọc `_shared/web-conventions.md` trước.**
|
|
9
|
+
|
|
10
|
+
## Khi nào trigger
|
|
11
|
+
- Convert TC integration (output `qa-designer/integration/*`), TC Automatable=Y.
|
|
12
|
+
|
|
13
|
+
## Khi KHÔNG trigger
|
|
14
|
+
- Chỉ 1 endpoint/UI đơn → `functional/*` · hành trình đầu-cuối → `e2e.md`
|
|
15
|
+
|
|
16
|
+
## Quy ước riêng — không mock (nguyên tắc quan trọng nhất của integration test)
|
|
17
|
+
Mock API/DB trong integration test biến nó thành **unit test trá hình** — không còn verify
|
|
18
|
+
được tích hợp thật. Luôn gọi network/DB thật trên môi trường test:
|
|
19
|
+
- **GUI↔Backend**: `page.waitForResponse(url)` để capture request/response thật khi thao tác UI.
|
|
20
|
+
- **DB**: client DB thật (qua fixture, connection string từ `process.env.*`), verify trực tiếp
|
|
21
|
+
bảng/cột — không chỉ verify qua UI hiển thị đúng (UI có thể cache sai mà DB đã đúng, hoặc
|
|
22
|
+
ngược lại).
|
|
23
|
+
- **Kafka/queue**: producer/consumer thật trong fixture, verify payload nhận được, không
|
|
24
|
+
giả lập message.
|
|
25
|
+
|
|
26
|
+
## Phase 1 — Clarify
|
|
27
|
+
Chuỗi tích hợp & chặng cần verify; client/fixture (API/DB/Kafka) đã có chưa; data từ
|
|
28
|
+
`TEST_DATA_PLAN.md`.
|
|
29
|
+
|
|
30
|
+
## Phase 2 — Generate
|
|
31
|
+
Mỗi TC → 1 test theo data flow: action → verify từng chặng (response → DB → event → UI).
|
|
32
|
+
Nhóm: happy → contract-negative (4xx/5xx + UI hiển thị đúng message) → concurrency (mô tả rõ
|
|
33
|
+
số request đồng thời, assert không race condition — vd unique constraint giữ nguyên).
|
|
34
|
+
|
|
35
|
+
## Phase 3 — Self-Verify
|
|
36
|
+
```bash
|
|
37
|
+
npx tsc --noEmit
|
|
38
|
+
npx playwright test automation/tests/{TICKET-ID}/integration/<feature>-<scenario>.spec.ts --list
|
|
39
|
+
```
|
|
40
|
+
(Cần môi trường staging/DB/Kafka test khả dụng để chạy thật sau khi generate.)
|
|
41
|
+
|
|
42
|
+
## Output
|
|
43
|
+
Script + client/fixture (DB/Kafka/API) trong `automation/tests/{TICKET-ID}/integration/` + `fixtures/`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Gen Script — Web Non-Functional (Performance/Security/Accessibility/Compatibility)
|
|
7
|
+
|
|
8
|
+
**Đọc `_shared/web-conventions.md` trước** (locator/wait/assertion nền tảng vẫn áp dụng).
|
|
9
|
+
|
|
10
|
+
## Khi nào trigger
|
|
11
|
+
- Convert TC non-functional (output `qa-designer/non-functional.md`), TC Automatable=Y, có
|
|
12
|
+
**ngưỡng đo cụ thể** trong `TC_<FEATURE>.md`.
|
|
13
|
+
|
|
14
|
+
## Công cụ theo loại
|
|
15
|
+
|
|
16
|
+
| Loại | Công cụ | Assert |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| **Performance** | `performance.timing`/`page.evaluate` đo, hoặc tích hợp k6/Artillery cho load thật | Ngưỡng cụ thể (`expect(elapsed).toBeLessThan(2000)`), không assert mơ hồ |
|
|
19
|
+
| **Security** | Payload injection trong constant/fixture; test trên môi trường test, KHÔNG production | Status 4xx + không tạo được record + response không lộ PII |
|
|
20
|
+
| **Accessibility** | `@axe-core/playwright` (`AxeBuilder`) | `expect(results.violations).toHaveLength(0)` hoặc filter đúng WCAG level (`wcag2a`/`wcag2aa`) |
|
|
21
|
+
| **Compatibility** | Playwright `projects` trong config (chromium/firefox/webkit), hoặc device emulation | Mỗi project = 1 target trong TC; không hardcode 1 browser |
|
|
22
|
+
|
|
23
|
+
## Quy ước riêng
|
|
24
|
+
- Assertion **luôn có ngưỡng cụ thể khớp TC gốc** — không tự đặt ngưỡng khác, không
|
|
25
|
+
`expect(response).toBeTruthy()` mơ hồ.
|
|
26
|
+
- Đo elapsed time: bắt đầu/kết thúc rõ ràng, **không** bao gồm thời gian fixture setup.
|
|
27
|
+
- Test cần môi trường đặc biệt (load server, scanner) → `test.skip(!envReady, 'lý do')`.
|
|
28
|
+
|
|
29
|
+
## Phase 1 — Clarify
|
|
30
|
+
Loại + ngưỡng + công cụ; môi trường/tải mẫu; data đặc biệt từ `TEST_DATA_PLAN.md`.
|
|
31
|
+
|
|
32
|
+
## Phase 2 — Generate
|
|
33
|
+
Mỗi TC → 1 test đo + assert ngưỡng; đánh dấu test cần môi trường riêng bằng tag `@slow`.
|
|
34
|
+
|
|
35
|
+
## Phase 3 — Self-Verify
|
|
36
|
+
```bash
|
|
37
|
+
npx tsc --noEmit
|
|
38
|
+
npx playwright test automation/tests/{TICKET-ID}/non-functional/<feature>-<scenario>.spec.ts --list
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Output
|
|
42
|
+
`automation/tests/{TICKET-ID}/non-functional/<feature>-<scenario>.spec.ts` + helper đo/scan (`utils/measure.ts`).
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
new_in: QC-Workflow-Proposal (8-phase)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Run — Mobile (WebdriverIO + Appium)
|
|
8
|
+
|
|
9
|
+
Skill **tự chứa** cho `/qc-run-script` khi `active_platform = app`.
|
|
10
|
+
|
|
11
|
+
## Lệnh chạy
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx wdio run wdio.conf.ts --spec mobile-automation/test/specs/{TICKET-ID}/...
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Video/screenshot on-fail cấu hình qua `afterTest` hook trong `wdio.conf.ts` (chụp screenshot
|
|
18
|
+
khi `passed === false`; ghi video nếu dùng service `wdio-video-reporter` hoặc quay màn hình
|
|
19
|
+
qua `driver.saveRecordingScreen`/tương đương simulator/emulator).
|
|
20
|
+
|
|
21
|
+
## Đọc kết quả trước khi đề xuất phân loại Fail
|
|
22
|
+
|
|
23
|
+
Với mỗi FAIL, xem screenshot/video tại thời điểm fail + log Appium server (`appium.log`)
|
|
24
|
+
trước khi đoán:
|
|
25
|
+
|
|
26
|
+
| Dấu hiệu | Khả năng cao là |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Element "not found" nhưng screenshot cho thấy nó **hiển thị rõ trên màn hình** | **script-bug** — sai `ValueKey`/locator, hoặc app chưa bật `Semantics` đúng cho driver `FlutterIntegration` đọc |
|
|
29
|
+
| Log Appium báo `automationName` không khớp app (vd dùng `UiAutomator2` cho app Flutter không bật accessibility) | **script-bug** — sai cấu hình driver, xem `_shared/mobile-conventions.md` §0 |
|
|
30
|
+
| Hành động đúng (tap đúng nút, đúng data) nhưng app **không phản hồi đúng spec** (không điều hướng, không lưu data) | **product-gap** |
|
|
31
|
+
| Permission dialog native chặn action, test không xử lý | **script-bug** — thiếu xử lý dialog, không phải bug sản phẩm |
|
|
32
|
+
| Fail chỉ xảy ra trên 1 device/OS version cụ thể | Có thể **product-gap** riêng cho compatibility đó — không quy chung là flaky |
|
|
33
|
+
|
|
34
|
+
## Retry trước khi kết luận (bắt buộc — bước 0 của gate phân loại Fail)
|
|
35
|
+
Mobile vốn có độ trễ/nhiễu cao hơn web (cold start, animation, tốc độ máy) — trước khi đề xuất
|
|
36
|
+
phân loại bất kỳ Fail nào, chạy lại riêng test đó tối đa 2 lần trên cùng device/emulator. Kết
|
|
37
|
+
quả không nhất quán → đề xuất `flaky` (xem `/qc-run-script` §Phân loại mỗi Fail), không phải
|
|
38
|
+
script-bug/product-gap ngay.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
source: upstream/qc-base-new/Automation-Standards.md §1 + OQ-01 · Mobile-Automation-Standards.md §1 (Approved)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Report skill — TypeScript stack (Playwright HTML Report / WDIO Allure Report)
|
|
8
|
+
|
|
9
|
+
Skill **tự chứa** cho `/qc-report`. Báo cáo do **công cụ sinh** — Playwright HTML Report (web·system) hoặc Allure v2.x (app) — **không** dashboard tự viết.
|
|
10
|
+
|
|
11
|
+
## Web — Playwright HTML Report + Trace Viewer
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx playwright test automation/tests/{TICKET-ID}/... --reporter=html
|
|
15
|
+
npx playwright show-report # mở report HTML tương tác
|
|
16
|
+
npx playwright show-trace test-results/<nodeid>/trace.zip # debug 1 test cụ thể
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- Report HTML mặc định ở `playwright-report/` (self-contained, mở trực tiếp trong browser).
|
|
20
|
+
- Mỗi test fail có sẵn trace + screenshot đính kèm (cấu hình qua
|
|
21
|
+
`use: { trace: 'on-first-retry', screenshot: 'only-on-failure' }` trong `playwright.config.ts`).
|
|
22
|
+
|
|
23
|
+
## Mobile — WebdriverIO Allure Report
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx wdio run wdio.conf.ts --spec ...
|
|
27
|
+
npx allure generate ./allure-results --clean -o ./allure-report
|
|
28
|
+
npx allure open ./allure-report
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- Cần reporter `@wdio/allure-reporter` khai trong `wdio.conf.ts` (`reporters: ['allure']`).
|
|
32
|
+
- Screenshot/video on-fail đính kèm tự động vào report qua `afterTest` hook (xem
|
|
33
|
+
`qa-script-runner/mobile/run.md`).
|
|
34
|
+
|
|
35
|
+
## Nguyên tắc chung (cả hai platform)
|
|
36
|
+
- Evidence trung thực: report phản ánh đúng lần chạy gần nhất, không chỉnh sửa số liệu.
|
|
37
|
+
- FAIL giữ nguyên trạng thái thật cho tới khi fix + chạy lại — **không fake-pass**.
|
|
38
|
+
- `playwright-report/`, `test-results/`, `allure-results/`, `allure-report/` đã gitignore
|
|
39
|
+
(artifact nặng) — không commit vào repo.
|
|
40
|
+
- Tóm tắt bắt buộc: **TOTAL / PASS / FAIL / SKIP / FLAKY** + duration, và với mỗi FAIL: phân
|
|
41
|
+
loại đã xác nhận (script-bug/product-gap/flaky) từ `/qc-run-script`, kèm `BUG-{id}` nếu đã file.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-09
|
|
4
|
+
new_in: QC-Workflow-Proposal (8-phase)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Run — Web (Playwright Test)
|
|
8
|
+
|
|
9
|
+
Skill **tự chứa** cho `/qc-run-script` khi `active_platform = web`.
|
|
10
|
+
|
|
11
|
+
## Lệnh chạy
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx playwright test automation/tests/{TICKET-ID}/... --reporter=html,list
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Trace tự động bật qua `playwright.config.ts` (`use: { trace: 'on-first-retry' }` hoặc `'on'`
|
|
18
|
+
nếu muốn trace mọi lần) → mỗi test có `test-results/<nodeid>/trace.zip` khi fail.
|
|
19
|
+
|
|
20
|
+
## Đọc kết quả trước khi đề xuất phân loại Fail
|
|
21
|
+
|
|
22
|
+
Với mỗi FAIL, **mở trace trước khi đoán**:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx playwright show-trace test-results/<nodeid>/trace.zip
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Trace viewer cho: timeline hành động, DOM snapshot tại từng bước, network request/response,
|
|
29
|
+
console log. Dấu hiệu phân biệt:
|
|
30
|
+
|
|
31
|
+
| Dấu hiệu trong trace | Khả năng cao là |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Locator "not found" nhưng DOM snapshot cho thấy element **có tồn tại** với selector khác | **script-bug** — selector sai/lỗi thời do UI đổi cấu trúc, không phải bug sản phẩm |
|
|
34
|
+
| Element thực sự **không xuất hiện** sau hành động đúng spec (nút bấm không có phản hồi, API trả lỗi mà spec nói phải thành công) | **product-gap** — hành vi thực tế ≠ spec |
|
|
35
|
+
| Timeout chờ network response, response **không bao giờ tới** | **product-gap** nếu spec yêu cầu response — hoặc **script-bug** nếu URL/endpoint chờ sai |
|
|
36
|
+
| Assertion so giá trị: actual đúng theo spec nhưng expected trong test viết sai | **script-bug** |
|
|
37
|
+
| Flaky ngẫu nhiên (pass khi chạy lẻ, fail khi chạy song song) | **script-bug** — thiếu cách ly data/test independence, xem `_shared/web-conventions.md` §Common Pitfalls #5-6 |
|
|
38
|
+
|
|
39
|
+
Không kết luận nếu bằng chứng không đủ rõ — báo "không chắc, cần điều tra thêm" thay vì đoán.
|
|
40
|
+
|
|
41
|
+
## Retry trước khi kết luận (bắt buộc — bước 0 của gate phân loại Fail)
|
|
42
|
+
Trước khi đề xuất phân loại bất kỳ Fail nào, chạy lại riêng test đó tối đa 2 lần:
|
|
43
|
+
```bash
|
|
44
|
+
npx playwright test <file> -g "<title>" --repeat-each=1
|
|
45
|
+
```
|
|
46
|
+
Kết quả không nhất quán (fail→pass hoặc ngược lại) → đề xuất `flaky`, không phải
|
|
47
|
+
script-bug/product-gap (xem `/qc-run-script` §Phân loại mỗi Fail). Chỉ khi fail **nhất quán**
|
|
48
|
+
qua các lần retry mới tiếp tục điều tra để phân biệt script-bug/product-gap.
|
|
@@ -190,7 +190,7 @@ services:
|
|
|
190
190
|
- Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
|
|
191
191
|
- Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
|
|
192
192
|
- Override `paths.prd_change_requests_dir` → `{spec_source}/feedback/prd-change-requests`
|
|
193
|
-
- Override `paths.trace_dir` → `{spec_source}/.trace` — **luôn khi `spec_source` được đặt.** Trace TSV được gộp vào spec repo (một nơi authoritative duy nhất, không tách theo service) để PM/PO có một chỗ duy nhất quản lý trạng thái. Cấu trúc bên trong: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv`. Các lệnh phía code (`/generate-code`, `/dev-run-test`, `/qc-run-
|
|
193
|
+
- Override `paths.trace_dir` → `{spec_source}/.trace` — **luôn khi `spec_source` được đặt.** Trace TSV được gộp vào spec repo (một nơi authoritative duy nhất, không tách theo service) để PM/PO có một chỗ duy nhất quản lý trạng thái. Cấu trúc bên trong: `.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv`. Các lệnh phía code (`/generate-code`, `/dev-run-test`, `/qc-run-script`) chạy từ `service_root` nhưng **ghi trace row của chúng vào `{spec_source}/.trace/{domain}/{prd-slug}/`** — giống như chúng đã push `feedback/` vào đó. *(`.trace` theo service chỉ khi không có `spec_source`.)*
|
|
194
194
|
- Override `paths.refinement_dir` → `{spec_source}/.agent/review` — **luôn khi `spec_source` được đặt.** Findings review (`/refine-prd`, `/review-context`, `/review-tech-docs`) là artifact liên-team *về* tài liệu trong spec repo (PRD/BDD/tech-design) — thuộc cùng khu vực ghi với `.trace/` và `feedback/`. Các lệnh review chạy từ working dir của service (BE repo) nhưng **ghi findings vào `{spec_source}/.agent/review/`**, KHÔNG phải `.agent/review` của service repo. Bên trong flat, phân biệt bằng tên file đã prefix `{prd-slug}`/`{UC-ID}`/`{TICKET-ID}`. *(`.agent/review` theo service chỉ khi không có `spec_source`.)*
|
|
195
195
|
|
|
196
196
|
> **Vì sao đặt dưới `spec_source`:** PRD, BDD, tech-docs, design-spec, domain knowledge, feedback của tester, **trạng thái coverage `.trace/`**, **và findings review `.agent/review/`** đều là **artifact liên team** — chúng nằm trong **spec repo dùng chung** theo bố cục feature-package để mọi umbrella (FE/App/BE) và PM đọc từ một nguồn qua `/sync`. Trong bố cục feature-package, một folder `specs/{domain}/{prd-slug}/` gom tất cả loại artifact của một PRD, giúp spec repo tự đủ và dễ điều hướng theo feature. Service submodule chỉ chứa **code** (+ tooling build/test). `.trace/`, `.agent/review/` và `feedback/` là khu vực **ghi** của dev/QC/reviewer trong spec repo. Ở chế độ single-service (không có `spec_source`), mọi thứ mặc định dưới gốc repo — vẫn là một repo.
|
package/core/steps/gate.md
CHANGED
|
@@ -77,7 +77,7 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
|
|
|
77
77
|
|
|
78
78
|
| Mức | Lệnh nào | `--yes` bỏ qua được? |
|
|
79
79
|
|---|---|:---:|
|
|
80
|
-
| **Không chặn** |
|
|
80
|
+
| **Không chặn** | `/review-code` · `/validate-traces` · `/debug` — **KHÔNG phải vì read-only**: cả ba đều CÓ ghi file. Chúng không chặn vì thao tác ghi của chúng hoặc nằm sau một câu hỏi `(Y/N)`, hoặc nằm sau một cờ, hoặc là `append`/dựng-lại-được | — (vốn không có) |
|
|
81
81
|
| **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
|
|
82
82
|
| **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
|
|
83
83
|
|
|
@@ -85,6 +85,12 @@ Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phi
|
|
|
85
85
|
`--` khỏi phần resolve target, nên cờ này không ảnh hưởng việc tìm file.) Mở đường chạy
|
|
86
86
|
headless: `claude -p "/generate-code UC1 --yes"`.
|
|
87
87
|
|
|
88
|
+
> **Tên lệnh trong bảng trên có máy canh — `R19`.** Mỗi hàng bảng vừa nêu một mức vừa nêu
|
|
89
|
+
> tên lệnh sẽ bị đối chiếu với `gate.checkpoint_levels`; lệch là build đỏ. Lý do có rule này:
|
|
90
|
+
> ngày 2026-09-16 hai lệnh đổi mức, schema và `commands/*.tmpl` đều sửa, **build vẫn xanh**,
|
|
91
|
+
> mà bảng này lẫn `rules/workflow.md` đều còn liệt chúng ở mức cũ. `R11` chỉ canh
|
|
92
|
+
> `commands/*.tmpl` ↔ schema — *biết có máy canh không bằng biết máy canh **đến đâu***.
|
|
93
|
+
|
|
88
94
|
> **KHÔNG tự suy mức từ bảng này.** Mỗi lệnh **tự khai** mức của nó ở một dòng `*Checkpoint: …*`
|
|
89
95
|
> ngay dưới `## Gate` của chính nó — đọc dòng đó, đừng suy diễn. Bảng trên chỉ giải thích ba mức
|
|
90
96
|
> **nghĩa là gì**.
|
package/core/steps/qc-scope.md
CHANGED
|
@@ -58,6 +58,49 @@ Theo thứ tự, dừng ở cái đầu tiên khớp:
|
|
|
58
58
|
Lưu `active_platform`. Từ đây, **mọi** phép đọc `.feature` chỉ đọc thư mục
|
|
59
59
|
`bdd/{active_platform}/` — không trộn SC chéo nền.
|
|
60
60
|
|
|
61
|
+
> **Nền `system` còn MỘT câu hỏi nữa, và nó ở trạm 3.** `system` không đồng nghĩa với API — nó
|
|
62
|
+
> còn chứa **job tự chạy** và **consumer hàng đợi**, hai thứ không có endpoint nào. Khi không suy
|
|
63
|
+
> được, `/qc-design-test` hỏi QC rồi ghi câu trả lời vào `Tags` của TC. Xem
|
|
64
|
+
> `/qc-design-test` §Nền `system`. Ghi ở đây để người đọc luật nền biết **còn một câu chưa xong**,
|
|
65
|
+
> chứ không phải phân giải xong nền là hết.
|
|
66
|
+
|
|
67
|
+
### 2b — Nền → module QC → lane skill *(bảng DUY NHẤT, đừng chép lại ở lệnh)*
|
|
68
|
+
|
|
69
|
+
| `active_platform` | module QC | `layout` | lane skill |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `web` · `webview` | `qc-playwright-ts` | `layout.web` — `automation/` | `qa-script-designer/web/*` |
|
|
72
|
+
| `app` · `app-ios` · `app-android` | `qc-wdio-appium` | `layout.mobile` — `mobile-automation/` | `qa-script-designer/mobile/*` |
|
|
73
|
+
| `system` + lane `api` | `qc-playwright-ts` | `layout.api` — `api-automation/` | `qa-script-designer/api/*` |
|
|
74
|
+
| `system` + lane `job` · `queue` | `qc-playwright-ts` | `layout.api` — `api-automation/` | ⚠️ **chưa có lane script** — xem dưới |
|
|
75
|
+
|
|
76
|
+
> **Vì sao bảng này ở đây chứ không ở lệnh.** Cùng lý do mục §2 tồn tại: luật phân giải nền
|
|
77
|
+
> từng được copy-paste ở 5 lệnh rồi câu chữ lệch nhau. Ba lệnh script trỏ vào đây, **không
|
|
78
|
+
> chép lại**.
|
|
79
|
+
>
|
|
80
|
+
> **Vì sao KHÔNG có key cấu hình riêng.** Từng có một lời hứa `tech_stack.qc_module` trong
|
|
81
|
+
> comment của module cũ, nhưng nó **chưa bao giờ được cài** — và không nên cài: `active_platform`
|
|
82
|
+
> đã trả lời xong câu này ở §2 và đã **khoá cho cả pass QC**. Một field thứ hai là hai đáp án
|
|
83
|
+
> cho một câu hỏi, và khi chúng lệch nhau thì artifact ghi vào thư mục của nền này trong khi
|
|
84
|
+
> script sinh theo layout của nền kia — hỏng **im lặng**.
|
|
85
|
+
>
|
|
86
|
+
> 🔴 **`system` KHÔNG đồng nghĩa với API — sửa 2026-09-17 sau ca thật LESS-22.** Quyết định
|
|
87
|
+
> `S-API` ánh xạ `system → lane api` vô điều kiện, và nó **sai**: `system` còn chứa **job tự
|
|
88
|
+
> chạy** *(không ai gọi)* và **consumer hàng đợi** *(nằm chờ message)*. Cả ba tài liệu chuẩn dùng
|
|
89
|
+
> để chốt `S-API` đều **chỉ nói về API**, nên không ai thấy hai hình dạng kia.
|
|
90
|
+
>
|
|
91
|
+
> **Tầng thiết kế TC đã có đủ ba** *(trạm 3 hỏi QC rồi ghi lane — xem `/qc-design-test` §Nền
|
|
92
|
+
> `system`)*: `functional/api` · `functional/job` · `integration/queue`.
|
|
93
|
+
>
|
|
94
|
+
> **Tầng sinh script mới có một** — `qa-script-designer/api/*`. Lane `job` và `queue` chạy tới
|
|
95
|
+
> trạm 6 thì **chưa có skill**. Đây là **lỗ đã biết, ghi ra thay vì để trạm 6 lặng lẽ dùng lane
|
|
96
|
+
> `api`**: gặp TC lane `job`/`queue`, trạm 6 phải **DỪNG** và nói rõ chưa hỗ trợ, không được
|
|
97
|
+
> sinh API Object cho một thứ không có endpoint.
|
|
98
|
+
|
|
99
|
+
> **`web` và `system` dùng chung module, khác `layout`.** Đó là chủ ý: cùng Playwright + TS
|
|
100
|
+
> *(AD-API-001 — "tái dùng infrastructure với Web testing")*, nên tách làm hai module là khai
|
|
101
|
+
> dãy phiên bản hai lần. Nhưng **API Object ≠ Page Object** và `api-automation/` là thư mục
|
|
102
|
+
> gốc riêng, nên `layout` và lane skill phải tách.
|
|
103
|
+
|
|
61
104
|
---
|
|
62
105
|
|
|
63
106
|
## 3 — `qc_artifact_dir`
|
|
@@ -114,7 +157,7 @@ và đánh dấu trong artifact là dựa trên BDD nháp. *(Tên cờ chung cho
|
|
|
114
157
|
|
|
115
158
|
### 4b — Cổng cấp UC: **cái UC vừa được gọi tên** có làm được không?
|
|
116
159
|
|
|
117
|
-
|
|
160
|
+
Bảy lệnh nhận target là **UC-ID** — `/qc-design-test` · `/qc-review-testcase` · `/qc-review-script` · `/qc-design-script` · `/qc-run-script` · `/qc-run-manualtest` · `/qc-report`
|
|
118
161
|
— phải đối chiếu target với **bảng vừa in ở trên**. Hai lệnh cấp PRD (`/qc-analyze` · `/qc-plan`)
|
|
119
162
|
**bỏ qua mục này**: target của chúng là `TICKET-ID`, và cổng 4a đã trả lời đúng câu hỏi của chúng.
|
|
120
163
|
|
|
@@ -141,7 +184,7 @@ Bốn lệnh nhận target là **UC-ID** — `/qc-design-test` · `/qc-review`
|
|
|
141
184
|
> đi thẳng vào một spec chưa ai duyệt.
|
|
142
185
|
>
|
|
143
186
|
> Cái giá không dừng ở "thiết kế trên bản nháp". `Guard SC coverage` của trạm 3 sẽ **khẳng định**
|
|
144
|
-
> `khớp K/K` trên spec chưa duyệt, và `/qc-run-
|
|
187
|
+
> `khớp K/K` trên spec chưa duyệt, và `/qc-run-script` sẽ ghi `qc_status = pass` **chính thức** vào sổ
|
|
145
188
|
> trace cho nó. Đó là **báo cáo sai** — `rules/workflow.md` §*"ai KHẲNG ĐỊNH một giá trị dương phải
|
|
146
189
|
> được phép khẳng định"*.
|
|
147
190
|
>
|
package/core/steps/qc-stamp.md
CHANGED
|
@@ -17,7 +17,7 @@ Câu chưa ai trả lời là *"**tài liệu thiết kế test** còn khớp kh
|
|
|
17
17
|
|
|
18
18
|
| Tín hiệu | Nghĩa | Việc phải làm |
|
|
19
19
|
|---|---|---|
|
|
20
|
-
| `qc_status = not_run` | kết quả cũ hết hiệu lực | **chạy lại** `/qc-run-
|
|
20
|
+
| `qc_status = not_run` | kết quả cũ hết hiệu lực | **chạy lại** `/qc-run-script` |
|
|
21
21
|
| **stamp lệch** | TC/gap/plan mô tả spec cũ | **viết lại** — `/qc-analyze` hoặc `/qc-design-test` |
|
|
22
22
|
|
|
23
23
|
Thiếu vế sau thì người ta thấy `not_run` và **chạy lại** — đúng phản xạ, sai việc. Một bộ TC lỗi thời
|
|
@@ -111,8 +111,8 @@ Với mỗi artifact mà lệnh này đọc:
|
|
|
111
111
|
|
|
112
112
|
| Trạm | Lệch thì | Vì sao |
|
|
113
113
|
|---|---|---|
|
|
114
|
-
| `/qc-plan` · `/qc-design-test` · `/qc-review` | **⚠️ cảnh báo, đi tiếp** | Cùng họ `TECHDOC_DRIFT`/`BDD_DRIFT` — 13/17 cờ audit không chặn. Thiết kế TC trên bản hơi cũ vẫn ra sản phẩm dùng được; chặn ở đây là **ồn** |
|
|
115
|
-
| `/qc-run-
|
|
114
|
+
| `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` | **⚠️ cảnh báo, đi tiếp** | Cùng họ `TECHDOC_DRIFT`/`BDD_DRIFT` — 13/17 cờ audit không chặn. Thiết kế TC trên bản hơi cũ vẫn ra sản phẩm dùng được; chặn ở đây là **ồn** |
|
|
115
|
+
| `/qc-run-script` | **chặn `pass`, KHÔNG chặn chạy** | Lớp **báo cáo sai** |
|
|
116
116
|
|
|
117
117
|
```
|
|
118
118
|
⚠️ Stamp lệch — {file} dựng trên {nguồn} {ver_cũ}, hiện tại {ver_mới}.
|
|
@@ -120,7 +120,7 @@ Với mỗi artifact mà lệnh này đọc:
|
|
|
120
120
|
Nên chạy lại: {lệnh} (đi tiếp vẫn được, nhưng {hệ quả cụ thể})
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
**`/qc-run-
|
|
123
|
+
**`/qc-run-script` — nhập vào cơ chế đã có, không phát minh cơ chế mới.** Stamp lệch xử lý **y hệt**
|
|
124
124
|
row `DRIFT`/`ORPHANED` của `positive_assertion_guards` + lint **T12** (G55): test vẫn chạy, nhưng
|
|
125
125
|
xanh → ghi `not_run` chứ **không** ghi `pass`, và **không đóng bug nào** ở lần chạy đó.
|
|
126
126
|
|
|
@@ -54,9 +54,9 @@ Discovery → PRD → [Design Spec] → BDD → Tech Design ─┬─ Code → D
|
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
**Sơ đồ rẽ đôi, không phải một dòng thẳng.** `/map-testids` chốt hợp đồng test-id §4.5.6 ở Tech
|
|
57
|
-
Design, nên **Code** và **QC Design** (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review`)
|
|
57
|
+
Design, nên **Code** và **QC Design** (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase`)
|
|
58
58
|
đọc cùng một bản đã đóng băng và **chạy song song, không chờ nhau**. Hai nhánh gặp lại ở **QC Run**
|
|
59
|
-
(`/qc-run-
|
|
59
|
+
(`/qc-run-script` → `/qc-report`) — trạm duy nhất cần code chạy được.
|
|
60
60
|
|
|
61
61
|
Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **phase của nó** trong sơ đồ trên:
|
|
62
62
|
|
|
@@ -69,8 +69,8 @@ Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **pha
|
|
|
69
69
|
| Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
|
|
70
70
|
| Code | `/generate-code` · `/review-code` |
|
|
71
71
|
| Dev Self-Check | `/dev-gen-test` · `/dev-run-test` · `/dev-smoke-test` |
|
|
72
|
-
| QC Design | `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review` |
|
|
73
|
-
| QC Run | `/qc-run-
|
|
72
|
+
| QC Design | `/qc-analyze` · `/qc-plan` · `/qc-design-test` · `/qc-review-testcase` · `/qc-automation-assess` |
|
|
73
|
+
| QC Run | `/qc-design-script` · `/qc-review-script` · `/qc-run-script` · `/qc-run-manualtest` · `/qc-report` |
|
|
74
74
|
| Trace Audit | `/validate-traces` |
|
|
75
75
|
|
|
76
76
|
Với **lệnh review**, thêm vòng review 3 bước và đánh dấu bước hiện tại, vd:
|
|
@@ -97,10 +97,11 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
97
97
|
| /review-context (BDD) | `/generate-tech-docs {UC-ID}` nếu APPROVED; sinh lại nếu NEEDS_FIX |
|
|
98
98
|
| /qc-analyze | `/qc-plan {TICKET-ID} {platform}` — **cấp PRD**, không phải `{UC-ID}` (xử lý các gap blocker 🔴 trước) |
|
|
99
99
|
| /qc-plan | `/qc-design-test {UC-ID}` |
|
|
100
|
-
| /qc-design-test | `/qc-review {UC-ID}`
|
|
101
|
-
| /qc-
|
|
102
|
-
| /qc-
|
|
103
|
-
| /qc-
|
|
100
|
+
| /qc-design-test | `/qc-review-testcase {UC-ID}` |
|
|
101
|
+
| /qc-automation-assess | `/qc-design-script {TICKET-ID}` (Automatable: Y) · `/qc-run-manualtest {UC-ID}` (N) |
|
|
102
|
+
| /qc-review-testcase | `/qc-automation-assess {TICKET-ID}` nếu `APPROVED` hoặc `APPROVED_WITH_SUGGESTIONS`; sửa TC bằng `/qc-design-test` nếu `REVISION_REQUIRED` · `REJECTED` |
|
|
103
|
+
| /qc-run-script | `/qc-run-manualtest {UC-ID}` (TC Automatable: N) rồi `/qc-report {UC-ID}` |
|
|
104
|
+
| /qc-review-script | `/qc-report {UC-ID}` rồi tạo PR nếu `APPROVED` hoặc `APPROVED_WITH_SUGGESTIONS`; sửa script nếu `REVISION_REQUIRED` · `REJECTED` |
|
|
104
105
|
| /qc-report | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
|
|
105
106
|
| /generate-tech-docs | `/map-testids {UC-ID}` — chốt hợp đồng test-id §4.5.6 **trước** khi review |
|
|
106
107
|
| /map-testids | `/review-tech-docs {tech-design-file}` (review CẢ hợp đồng vừa ghi) |
|
|
@@ -112,7 +113,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
112
113
|
| /review-code | `/dev-smoke-test {UC-ID}` hoặc tạo PR |
|
|
113
114
|
| /dev-smoke-test | Tạo PR và link tới ticket |
|
|
114
115
|
| /validate-traces | **Cờ 🔴 trước (chặn PR):** SEAM_UNWIRED → nối binding sang class thật, xoá/thay stub · STUB_UNRESOLVED → `/generate-code {owner_uc}` (lấp logic tại chỗ + xoá hàm song song) · ORPHANED/TRACE_ORPHAN → quyết định thủ công (xoá code+test, đưa scenario trở lại `.feature`, hoặc sửa `sc_id` của tag). **Rồi:** DRIFT/UNTRACKED → `/generate-code {UC-ID}` · BDD_DRIFT → `/generate-code {feature-file}` · tech-doc lỗi thời vs BDD → `/generate-tech-docs` → `/review-tech-docs` · PRD drift → `/generate-bdd {prd-file}` · GAP → `/dev-gen-test {UC-ID}`. **Chỉ tạo PR khi mọi cờ 🔴 = 0** |
|
|
115
|
-
| /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-
|
|
116
|
+
| /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-script {UC-ID}` để verify + đóng bug |
|
|
116
117
|
| /debug | `/fix-bug {ticket-id}` nếu cần sửa |
|
|
117
118
|
| /report-bug | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
|
|
118
119
|
| /propose-scenario | **Case A** (thiếu scenario cho AC có sẵn) → báo PO/Dev review trong `feedback/bdd-proposals/`; `/generate-bdd` tự chèn khi `Status: accepted`. **Case B** (requirement mới) → `feedback/prd-change-requests/` — PO phải đưa vào PRD trước, KHÔNG tự vào BDD được; `/validate-traces` nhắc lại kèm số ngày chờ chừng nào `Status: Open` |
|
|
@@ -25,7 +25,7 @@ Trước khi đẩy sang QC chính thức, Dev cần một vòng **kiểm nhanh
|
|
|
25
25
|
|
|
26
26
|
> **`dev_selftest` ≠ `qc_status`.** Hai trục **độc lập**: dev smoke (nhanh, tự kiểm) vs QC chính thức (Playwright, evidence). Không lấn quyền nhau.
|
|
27
27
|
>
|
|
28
|
-
> ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-
|
|
28
|
+
> ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-script` và `/qc-run-manualtest` **không được** ghi `pass`; chúng hạ về `not_run`. `fail`/`skip` thì ghi bình thường. `lint-trace` **T12** bắt trạng thái `DRIFT + pass` ở sổ thật, bất kể ai ghi ra.
|
|
29
29
|
|
|
30
30
|
---
|
|
31
31
|
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
# Bước 8 · QC Automation — Dây chuyền kiểm thử 6 trạm (QC Pipeline)
|
|
4
4
|
|
|
5
5
|
> **Tóm tắt.** Dây chuyền QC tự động 6 trạm: phân rã yêu cầu → lập kế hoạch → thiết kế test case → review → chạy Playwright → report. Ghi `qc_status` **chính thức** + evidence.
|
|
6
|
-
> **Commands:** `/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review` → `/qc-run-
|
|
6
|
+
> **Commands:** `/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase` → `/qc-automation-assess` → `/qc-design-script` → `/qc-review-script` → `/qc-run-script` → `/qc-report`
|
|
7
7
|
|
|
8
8
|
| | |
|
|
9
9
|
|---|---|
|
|
10
10
|
| **Giai đoạn** | QC Automation |
|
|
11
11
|
| **Owner** | 👤 QA / Tester |
|
|
12
|
-
| **Đầu vào** | **Trạm 1–4:** spec (PRD/BDD `approved`) + **hợp đồng test-id §4.5.6** (đóng băng ở bước 5) — **chưa cần code**.<br/>**Trạm
|
|
12
|
+
| **Đầu vào** | **Trạm 1–4:** spec (PRD/BDD `approved`) + **hợp đồng test-id §4.5.6** (đóng băng ở bước 5) — **chưa cần code**.<br/>**Trạm 6–8 `/qc-design-script` · `/qc-run-script` thêm:** code đã chạy được — **hai trạm duy nhất** cần |
|
|
13
13
|
| **Đầu ra** | Test case, script Playwright, `qc_status`, evidence, product-gap |
|
|
14
14
|
| **HITL** | 🟠 Vừa — cổng review case & script trước khi chạy |
|
|
15
15
|
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
## Mục đích (Purpose)
|
|
19
19
|
|
|
20
|
-
Đây là **kiểm thử chính thức** (khác với dev smoke). Dùng module **`qc-playwright`** (
|
|
20
|
+
Đây là **kiểm thử chính thức** (khác với dev smoke). Dùng module QC theo nền — **`qc-playwright-ts`** (web·system) hoặc **`qc-wdio-appium`** (app), phân giải ở `steps/qc-scope.md` §2b — độc lập với module implementation của dev. Bước này:
|
|
21
21
|
|
|
22
22
|
- Phân rã yêu cầu thành test case bám scenario, phát hiện **gap tài liệu**.
|
|
23
23
|
- Chạy test thật, ghi **`qc_status` chính thức** + **evidence**.
|
|
24
|
-
⚠️ Nhưng `/qc-run-
|
|
24
|
+
⚠️ Nhưng `/qc-run-script` và `/qc-run-manualtest` **đọc cột `status` trước khi ghi `pass`** *(GAPS-v4 G55)*: row `DRIFT`/`ORPHANED` + test xanh → hạ về `not_run`, và **không** đóng bug nào ở lần chạy đó. `fail`/`skip` ghi bình thường.
|
|
25
25
|
- Phân loại FAIL thành **ba** nhãn — `script-bug` · `product-gap` · `flaky` — **sau khi đã chạy lại tối đa 2 lần**. Một test đỏ **một lần** chưa nói được nó đỏ vì cái gì.
|
|
26
26
|
- Đẩy **product-gap** ngược về PO/Dev.
|
|
27
27
|
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
- **UC-ID** + platform (QC pass khoá 1 platform).
|
|
33
33
|
- Spec: PRD / `.feature` (từ spec repo, qua `spec_source`).
|
|
34
34
|
- **Hợp đồng test-id**: `@trace.testid_attr` (header tech-doc, **tên** thuộc tính) + §4.5.6 Test Selectors (**giá trị** test-id, cột *Serves SC* là chỉ mục ngược). Đã chốt ở [bước 5](05-tech-docs.md) **trước khi có code**.
|
|
35
|
-
- Code đã sinh & chạy được — **chỉ `/qc-run-
|
|
36
|
-
- `qc_dir` (working docs của QC) + module `qc-playwright
|
|
35
|
+
- Code đã sinh & chạy được — **chỉ `/qc-design-script` và `/qc-run-script` cần**. Bốn trạm đầu (`/qc-analyze` → `/qc-plan` → `/qc-design-test` → `/qc-review-testcase`) chạy **song song với FE** vì chỉ cần spec + hợp đồng test-id. Đó là chỗ hai nhánh của [bước 5](05-tech-docs.md) gặp lại.
|
|
36
|
+
- `qc_dir` (working docs của QC) + module QC theo nền (`qc-playwright-ts` · `qc-wdio-appium`).
|
|
37
37
|
|
|
38
38
|
## Output (Đầu ra)
|
|
39
39
|
|
|
40
40
|
| Artifact | Nội dung |
|
|
41
41
|
|----------|----------|
|
|
42
42
|
| `docs/{TICKET-ID}/{platform}/…` | `REQUIREMENT_ANALYSIS.md`, `DOC_GAP.md`, `TEST_PLAN.md`, `test-cases/*.Test.md` — **mỗi loại đúng một file cho cả (PRD × nền)**, các UC là hàng/mục bên trong (cột `UC`) |
|
|
43
|
-
| Script
|
|
43
|
+
| Script TypeScript (`*.spec.ts`) | Sinh từ `.Test.md` đã review |
|
|
44
44
|
| Cột `qc_status` trong `.trace/…/{UC-ID}-{platform}.tsv` | Trạng thái QC **chính thức** |
|
|
45
45
|
| Evidence + report | `/qc-report` — kèm product-gap đẩy về PO/Dev |
|
|
46
46
|
|
|
@@ -75,8 +75,9 @@ Dây chuyền **6 trạm**, output trạm trước là input trạm sau:
|
|
|
75
75
|
| 1 | `/qc-analyze` | Phân rã yêu cầu + phát hiện **gap tài liệu** (`DOC_GAP.md`) | **Guard BR-tag** |
|
|
76
76
|
| 2 | `/qc-plan` | Đánh giá **rủi ro** + câu hỏi cho dev (`TEST_PLAN.md`) | — |
|
|
77
77
|
| 3 | `/qc-design-test` | Thiết kế **test case** dạng Markdown (`*.Test.md`) | **Guard SC coverage** |
|
|
78
|
-
| 4 | `/qc-review` | 🛑 **Cổng review**
|
|
79
|
-
|
|
|
78
|
+
| 4 | `/qc-review-testcase` | 🛑 **Cổng review test case** — verdict `APPROVED`/`NEEDS_FIX` là điều kiện tiên quyết của trạm sau | — |
|
|
79
|
+
| 6 | `/qc-review-script` | 🛑 **Cổng review script** — biên bản riêng `REVIEW_SCRIPT_<FEATURE>.md` | — |
|
|
80
|
+
| 5–8 | `/qc-design-script` · `/qc-run-script` | Sinh rồi chạy **script TypeScript**, ghi **`qc_status`** chính thức | **chạy lại ×2 + 3 nhãn FAIL** |
|
|
80
81
|
| 6 | `/qc-report` | Report + **evidence**, đẩy **product-gap** về PO/Dev | — |
|
|
81
82
|
|
|
82
83
|
### Hai Guard cơ học — chống bỏ sót **im lặng**
|
|
@@ -120,14 +121,14 @@ Cả sáu trạm nạp chung `skills/qc/_shared/self-review-principles.md` và c
|
|
|
120
121
|
|
|
121
122
|
> ⚠️ **Self-review KHÔNG thay Guard.** Guard là phép **đếm cơ học**, có hệ quả bắt buộc. Self-review là lượt đọc lại **rộng hơn nhưng mềm hơn**. Một bộ nguyên tắc tự soát **không bao giờ** được dùng làm lý do gỡ một guard — file đó ghi rõ ranh giới này ngay ở đầu.
|
|
122
123
|
|
|
123
|
-
- Stack QC bắt buộc theo `
|
|
124
|
+
- Stack QC bắt buộc theo `stack-profile.yaml` của module đã phân giải (§2b): TypeScript + Playwright Test (web·system) / WebdriverIO + Appium (app); mỗi test độc lập; gom theo (role, account) để auth không xen kẽ.
|
|
124
125
|
- **Locator lấy từ hợp đồng, không dò DOM**: thứ tự ưu tiên là §4.5.6 → `@trace.testid_attr` → mới tới các cách khác. Skill `qa-runner` đã bỏ hết chỉ dẫn "dò DOM trước".
|
|
125
126
|
|
|
126
127
|
---
|
|
127
128
|
|
|
128
129
|
## HITL / Gate
|
|
129
130
|
|
|
130
|
-
- 🛑 `/qc-review` — **cổng review
|
|
131
|
+
- 🛑 `/qc-review-testcase` · `/qc-review-script` — **hai cổng review riêng**: không chạy test kém, và trạm sau đọc được verdict của ĐÚNG vai nó cần.
|
|
131
132
|
- 🛑 **Xác nhận phân loại FAIL** — mỗi FAIL phải được người chốt nhãn trước khi ghi `qc_status`. Đây là cổng chặn hiếm hoi được **thêm vào** (framework vốn đang giảm số cổng), vì **cả hai hướng sai đều không đảo ngược rẻ**.
|
|
132
133
|
- **Không fake-pass**: FAIL là product-gap → giữ nguyên FAIL + evidence, đẩy về PO/Dev.
|
|
133
134
|
|
|
@@ -137,7 +138,7 @@ Cả sáu trạm nạp chung `skills/qc/_shared/self-review-principles.md` và c
|
|
|
137
138
|
|
|
138
139
|
- ❌ Lẫn `qc_status` với `dev_selftest` — hai trục độc lập.
|
|
139
140
|
- ❌ Sửa script cho "xanh" khi thực chất là product-gap → giấu lỗi sản phẩm.
|
|
140
|
-
- ❌ Chạy `/qc-
|
|
141
|
+
- ❌ Chạy `/qc-design-script` khi chưa qua cổng `/qc-review-testcase`.
|
|
141
142
|
- ❌ **Kết luận từ một lần chạy đỏ** — chưa loại nhiễu thì chưa phân biệt được `flaky` với lỗi thật.
|
|
142
143
|
- ❌ **Tự dò selector từ DOM** thay vì đọc §4.5.6 — script giòn, dev đổi một class là vỡ mà không ai báo.
|
|
143
144
|
- ❌ Dùng self-review làm lý do **bỏ qua** một Guard.
|