@educa-corp/sdd-framework 0.9.7 → 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/qc-base-map.json +13 -11
- package/bin/self-check.js +49 -4
- package/bin/trace-schema.json +3226 -3187
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/qc-analyze.md +2 -2
- package/core/commands/qc-automation-assess.md +3 -3
- package/core/commands/qc-design-script.md +60 -30
- package/core/commands/qc-design-test.md +79 -7
- package/core/commands/qc-plan.md +1 -1
- package/core/commands/qc-report.md +85 -76
- package/core/commands/qc-review-script.md +25 -16
- package/core/commands/qc-review-testcase.md +8 -7
- package/core/commands/qc-run-manualtest.md +1 -1
- package/core/commands/qc-run-script.md +15 -8
- 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/skills/qc/qa-analyst/data-flow.md +1 -1
- package/core/skills/qc/qa-automation-assess/matrix.md +6 -3
- package/core/skills/qc/{qa-runner → qa-designer}/exploratory/session.md +8 -2
- package/core/skills/qc/qa-designer/functional/api.md +1 -1
- package/core/skills/qc/qa-designer/functional/job.md +128 -0
- package/core/skills/qc/qa-designer/integration/api.md +1 -1
- package/core/skills/qc/qa-designer/integration/db.md +1 -1
- package/core/skills/qc/qa-designer/integration/{kafka.md → queue.md} +20 -4
- package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +17 -0
- package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +17 -0
- 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 +2 -2
- 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 +26 -7
- package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/integration.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
- 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/qc-scope.md +43 -0
- package/core/steps/report-footer.md +2 -2
- package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +10 -10
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +1 -1
- package/docs/02-concepts/traceability.md +1 -1
- package/docs/03-guides/developer.md +1 -1
- package/docs/03-guides/tester-qa.md +40 -12
- package/docs/04-reference/commands.md +1 -1
- package/docs/04-reference/modules.md +2 -1
- package/docs/explain/17-qc-design-test.md +2 -2
- package/docs/explain/19-qc-run-test.md +4 -4
- package/docs/explain/20-qc-report.md +1 -1
- package/docs/explain/23-fix-bug.md +2 -2
- package/docs/plans/qc-surgery/01-checklist.md +18 -6
- 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/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
|
@@ -6,8 +6,9 @@ ported_from: ai-automation-qc-base
|
|
|
6
6
|
|
|
7
7
|
# /qc-review-testcase — QC Review Gate: test case
|
|
8
8
|
|
|
9
|
-
>
|
|
10
|
-
>
|
|
9
|
+
> Trạm 4/9 của dây chuyền QC automation (qc-analyze → qc-plan → qc-design-test → **qc-review-testcase** →
|
|
10
|
+
> qc-automation-assess → qc-design-script → qc-review-script → qc-run-script ∥ qc-run-manualtest
|
|
11
|
+
> → qc-report). Soát `.Test.md` do
|
|
11
12
|
> `/qc-design-test` sinh: coverage · độ rõ · trace. Cặp với `/qc-review-script` — hai lệnh, hai vai.
|
|
12
13
|
|
|
13
14
|
## Gate
|
|
@@ -339,10 +340,10 @@ File **phải** chứa đúng một dòng theo khuôn này, ở §Tổng quan:
|
|
|
339
340
|
```
|
|
340
341
|
hoặc
|
|
341
342
|
```
|
|
342
|
-
**Verdict:**
|
|
343
|
+
**Verdict:** REVISION_REQUIRED ← hoặc REJECTED khi có BLOCKER
|
|
343
344
|
```
|
|
344
345
|
|
|
345
|
-
`
|
|
346
|
+
Verdict suy từ **số đếm lỗi**, không từ điểm — `≥1 BLOCKER` → `REJECTED` · `≥1 MAJOR` → `REVISION_REQUIRED` · chỉ MINOR/SUGGESTION → `APPROVED_WITH_SUGGESTIONS` · sạch → `APPROVED`. Xem `qa-reviewer/shared/review-file-template.md` §Verdict.
|
|
346
347
|
|
|
347
348
|
> **Đây là contract, không phải định dạng cho đẹp.** `/qc-automation-assess` (Đợt 2 · b3) **loại**
|
|
348
349
|
> khỏi lượt mọi TC chưa `APPROVED`. Đổi chuỗi này là làm trạm đó mù — nên nếu phải đổi, đổi ở cả
|
|
@@ -401,9 +402,9 @@ Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
|
|
|
401
402
|
```
|
|
402
403
|
/qc-review-testcase Hoàn tất — {UC-ID} vòng #{N}
|
|
403
404
|
Điểm : {XX}/100 ({fail} FAIL × −5đ · {warn} WARN × −2đ){nếu có vòng trước: " ← vòng #{N-1}: {YY}/100"}
|
|
404
|
-
Verdict: {APPROVED |
|
|
405
|
+
Verdict: {APPROVED | APPROVED_WITH_SUGGESTIONS | REVISION_REQUIRED | REJECTED} — {n} findings ({blk} BLOCKER · {maj} MAJOR · {min} MINOR · {sug} SUGGESTION)
|
|
405
406
|
File : {qc_artifact_dir}test-cases/REVIEW_<FEATURE>.md (thêm 1 hàng vào bảng Tổng quan)
|
|
406
407
|
Self-review: {✅ sạch | ⚠️ {n} điểm cần chú ý — liệt kê}
|
|
407
|
-
Next (
|
|
408
|
-
(
|
|
408
|
+
Next (≥ APPROVED_WITH_SUGGESTIONS) : /qc-design-script {UC-ID}
|
|
409
|
+
(REVISION_REQUIRED | REJECTED → sửa TC bị gắn cờ bằng /qc-design-test {UC-ID}, rồi chạy lại lệnh này)
|
|
409
410
|
```
|
|
@@ -5,7 +5,7 @@ updated: 2026-09-16
|
|
|
5
5
|
|
|
6
6
|
# /qc-run-manualtest — Ghi kết quả test TAY vào sổ trace
|
|
7
7
|
|
|
8
|
-
>
|
|
8
|
+
> Trạm 8b/9 của dây chuyền QC automation — song song với trạm 8. QC chạy tay các TC mang `Automatable: N`, lệnh **hỏi từng TC** rồi ghi `qc_status`
|
|
9
9
|
> vào sổ trace. Không có lệnh này thì những scenario ấy nằm `not_run` vĩnh viễn — và `/qc-report`
|
|
10
10
|
> sẽ chấm cả PRD là **FAIL**, không cách nào sửa.
|
|
11
11
|
|
|
@@ -6,7 +6,7 @@ ported_from: ai-automation-qc-base
|
|
|
6
6
|
|
|
7
7
|
# /qc-run-script — Chạy automation script (ghi qc_status)
|
|
8
8
|
|
|
9
|
-
>
|
|
9
|
+
> Trạm 8/9 của dây chuyền QC automation. Chạy script **đã `APPROVED`**, phân loại mỗi FAIL, rồi ghi `qc_status` **chính thức**
|
|
10
10
|
> vào sổ trace. **Không sinh script** — đó là `/qc-design-script`.
|
|
11
11
|
|
|
12
12
|
## Gate
|
|
@@ -200,8 +200,8 @@ cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắ
|
|
|
200
200
|
|
|
201
201
|
| Đọc được | Làm gì |
|
|
202
202
|
|---|---|
|
|
203
|
-
| `APPROVED` |
|
|
204
|
-
| `
|
|
203
|
+
| `APPROVED` · `APPROVED_WITH_SUGGESTIONS` | **đi tiếp** — in một dòng bằng chứng:<br/>`✅ Cổng script đã soát: {verdict} — {đường dẫn file vừa đọc}` |
|
|
204
|
+
| `REVISION_REQUIRED` · `REJECTED` | **DỪNG** — `❌ Script chưa đạt. Sửa rồi soát lại bằng /qc-review-script {UC-ID}.` |
|
|
205
205
|
| Không có file | **DỪNG** — `❌ Chưa soát script. Chạy /qc-review-script {UC-ID} trước.` |
|
|
206
206
|
|
|
207
207
|
> **Cổng này là lý do `/qc-review` phải tách đôi** (Đợt 2 · b1). Biên bản cũ không nói nó soát
|
|
@@ -222,15 +222,22 @@ cả hai đều xảy ra trong im lặng, không có bước nào phía sau bắ
|
|
|
222
222
|
> hoặc **chạy 0 test mà vẫn báo xanh** — rồi con số đó đi thẳng vào `/qc-report` thành số liệu
|
|
223
223
|
> người ta tin. Đây là kiểu hỏng tệ nhất: một báo cáo xanh trên một lần chạy **không tồn tại**.
|
|
224
224
|
|
|
225
|
-
## Role & stack (theo
|
|
225
|
+
## Role & stack (module theo nền — bảng §2b của `steps/qc-scope.md`)
|
|
226
226
|
|
|
227
|
-
Bạn là **QC Script Runner**. Chạy
|
|
227
|
+
Bạn là **QC Script Runner**. Chạy script đã có **theo nền đã phân giải ở §2b**, thu bằng chứng, phân loại FAIL,
|
|
228
228
|
ghi kết quả theo từng scenario. **KHÔNG sửa script, KHÔNG sinh script.**
|
|
229
229
|
|
|
230
|
-
## Skills — chọn
|
|
230
|
+
## Skills — chọn NỀN, nạp MỘT file (`{paths.qc_skills_dir}/qa-script-runner/`)
|
|
231
231
|
|
|
232
|
-
`
|
|
233
|
-
|
|
232
|
+
**Nạp theo nền đã phân giải ở `steps/qc-scope.md` §2b:**
|
|
233
|
+
|
|
234
|
+
| `active_platform` | File |
|
|
235
|
+
|---|---|
|
|
236
|
+
| `web` · `webview` · `system` | `web/run.md` |
|
|
237
|
+
| `app` · `app-ios` · `app-android` | `mobile/run.md` |
|
|
238
|
+
|
|
239
|
+
Báo cáo sau lượt chạy: `report.md` — reporter **theo nền** *(Playwright HTML Report cho
|
|
240
|
+
web·system, Allure v2.x cho app)*.
|
|
234
241
|
|
|
235
242
|
---
|
|
236
243
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: "QC Playwright (TypeScript)"
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: "QC automation — Playwright + TypeScript. Phục vụ HAI nền: web (automation/) và API/system (api-automation/)"
|
|
4
|
+
language: "TypeScript"
|
|
5
|
+
framework: "Playwright Test"
|
|
6
|
+
stack_type: "qc-automation"
|
|
7
|
+
default_layer_order:
|
|
8
|
+
- Test case Markdown (.Test.md) — nguồn sự thật, review xong mới sinh code
|
|
9
|
+
- Test data (data/*.data.ts)
|
|
10
|
+
- Page Object (pages/*.page.ts) · API Object (api/*.api.ts)
|
|
11
|
+
- Fixture (fixtures/*.fixture.ts)
|
|
12
|
+
- Spec (tests/[feature]/*.spec.ts)
|
|
13
|
+
test_framework: "Playwright Test + expect"
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# QC automation module — Playwright + TypeScript.
|
|
2
|
+
#
|
|
3
|
+
# Nguồn: upstream/qc-base-new/Automation-Standards.md (Approved) §1 §2.3 §3 §6.1 §9.2
|
|
4
|
+
# upstream/qc-base-new/API-Testing-Standards.md (Approved) §1 §2.1 §7.2 §7.3
|
|
5
|
+
#
|
|
6
|
+
# Module này phục vụ HAI nền — web và system(API) — vì cả hai dùng CÙNG stack
|
|
7
|
+
# (AD-API-001: "Playwright API mode thay vì framework riêng, để tái dùng infrastructure
|
|
8
|
+
# với Web testing"). Tách làm hai module là khai dãy phiên bản Playwright/TS hai lần.
|
|
9
|
+
# Nền mobile ở modules/qc-wdio-appium (stack khác hẳn: WebdriverIO + Appium).
|
|
10
|
+
#
|
|
11
|
+
# CHỌN NỀN LÚC CHẠY: theo `active_platform` đã phân giải ở trạm 1 (steps/qc-scope.md).
|
|
12
|
+
# KHÔNG có key cấu hình riêng cho việc này — một pass QC đã khoá đúng một nền, hỏi lại
|
|
13
|
+
# bằng một field thứ hai là tạo hai đáp án cho một câu.
|
|
14
|
+
#
|
|
15
|
+
# web · webview → layout.web app · app-ios · … → qc-wdio-appium
|
|
16
|
+
# system → layout.api
|
|
17
|
+
|
|
18
|
+
versions:
|
|
19
|
+
playwright: "latest" # Playwright Test — runner + assertion + reporter, không thêm Jest/Mocha
|
|
20
|
+
typescript: "v5.x" # strict mode
|
|
21
|
+
|
|
22
|
+
build:
|
|
23
|
+
web:
|
|
24
|
+
test: "npx playwright test"
|
|
25
|
+
e2e: "npx playwright test tests/ --grep @e2e"
|
|
26
|
+
report: "npx playwright show-report"
|
|
27
|
+
show_trace: "npx playwright show-trace test-results/<test>/trace.zip"
|
|
28
|
+
api:
|
|
29
|
+
test: "npx playwright test --config=api-automation/playwright.config.ts"
|
|
30
|
+
report: "npx playwright show-report"
|
|
31
|
+
|
|
32
|
+
layout:
|
|
33
|
+
# §2.3 của Automation-Standards — mirror test-suites/, KHÔNG đổi tên thư mục.
|
|
34
|
+
web: |
|
|
35
|
+
automation/
|
|
36
|
+
├── playwright.config.ts
|
|
37
|
+
├── package.json · tsconfig.json
|
|
38
|
+
├── pages/ ← Page Object: base.page.ts · <feature>.page.ts
|
|
39
|
+
├── tests/ ← spec, mirror test-suites/: {TICKET-ID}/<feature>-happy-path.spec.ts
|
|
40
|
+
├── data/ ← <feature>.data.ts (ref TDS artifact)
|
|
41
|
+
├── fixtures/ ← base.fixture.ts
|
|
42
|
+
├── helpers/ ← <helper>.ts
|
|
43
|
+
└── reports/ ← sinh ra, gitignored
|
|
44
|
+
|
|
45
|
+
# §2.1 của API-Testing-Standards — thư mục gốc RIÊNG, "tách biệt với automation/ (web)
|
|
46
|
+
# để tránh xung đột config và dependency". api/ thay cho pages/; không có Page Object.
|
|
47
|
+
api: |
|
|
48
|
+
api-automation/
|
|
49
|
+
├── playwright.config.ts ← config riêng của API mode
|
|
50
|
+
├── package.json · tsconfig.json
|
|
51
|
+
├── api/ ← API Object: base.api.ts · <resource>.api.ts
|
|
52
|
+
├── tests/ ← {TICKET-ID}/<feature>-{happy-path,negative,security}.spec.ts
|
|
53
|
+
├── data/ ← <resource>.data.ts
|
|
54
|
+
├── fixtures/ ← api.fixture.ts (shared API context, auth token)
|
|
55
|
+
├── helpers/ ← schema.helper.ts · auth.helper.ts
|
|
56
|
+
└── reports/ ← sinh ra, gitignored
|
|
57
|
+
|
|
58
|
+
naming:
|
|
59
|
+
# §9.2 (web) · §7.2 (api). File kebab-case; class PascalCase; method camelCase verb-first.
|
|
60
|
+
page_object: "pages/<feature>.page.ts → class <Feature>Page extends BasePage"
|
|
61
|
+
api_object: "api/<resource>.api.ts → class <Resource>API extends BaseAPI"
|
|
62
|
+
spec: "tests/{TICKET-ID}/<feature>-<scenario>.spec.ts"
|
|
63
|
+
test_data: "data/<resource>.data.ts"
|
|
64
|
+
fixture: "fixtures/<name>.fixture.ts"
|
|
65
|
+
helper: "helpers/<name>.helper.ts"
|
|
66
|
+
test_case_md: "{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md"
|
|
67
|
+
|
|
68
|
+
locator_priority:
|
|
69
|
+
# §6.1 — chỉ áp cho nền web. API không có locator.
|
|
70
|
+
web: "getByRole → getByLabel → getByPlaceholder → getByTestId → getByText → locator('[css]') (last resort, ghi lý do)"
|
|
71
|
+
note: "Giá trị test-id lấy từ bảng Test Selectors §4.5.6 của tech-doc, KHÔNG scan runtime.
|
|
72
|
+
Tên thuộc tính đọc từ `@trace.testid_attr`; nếu ≠ data-testid thì phải gọi
|
|
73
|
+
`expect.configure`/`selectors.setTestIdAttribute` trước khi dùng getByTestId."
|
|
74
|
+
|
|
75
|
+
reporting:
|
|
76
|
+
web: "Playwright HTML Report" # §1 + OQ-01 đã đóng 2026-06-02: Phase 1 KHÔNG cần Allure
|
|
77
|
+
api: "Playwright HTML Report" # Allure defer Phase 2
|
|
78
|
+
|
|
79
|
+
trace_tags:
|
|
80
|
+
# Dấu comment là `//` (TypeScript) — stack cũ dùng `#`. Bộ parse bám chuỗi `@trace.*`,
|
|
81
|
+
# không bám dấu comment (bin/lint-trace.js:733), nên đổi dấu là an toàn; lane DEV đã
|
|
82
|
+
# dùng `//` từ trước.
|
|
83
|
+
verifies: "// @trace.verifies={UC-ID}-SC{N}"
|
|
84
|
+
source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
|
|
85
|
+
test_type: "// @trace.test_type=functional|integration|e2e|non-functional"
|
|
86
|
+
|
|
87
|
+
artifact_id_prefix:
|
|
88
|
+
# §7.3 API-Testing-Standards — dãy API độc lập với web/mobile.
|
|
89
|
+
api: "TS-API · SCN-API · TC-API · AUT-API · TDS-API"
|
|
90
|
+
|
|
91
|
+
# Luật VIẾT CODE (Page Object 3 lớp, assertion, wait, anti-pattern, flaky policy) KHÔNG ở
|
|
92
|
+
# đây — chúng ở skills/qc/qa-script-designer/_shared/web-conventions.md.
|
|
93
|
+
# Ranh giới: hồ sơ này trả lời "chạy ở đâu, đặt tên gì"; skill trả lời "viết thế nào".
|
|
94
|
+
# Vì sao tách: hồ sơ được đọc NGUYÊN vào ngữ cảnh mỗi lần chạy lệnh, còn skill nạp MỘT
|
|
95
|
+
# file theo lane — nhồi luật vào đây bắt mọi lần làm web phải đọc cả luật của nền khác.
|
|
96
|
+
|
|
97
|
+
# qc_status: /qc-run-script ghi pass|fail|skip|not_run + qc_run_at vào
|
|
98
|
+
# {trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv — song song với dev_selftest,
|
|
99
|
+
# và đây là kết quả QC CHÍNH THỨC hiện trên Living Docs.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
name: "QC WebdriverIO + Appium (mobile)"
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: "QC automation cho nền app — WebdriverIO v9 + Appium v2 + UiAutomator2, TypeScript"
|
|
4
|
+
language: "TypeScript"
|
|
5
|
+
framework: "WebdriverIO + Appium"
|
|
6
|
+
stack_type: "qc-automation"
|
|
7
|
+
default_layer_order:
|
|
8
|
+
- Test case Markdown (.Test.md) — nguồn sự thật, review xong mới sinh code
|
|
9
|
+
- Test data (data/*.data.ts)
|
|
10
|
+
- Screen Object (screens/*.screen.ts)
|
|
11
|
+
- Helper (api · device · gesture)
|
|
12
|
+
- Spec (tests/[feature]/*.spec.ts)
|
|
13
|
+
test_framework: "WebdriverIO + Appium + Allure"
|
|
14
|
+
|
|
15
|
+
# ⚠️ PHẠM VI HẸP — KHAI RÕ (PLAN_v2 §8 luật 4).
|
|
16
|
+
# Module này được port theo KHUNG từ Mobile-Automation-Standards.md (Approved) ở Bước S,
|
|
17
|
+
# và CHƯA được chạy thử trên một dự án mobile thật. Ba mục riêng của nền mobile (§6 API
|
|
18
|
+
# Helper · §9 Gesture Helper · §12 Environment Validation) đã có mặt, nhưng các con số
|
|
19
|
+
# trong đó (toạ độ swipe, timeout) là giá trị mặc định của chuẩn, chưa hiệu chỉnh theo
|
|
20
|
+
# thiết bị thật. Lần đầu chạy thật: đối chiếu lại §12 trước khi tin kết quả.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# QC automation module — WebdriverIO + Appium, nền app (mobile).
|
|
2
|
+
#
|
|
3
|
+
# Nguồn: upstream/qc-base-new/Mobile-Automation-Standards.md (Approved)
|
|
4
|
+
# §1 §2 §3 §6 §7.1 §9 §10.2 §12
|
|
5
|
+
#
|
|
6
|
+
# ⚠️ ĐÂY KHÔNG PHẢI BẢN COPY CỦA qc-playwright-ts. Chuẩn mobile dài hơn chuẩn web 129 dòng,
|
|
7
|
+
# và phần dôi ra không phải văn vẻ: §6 API Helper · §9 Gesture Helper · §12 Environment
|
|
8
|
+
# Validation Checklist. Một hồ sơ mobile copy từ web sẽ im lặng thiếu ba mục đó, và cái
|
|
9
|
+
# thiếu chỉ lộ ra khi có người chạy thật trên máy thật — tức SAU khi đã tin là xong.
|
|
10
|
+
#
|
|
11
|
+
# CHỌN NỀN LÚC CHẠY: theo `active_platform` ở trạm 1 (steps/qc-scope.md).
|
|
12
|
+
# app · app-ios · app-android → module này
|
|
13
|
+
# web · webview · system → qc-playwright-ts
|
|
14
|
+
|
|
15
|
+
versions:
|
|
16
|
+
appium: "v2.x" # latest
|
|
17
|
+
webdriverio: "v9.x" # latest — test runner
|
|
18
|
+
typescript: "v5.x"
|
|
19
|
+
android_driver: "UiAutomator2" # driver@latest
|
|
20
|
+
emulator: "Genymotion" # trial, latest
|
|
21
|
+
|
|
22
|
+
build:
|
|
23
|
+
test: "npx wdio ./wdio.config.ts"
|
|
24
|
+
android: "npx wdio ./wdio.android.config.ts"
|
|
25
|
+
dry_run: "npx wdio ./wdio.config.ts --dry-run"
|
|
26
|
+
appium: "npx appium"
|
|
27
|
+
report: "npx allure generate reports/allure-results --clean && npx allure open"
|
|
28
|
+
|
|
29
|
+
layout:
|
|
30
|
+
mobile: |
|
|
31
|
+
projects/[ProjectName]/mobile-automation/
|
|
32
|
+
├── wdio.config.ts ← WebdriverIO + Appium
|
|
33
|
+
├── wdio.android.config.ts ← override riêng Android
|
|
34
|
+
├── package.json ← dependency mobile RIÊNG
|
|
35
|
+
├── tsconfig.json · .env.example
|
|
36
|
+
├── screens/ ← Screen Object (≈ Page Object): base.screen.ts · <feature>.screen.ts
|
|
37
|
+
├── tests/ ← {TICKET-ID}/<feature>-{happy-path,negative,api-sync}.spec.ts
|
|
38
|
+
├── data/ ← <feature>.data.ts (dùng chung chuẩn với web)
|
|
39
|
+
├── fixtures/ ← base.fixture.ts
|
|
40
|
+
├── helpers/ ← api.helper.ts · device.helper.ts · gesture.helper.ts
|
|
41
|
+
└── reports/ ← Allure output, gitignored
|
|
42
|
+
|
|
43
|
+
naming:
|
|
44
|
+
# §10.2 — khác web: hậu tố "Screen", không phải "Page".
|
|
45
|
+
screen_object: "screens/<feature>.screen.ts → class <Feature>Screen extends BaseScreen"
|
|
46
|
+
spec: "tests/{TICKET-ID}/<feature>-<scenario>.spec.ts"
|
|
47
|
+
test_data: "data/<feature>.data.ts"
|
|
48
|
+
helper: "helpers/<name>.helper.ts"
|
|
49
|
+
test_case_md: "{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md"
|
|
50
|
+
|
|
51
|
+
locator_priority:
|
|
52
|
+
# §7.1 — KHÁC HẲN web. Không có getByRole/getByLabel.
|
|
53
|
+
order: "~accessibilityId → id (resource-id) → xpath (last resort, ghi lý do)"
|
|
54
|
+
note: "`~accessibilityId` dùng Android content-desc và YÊU CẦU dev gán. Giá trị lấy từ
|
|
55
|
+
bảng Test Selectors §4.5.6 của tech-doc, tên thuộc tính đọc từ `@trace.testid_attr`
|
|
56
|
+
(RN: testID · Flutter: Key/Semantics(identifier:) · native iOS: accessibilityIdentifier)."
|
|
57
|
+
|
|
58
|
+
# ── Ba mục CHỈ mobile mới có. Thiếu bất kỳ mục nào là hồ sơ chưa xong. ──
|
|
59
|
+
|
|
60
|
+
api_helper:
|
|
61
|
+
# §6 — mobile verify dữ liệu server bằng Playwright request, TÁI DÙNG từ automation/ (web).
|
|
62
|
+
file: "helpers/api.helper.ts"
|
|
63
|
+
impl: "class ApiHelper dùng `request`/`APIRequestContext` của @playwright/test;
|
|
64
|
+
baseUrl = process.env.API_BASE_URL"
|
|
65
|
+
why: "spec `*-api-sync.spec.ts` đối chiếu thứ hiện trên màn hình với thứ server thật có —
|
|
66
|
+
một màn hình hiển thị đúng dữ liệu CŨ vẫn là bug, và UI assertion không bắt được."
|
|
67
|
+
|
|
68
|
+
gesture_helper:
|
|
69
|
+
# §9 — web không cần mục này.
|
|
70
|
+
file: "helpers/gesture.helper.ts"
|
|
71
|
+
impl: "class GestureHelper — scrollDown · swipeLeft · … dựng bằng
|
|
72
|
+
browser.action('pointer', { parameters: { pointerType: 'touch' } })"
|
|
73
|
+
note: "Toạ độ mặc định trong chuẩn (x=540, startY=800, endY=300, duration=500) là giá trị
|
|
74
|
+
của MỘT cấu hình màn hình. Hiệu chỉnh theo thiết bị thật trước khi tin kết quả."
|
|
75
|
+
|
|
76
|
+
environment_validation:
|
|
77
|
+
# §12 — Gate 6B. Chạy TRƯỚC mọi lần execute mobile.
|
|
78
|
+
gate: "6B"
|
|
79
|
+
checklist:
|
|
80
|
+
- "Genymotion emulator đang chạy và `adb devices` thấy thiết bị"
|
|
81
|
+
- "APK đúng version đã install trên emulator"
|
|
82
|
+
- "App khởi động thành công (smoke check bằng tay)"
|
|
83
|
+
- "API_BASE_URL gọi được TỪ emulator: `adb shell curl ${API_BASE_URL}/health`"
|
|
84
|
+
- "Test data đã seed trên server (nếu cần)"
|
|
85
|
+
- ".env đã cấu hình đúng environment hiện tại"
|
|
86
|
+
- "Appium server connect được: `npx appium` chạy không lỗi"
|
|
87
|
+
- "WDIO dry-run pass: `npx wdio ./wdio.config.ts --dry-run`"
|
|
88
|
+
why: "Tám mục này là ranh giới giữa 'test đỏ' và 'môi trường chưa sẵn sàng'. Bỏ qua thì
|
|
89
|
+
mọi FAIL đều trông như product-gap, và QC đi mở bug cho một cái emulator chưa bật."
|
|
90
|
+
|
|
91
|
+
reporting:
|
|
92
|
+
# §1 — ⚠️ NGƯỢC với luật "No Allure" của stack cũ và của nền web.
|
|
93
|
+
tool: "Allure Report v2.x"
|
|
94
|
+
note: "Nền web dùng Playwright HTML Report (OQ-01 đóng 2026-06-02: Allure defer Phase 2).
|
|
95
|
+
Nền mobile thì Allure là BẮT BUỘC theo §1. Hai nền khác nhau ở điểm này — đừng
|
|
96
|
+
'thống nhất' chúng lại; đó là quyết định của chuẩn, không phải chỗ sót."
|
|
97
|
+
|
|
98
|
+
trace_tags:
|
|
99
|
+
verifies: "// @trace.verifies={UC-ID}-SC{N}"
|
|
100
|
+
source: "// @trace.source=specs/{domain}/{prd-slug}/bdd/{platform}/{UC-ID}-{slug}.feature"
|
|
101
|
+
test_type: "// @trace.test_type=functional|integration|e2e|non-functional"
|
|
102
|
+
|
|
103
|
+
# Luật VIẾT CODE ở skills/qc/qa-script-designer/_shared/mobile-conventions.md.
|
|
104
|
+
# Ranh giới: hồ sơ này trả lời "chạy ở đâu, đặt tên gì"; skill trả lời "viết thế nào".
|
|
105
|
+
|
|
106
|
+
# qc_status: /qc-run-script ghi pass|fail|skip|not_run + qc_run_at vào
|
|
107
|
+
# {trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv
|
|
@@ -60,7 +60,7 @@ Ghi vào **mục Data Flow** của `{qc_artifact_dir}REQUIREMENT_ANALYSIS.md`
|
|
|
60
60
|
- Sơ đồ/list luồng dữ liệu cho mỗi kịch bản chính.
|
|
61
61
|
- Danh sách integration point + state change + failure point.
|
|
62
62
|
- Gợi ý loại test cần cho từng điểm (gui-feature / integration / e2e) khi sang qa-designer.
|
|
63
|
-
- Dữ liệu/trạng thái cần chuẩn bị & cleanup → đầu vào fixture cho qa-
|
|
63
|
+
- Dữ liệu/trạng thái cần chuẩn bị & cleanup → đầu vào fixture cho `qa-script-designer`.
|
|
64
64
|
|
|
65
65
|
Chặng nào luồng/hành vi chưa rõ (vd lỗi xử lý ra sao, retry, partial commit) →
|
|
66
66
|
ghi vào `{qc_artifact_dir}DOC_GAP.md` (loại MISSING / OPEN QUESTION).
|
|
@@ -99,9 +99,12 @@ biến một TC đang `Y` thành `N`.
|
|
|
99
99
|
tag `@trace.verifies`. Không có cột này thì `/qc-run-script` phải suy đường dẫn từ quy ước đặt
|
|
100
100
|
tên — suy sai thì chạy sai bộ test, hoặc **chạy 0 test mà vẫn báo xanh**.
|
|
101
101
|
|
|
102
|
-
> **Đường dẫn theo
|
|
103
|
-
> `
|
|
104
|
-
> `
|
|
102
|
+
> **Đường dẫn theo module đã phân giải ở `steps/qc-scope.md` §2b** — `qc-playwright-ts`
|
|
103
|
+
> *(web · system)* hoặc `qc-wdio-appium` *(app)*, mục `§layout.{web|api|mobile}` của
|
|
104
|
+
> `stack-profile.yaml` tương ứng. **Đừng viết cứng tên module ở đây.**
|
|
105
|
+
>
|
|
106
|
+
> *(Tên file theo `§naming` của module: `<feature>.page.ts` + `<feature>-<scenario>.spec.ts`
|
|
107
|
+
> (web) · `<resource>.api.ts` (system) · `<feature>.screen.ts` (app).)*
|
|
105
108
|
>
|
|
106
109
|
> *(Đề xuất gốc của đội QC viết theo TypeScript + Playwright Test / WebdriverIO. Việc đổi stack
|
|
107
110
|
> là một bước RIÊNG, cố ý tách khỏi đợt tách lệnh — xem quyết định F3, Đợt 2 · b2. Khi stack
|
|
@@ -28,9 +28,15 @@ expected/actual) · `#QUESTION`, `#IDEA` placeholder · summary cuối session.
|
|
|
28
28
|
## Mode 2 — Convert Findings
|
|
29
29
|
Input: session note (#BUG + #IDEA).
|
|
30
30
|
- **Bug report** mỗi #BUG: title, severity, priority, steps to reproduce, expected/actual, hypothesis root cause.
|
|
31
|
-
- **Functional TC mới
|
|
32
|
-
|
|
31
|
+
- **Functional TC mới → KHÔNG viết luật ở đây.** Dùng `explore-to-functional.md` Phase 4 — nó có
|
|
32
|
+
format `TC_<FEATURE>.Test.md` đầy đủ (metadata list, Trace BR, 🚫 Block, Test Data, Steps,
|
|
33
|
+
Expected 1 bullet, Trace matrix). Chỉ thêm một điều riêng của đường này: mỗi TC sinh từ session
|
|
34
|
+
phải mang `Origin: Exploratory session <date>`.
|
|
33
35
|
- **Weekly summary** (nếu yêu cầu): overview, top findings, coverage gap, recommendations.
|
|
34
36
|
|
|
37
|
+
> **Vì sao Mode 2 trỏ đi chứ không tự viết** *(Bước S · S2, 2026-09-17)*: bản cũ mô tả lại format TC
|
|
38
|
+
> bằng một câu rút gọn, trong khi `explore-to-functional.md` Phase 4 đã có bản đủ. Hai bản của một
|
|
39
|
+
> format thì bản ngắn sẽ lạc hậu trước — và người đọc bản ngắn không biết mình đang đọc bản cũ.
|
|
40
|
+
|
|
35
41
|
## Output
|
|
36
42
|
Mode 1: file session note. Mode 2: bug reports + file TC trong `{qc_artifact_dir}test-cases/` + summary.
|
|
@@ -16,7 +16,7 @@ Nạp cùng `shared/` (khuôn + độ chính xác + từ điển hành động)
|
|
|
16
16
|
|
|
17
17
|
## Khi KHÔNG trigger
|
|
18
18
|
- Test qua giao diện → `functional/gui-screen`/`gui-feature`
|
|
19
|
-
- Luồng dữ liệu API ↔ DB/service khác → `integration/api` · message/event → `integration/
|
|
19
|
+
- Luồng dữ liệu API ↔ DB/service khác → `integration/api` · message/event → `integration/queue`
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-17
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Test Case — Job chạy ngầm *(tự chạy theo lịch hoặc điều kiện)*
|
|
7
|
+
|
|
8
|
+
Skill **tự chứa** để viết TC cho một việc **không ai gọi**: nó tự thức dậy theo lịch, theo ngưỡng,
|
|
9
|
+
hoặc theo một cờ trong dữ liệu. Chỉ cần load file này.
|
|
10
|
+
|
|
11
|
+
## Khi nào trigger
|
|
12
|
+
- Nền `system`, và hình dạng đã chốt là **job** *(xem `/qc-design-test` §Nền `system`)*.
|
|
13
|
+
- Ví dụ: dọn dữ liệu quá hạn lúc 2h sáng · tổng hợp báo cáo cuối ngày · gửi nhắc hạn ·
|
|
14
|
+
đồng bộ định kỳ với hệ ngoài · batch/ETL.
|
|
15
|
+
|
|
16
|
+
## Khi KHÔNG trigger
|
|
17
|
+
- Có endpoint, ai đó gọi vào → `functional/api.md`
|
|
18
|
+
- Nằm chờ message rồi xử lý → `integration/queue.md`
|
|
19
|
+
- Chỉ verify bản ghi DB sau **một thao tác của người** → `integration/db.md`
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Format file TC
|
|
24
|
+
|
|
25
|
+
> **Nạp `{paths.qc_skills_dir}/qa-designer/shared/tc-metadata-format.md`** — khuôn TC, luật
|
|
26
|
+
> ATOMIC (1 kết cục = 1 TC), phân nhóm, Trace + `@trace.verifies`, `🚫 Block`.
|
|
27
|
+
> **Không lặp lại luật format ở đây.**
|
|
28
|
+
>
|
|
29
|
+
> Khi viết Expected Result / Test Data: nạp thêm `shared/precision-rules.md` +
|
|
30
|
+
> `shared/action-keywords-glossary.md`.
|
|
31
|
+
|
|
32
|
+
**`Tags` của mọi TC ở đây mang lane `job`.** Trạm 5 và trạm 6 đọc nó để không phải hỏi lại.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 1 · Ba thứ phải chốt TRƯỚC khi viết TC
|
|
37
|
+
|
|
38
|
+
Job khác API ở chỗ **không có request để mô tả**. Thay vào đó phải chốt ba thứ, và **thiếu cái
|
|
39
|
+
nào thì dừng hỏi, đừng đoán**:
|
|
40
|
+
|
|
41
|
+
| | Chốt gì | Nếu thiếu |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| **Kích hoạt** | Trong môi trường test, job được làm cho chạy bằng cách nào? *(lịch bắn thật · gọi tay qua CLI/endpoint quản trị · cắm cờ trong DB · đẩy một message)* | Ghi `🚫 Block: [GAP-…]` — không có cách kích hoạt thì **không TC nào chạy được** |
|
|
44
|
+
| **Cửa sổ dữ liệu** | Lượt chạy này **nhặt những bản ghi nào**? *(tạo trước mốc nào · trạng thái nào · giới hạn bao nhiêu bản ghi một lượt)* | Không biết cửa sổ thì không dựng được Test Data, và Expected Result thành *"xử lý đúng"* — một cụm bị cấm |
|
|
45
|
+
| **Dấu vết quan sát được** | Sau khi chạy xong, **nhìn vào đâu** để biết nó đã làm? *(bản ghi đổi trạng thái · file sinh ra · message phát đi · thông báo gửi đi · số liệu/log)* | Không có dấu vết thì TC không có oracle — nó không đỗ/trượt được |
|
|
46
|
+
|
|
47
|
+
> **Đây là chỗ job hay bị viết hụt nhất.** Người viết quen với API: có request, có response, oracle
|
|
48
|
+
> hiển nhiên. Job **không trả gì cả** — oracle nằm ở **thay đổi trạng thái**, và nếu không chốt
|
|
49
|
+
> trước thì Expected Result sẽ trôi về *"job chạy thành công"*, một câu không kiểm được.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2 · Chín nhóm TC bắt buộc soi
|
|
54
|
+
|
|
55
|
+
Sáu nhóm từ **4** trở xuống là **rủi ro riêng của job** — không skill nào khác trong framework
|
|
56
|
+
phủ chúng. Bỏ nhóm nào thì nêu rõ **vì sao bỏ**, đừng im lặng.
|
|
57
|
+
|
|
58
|
+
### 1 · Đường thuận
|
|
59
|
+
Có dữ liệu đúng trong cửa sổ → chạy → **từng dấu vết ở §1 đổi đúng như mong đợi**.
|
|
60
|
+
Assert cả ba mặt nếu có: bản ghi · message phát ra · thông báo.
|
|
61
|
+
|
|
62
|
+
### 2 · Không nhặt thứ ngoài cửa sổ
|
|
63
|
+
Bản ghi **ngoài** điều kiện *(sai trạng thái, tạo sau mốc)* → chạy → **bản ghi đó KHÔNG đổi**.
|
|
64
|
+
Đây là assert **phủ định**, và là nhóm hay bị đánh rơi nhất khi rút gọn TC.
|
|
65
|
+
|
|
66
|
+
### 3 · Lượt chạy rỗng
|
|
67
|
+
Không có bản ghi nào để làm → chạy → **không lỗi, không phát message, không gửi thông báo**.
|
|
68
|
+
Job báo lỗi khi rỗng là bug; job gửi thông báo *"đã xử lý 0 bản ghi"* mỗi đêm cũng là bug.
|
|
69
|
+
|
|
70
|
+
### 4 · Chạy lại lần hai cùng dữ liệu *(idempotency)*
|
|
71
|
+
Chạy xong lần 1 → chạy lại ngay lần 2 trên cùng dữ liệu → **hiệu ứng chỉ xảy ra một lần**:
|
|
72
|
+
không trừ tiền hai lần, không gửi mail hai lần, không tạo bản ghi trùng.
|
|
73
|
+
|
|
74
|
+
> **Đây là bug kinh điển nhất của job chạy ngầm.** Nó xuất hiện thật khi lịch chạy chồng, khi
|
|
75
|
+
> có người kích tay lúc job đang chạy, hoặc khi hệ thống khởi động lại giữa chừng.
|
|
76
|
+
|
|
77
|
+
### 5 · Hỏng giữa chừng
|
|
78
|
+
Cho lỗi ở bản ghi thứ **k** của **n** *(k nằm giữa)* → phải trả lời được **hai** câu, và TC phải
|
|
79
|
+
ghi rõ thiết kế chọn đường nào:
|
|
80
|
+
|
|
81
|
+
| Đường | Kỳ vọng |
|
|
82
|
+
|---|---|
|
|
83
|
+
| **Dừng cả lượt** | k−1 bản ghi đầu **đã xong** phải giữ nguyên, hay bị rollback hết? |
|
|
84
|
+
| **Bỏ qua bản lỗi, chạy tiếp** | bản thứ k có được ghi lại ở đâu không? Lượt sau có nhặt lại nó không? |
|
|
85
|
+
|
|
86
|
+
Chạy lại sau khi hỏng: **k−1 bản đầu KHÔNG được xử lý lần thứ hai** *(nối với nhóm 4)*.
|
|
87
|
+
|
|
88
|
+
### 6 · Hai tiến trình cùng lúc
|
|
89
|
+
Kích hai lượt chạy chồng nhau → **không bản ghi nào bị xử lý hai lần**. Hoặc job phải **từ chối**
|
|
90
|
+
lượt thứ hai *(có khoá)*, hoặc hai lượt chia nhau bản ghi — **thiết kế chọn đường nào phải ghi
|
|
91
|
+
trong TC**, vì hai đường có Expected Result khác hẳn.
|
|
92
|
+
|
|
93
|
+
### 7 · Biên của cửa sổ
|
|
94
|
+
Bản ghi tạo **đúng mốc** · **trước mốc một đơn vị** · **sau mốc một đơn vị** → nhặt đúng cái phải
|
|
95
|
+
nhặt. Và ca khó hơn: bản ghi **được tạo trong lúc job đang chạy** — lượt này lấy hay để lượt sau?
|
|
96
|
+
|
|
97
|
+
> Nêu **đơn vị** tường minh *(giây? ngày? theo múi giờ nào?)* — `precision-rules.md` cấm mốc mơ hồ.
|
|
98
|
+
|
|
99
|
+
### 8 · Bản ghi độc
|
|
100
|
+
Một bản ghi hỏng *(dữ liệu sai định dạng, tham chiếu chết)* → nó **không được làm chết cả lượt**,
|
|
101
|
+
trừ khi thiết kế cố ý thế. Ghi rõ đường nào, và bản ghi độc đi đâu.
|
|
102
|
+
|
|
103
|
+
### 9 · Thử lại và trần
|
|
104
|
+
Job gọi ra ngoài mà bên kia lỗi → thử lại mấy lần, cách nhau bao lâu, **trần ở đâu**?
|
|
105
|
+
Không có trần là job treo tới khi có người tắt.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 3 · Phân nhóm trong file TC
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
1 Đường thuận ← nhóm 1
|
|
113
|
+
2 Cửa sổ & biên ← nhóm 2, 7
|
|
114
|
+
3 Chạy lặp & đồng thời ← nhóm 4, 6
|
|
115
|
+
4 Hỏng & phục hồi ← nhóm 5, 8, 9
|
|
116
|
+
5 Lượt rỗng ← nhóm 3
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 4 · Test Data — khác API ở chỗ nào
|
|
122
|
+
|
|
123
|
+
Job **không nhận payload**; dữ liệu của nó là **trạng thái có sẵn trong hệ thống**. Nên Test Data
|
|
124
|
+
của TC job là một **bảng bản ghi phải seed trước**, kèm ba cột tối thiểu: định danh · trạng thái ·
|
|
125
|
+
mốc thời gian liên quan tới cửa sổ.
|
|
126
|
+
|
|
127
|
+
Và phải nêu **dọn thế nào** — job đổi trạng thái thật, nên chạy hai lần liên tiếp mà không dọn
|
|
128
|
+
thì lượt sau đã không còn ở điều kiện ban đầu *(và đó chính là nhóm 4 nếu cố ý, là nhiễu nếu vô ý)*.
|
|
@@ -15,7 +15,7 @@ verify luồng dữ liệu & contract giữa các thành phần. Chỉ cần loa
|
|
|
15
15
|
|
|
16
16
|
## Khi KHÔNG trigger
|
|
17
17
|
- Chỉ verify request/response 1 endpoint → `functional/api`
|
|
18
|
-
- Verify riêng trạng thái DB → `integration/db` · message/event → `integration/
|
|
18
|
+
- Verify riêng trạng thái DB → `integration/db` · message/event → `integration/queue`
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -13,7 +13,7 @@ insert/update/soft-delete đúng giá trị, side-effect, toàn vẹn. Chỉ c
|
|
|
13
13
|
- Kiểm tra bản ghi DB sau thao tác (tạo ticket → ghi đúng bảng/cột); soft-delete, default, audit log
|
|
14
14
|
|
|
15
15
|
## Khi KHÔNG trigger
|
|
16
|
-
- Chỉ verify response API → `functional/api`/`integration/api` · message/event → `integration/
|
|
16
|
+
- Chỉ verify response API → `functional/api`/`integration/api` · message/event → `integration/queue`
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -4,16 +4,32 @@ updated: 2026-06-11
|
|
|
4
4
|
ported_from: ui-automation-testing
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Test Case — Integration
|
|
7
|
+
# Test Case — Integration hàng đợi (Message/Event)
|
|
8
8
|
|
|
9
|
-
Skill **tự chứa** để viết TC tích hợp qua
|
|
10
|
-
|
|
9
|
+
Skill **tự chứa** để viết TC tích hợp qua hàng đợi/message bus — Kafka, RabbitMQ, SQS, hay bất
|
|
10
|
+
kỳ cơ chế nào có **người gửi** và **người nhận** tách rời: producer phát event đúng, consumer xử
|
|
11
|
+
lý đúng, đảm bảo ordering/idempotency/retry. Chỉ cần load file này.
|
|
12
|
+
|
|
13
|
+
> **Tên file đổi từ `kafka.md` (2026-09-17):** nội dung chưa bao giờ phụ thuộc Kafka — nó nói về
|
|
14
|
+
> **hình dạng hàng đợi**. Giữ tên một công nghệ cụ thể làm người dùng RabbitMQ/SQS tưởng không
|
|
15
|
+
> áp dụng được.
|
|
11
16
|
|
|
12
17
|
## Khi nào trigger
|
|
13
|
-
|
|
18
|
+
|
|
19
|
+
Hai phía, **cùng một file** — nêu rõ TC đang đứng ở phía nào:
|
|
20
|
+
|
|
21
|
+
| Phía | Khi nào | Ví dụ |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| **Người gửi** *(producer)* | một action sinh ra event | tạo ticket → phát event sang CRM; verify topic · key · payload · điều kiện phát |
|
|
24
|
+
| **Người nhận** *(consumer)* | service **nằm chờ**, có message tới thì xử lý — **không action nào của người đứng trước** | đơn hàng mới vào hàng đợi → service kho trừ tồn; verify xử lý đúng · khử trùng · lỗi thì đi đâu |
|
|
25
|
+
|
|
26
|
+
> **Phía người nhận là chỗ hay bị bỏ sót.** Khung cũ chỉ viết *"Action sinh event"* — tức luôn
|
|
27
|
+
> giả định có một thao tác đứng trước. Một consumer thuần thì **không có thao tác đó**, và TC
|
|
28
|
+
> phải bắt đầu bằng *"có message X trên hàng đợi Y"*, không phải bằng một hành động của người.
|
|
14
29
|
|
|
15
30
|
## Khi KHÔNG trigger
|
|
16
31
|
- Tích hợp đồng bộ qua API → `integration/api` · verify DB → `integration/db`
|
|
32
|
+
- **Tự chạy theo lịch, không có message nào kích** → `functional/job.md`
|
|
17
33
|
|
|
18
34
|
---
|
|
19
35
|
|
|
@@ -11,6 +11,21 @@ upstream_sha: 57125f0c21512f2abcc55d00420e92c84c95fc8f
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## Bước 0 — TC đã có lane chưa? *(hỏi TRƯỚC mọi câu khác)*
|
|
15
|
+
|
|
16
|
+
Nếu `Tags` của TC đã mang một `<lane>` — `ui` · `api` · `job` · `queue` · `db` · `e2e` · `nfr` —
|
|
17
|
+
thì **ĐỌC nó, dừng ở đây, không suy lại**. Bảng lane ↔ skill ở
|
|
18
|
+
`shared/tc-metadata-format.md` §Tags.
|
|
19
|
+
|
|
20
|
+
> **Vì sao dừng chứ không "kiểm tra lại cho chắc".** Với nền `system`, lane là **câu trả lời của
|
|
21
|
+
> QC** ở trạm 3 cho một câu mà máy không suy được *(xem `/qc-design-test` §Nền `system`)*. Suy lại
|
|
22
|
+
> là đặt phán đoán của máy lên trên câu trả lời của người — và khi hai bên lệch, TC và script sẽ
|
|
23
|
+
> kiểm hai thứ khác nhau mà **cả hai đều chạy được**.
|
|
24
|
+
>
|
|
25
|
+
> Chưa có lane → đi tiếp Bước 1.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
14
29
|
## Bước 1 — Đối tượng test là gì?
|
|
15
30
|
|
|
16
31
|
```
|
|
@@ -18,6 +33,8 @@ upstream_sha: 57125f0c21512f2abcc55d00420e92c84c95fc8f
|
|
|
18
33
|
├── Hiển thị / validation / state của 1 screen → [A] Xét tiếp Bước 2 (UI vs Integration GUI)
|
|
19
34
|
├── User thực hiện workflow có mục tiêu nghiệp vụ → [B] Xét tiếp Bước 3 (E2E vs Integration)
|
|
20
35
|
├── 1 API endpoint (request/response/mã lỗi) → api-testcase-designer
|
|
36
|
+
├── Việc TỰ CHẠY theo lịch/điều kiện, không ai gọi → functional/job.md
|
|
37
|
+
├── Nằm chờ message rồi xử lý → integration/queue.md
|
|
21
38
|
├── NFR (performance/security/a11y/i18n) → nfr-testcase-designer
|
|
22
39
|
└── Luồng đa màn nằm trong 1 feature, không xuyên hệ thống → ui-testcase-designer (gui-feature)
|
|
23
40
|
```
|