@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,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
|
|
|
@@ -46,4 +46,4 @@ Nhóm TC: happy (dữ liệu đúng đầu→cuối) → contract negative (inpu
|
|
|
46
46
|
|
|
47
47
|
Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ưu tiên P0 cho định tuyến & tiền-dữ liệu. Chuỗi gọi phụ thuộc nhau: `../api/crud-sequence.md`.
|
|
48
48
|
|
|
49
|
-
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
|
|
49
|
+
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
|
|
@@ -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
|
|
|
@@ -42,4 +42,4 @@ Nhóm TC: ghi đúng giá trị (happy) → default/null đúng → update khôn
|
|
|
42
42
|
|
|
43
43
|
Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ghi rõ query kiểm tra DB + yêu cầu cleanup; không hardcode ID, chuẩn bị/dọn data qua fixture (3 mức teardown: `../shared/precision-rules.md` §8).
|
|
44
44
|
|
|
45
|
-
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
|
|
45
|
+
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
|
|
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
|
|
|
44
44
|
|
|
45
45
|
Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 4 Integration (qua UI)**. Đây là tầng verify dòng dữ liệu API → giao diện, nên **vẫn thuộc file giao diện**: bỏ UI đi thì TC mất nghĩa.
|
|
46
46
|
|
|
47
|
-
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
|
|
47
|
+
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
|
|
@@ -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
|
|
|
@@ -44,4 +60,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
|
|
|
44
60
|
|
|
45
61
|
Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Mỗi TC ghi topic, key, payload cần verify + hành vi consumer.
|
|
46
62
|
|
|
47
|
-
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
|
|
63
|
+
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
|
|
@@ -44,4 +44,4 @@ Trace BR; gap chặn → 🚫 Block.
|
|
|
44
44
|
|
|
45
45
|
Ghi vào file theo cùng câu hỏi phân file *"verify được mà không cần UI?"*: a11y · responsive · touch-target → `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` **Nhóm 5 NFR**; tải/hiệu năng/bảo mật ở tầng API → `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md`. Mỗi TC ghi tiêu chí đo + ngưỡng + công cụ, đơn vị theo `../shared/precision-rules.md` §3.
|
|
46
46
|
|
|
47
|
-
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
|
|
47
|
+
**Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review-testcase`.
|
|
@@ -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
|
```
|
|
@@ -5,7 +5,12 @@ ported_from: ui-automation-testing
|
|
|
5
5
|
upstream_path: skills/qa-tc-designer/shared/tc-metadata-format.md
|
|
6
6
|
upstream_sha: a31d66a7a8dab19cf821c9102a88282b09e16cb9
|
|
7
7
|
---
|
|
8
|
-
# TC Metadata Format
|
|
8
|
+
# TC Metadata Format
|
|
9
|
+
|
|
10
|
+
> **`Automatable` KHÔNG phải một field của `.Test.md`.** Quyết định *"TC này máy chạy được hay
|
|
11
|
+
> phải chạy tay"* sống ở **đúng một chỗ**: `{qc_artifact_dir}AUTOMATION_ASSESSMENT.md`, do
|
|
12
|
+
> `/qc-automation-assess` ghi. Đừng chép giá trị đó vào đây — hai nơi ghi cùng một quyết định
|
|
13
|
+
> thì một nơi sẽ lệch, và lúc đó không ai biết nơi nào đúng. (Chuẩn chung)
|
|
9
14
|
|
|
10
15
|
## ⚠️ Nguyên tắc format file TC (BẮT BUỘC — QC yêu cầu)
|
|
11
16
|
|
|
@@ -56,6 +61,23 @@ Mỗi trường 1 dòng, không bảng, không emoji dư:
|
|
|
56
61
|
- **Status:** Draft
|
|
57
62
|
- **Author:** AI
|
|
58
63
|
- **Tags:** <lane>, <loại: smoke|sanity|regression>, <feature-tag>
|
|
64
|
+
|
|
65
|
+
**`<lane>` — giá trị hợp lệ** *(khai 2026-09-17; trước đó để ngỏ nên mỗi file viết một kiểu)*:
|
|
66
|
+
|
|
67
|
+
| Lane | Khi nào | Skill thiết kế |
|
|
68
|
+
|---|---|---|
|
|
69
|
+
| `ui` | có màn hình | `functional/gui-screen` · `gui-feature` |
|
|
70
|
+
| `api` | có endpoint, ai đó gọi vào | `functional/api` · `integration/api` |
|
|
71
|
+
| `job` | **tự chạy** theo lịch/điều kiện, không ai gọi | `functional/job` |
|
|
72
|
+
| `queue` | nằm chờ message rồi xử lý | `integration/queue` |
|
|
73
|
+
| `db` | verify trạng thái dữ liệu sau thao tác | `integration/db` |
|
|
74
|
+
| `e2e` | hành trình xuyên nhiều màn/hệ | `e2e/journey` |
|
|
75
|
+
| `nfr` | hiệu năng · bảo mật · a11y · i18n | `non-functional` |
|
|
76
|
+
|
|
77
|
+
> **Lane là câu trả lời đã chốt, không phải nhãn trang trí.** Với nền `system`, nó do **QC trả
|
|
78
|
+
> lời** ở trạm 3 khi không suy được hình dạng *(xem `/qc-design-test` §Nền `system`)*. Trạm 5 và
|
|
79
|
+
> trạm 6 **ĐỌC** lane này, **không suy lại** — suy lại là mở đường cho hai trạm kết luận khác nhau
|
|
80
|
+
> về cùng một TC.
|
|
59
81
|
- **Trace:** BR-xx (ID gốc trong PRD/BDD ở `{paths.specs_dir}`)
|
|
60
82
|
- **@trace.verifies:** {UC-ID}-SC{N}
|
|
61
83
|
- **🚫 Block:** [GAP-UC{N}-{nnn}](../DOC_GAP.md) — <lý do> *(chỉ khi có)*
|
|
@@ -205,7 +227,7 @@ Mọi thứ trên là chuẩn của đội QC. Bốn thứ dưới đây là **c
|
|
|
205
227
|
**Câu hỏi phân file:** *"TC này verify được mà **không cần UI** không?"*
|
|
206
228
|
→ **có** = file API · **không** = file giao diện. *(Trùng Bước 2 của `skill-decision-tree.md`.)*
|
|
207
229
|
|
|
208
|
-
⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-
|
|
230
|
+
⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-design-script` và `/qc-review-testcase` tìm `*.Test.md`;
|
|
209
231
|
ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm thấy**, và không có gì báo lỗi.
|
|
210
232
|
|
|
211
233
|
Đánh số `TC_<FEATURE>_NNN` **liên tục toàn file**, không đánh lại theo từng nhóm.
|
|
@@ -215,7 +237,7 @@ ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm th
|
|
|
215
237
|
| Trường | Dạng | Vì sao cần |
|
|
216
238
|
|---|---|---|
|
|
217
239
|
| `**Trace:**` | `[BR-xx](../REQUIREMENT_ANALYSIS.md#3-business-rules)` — không có BR → `⚠️ Chưa có Business Rule` | truy về luật nghiệp vụ |
|
|
218
|
-
| `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-
|
|
240
|
+
| `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-script` ghi `qc_status` theo từng kịch bản vào sổ trace |
|
|
219
241
|
|
|
220
242
|
Một `SC` map được nhiều TC. **Thiếu `@trace.verifies` thì kết quả chạy không vào được sổ** — TC
|
|
221
243
|
vẫn chạy, vẫn pass/fail, nhưng không ai biết nó phủ kịch bản nào.
|
|
@@ -241,7 +263,7 @@ Nguồn & phiên bản: BDD {UC-ID} `<vX.Y>` · tech-doc `<rev | —>`
|
|
|
241
263
|
```
|
|
242
264
|
|
|
243
265
|
Lấy `<vX.Y>` từ `| **Version** |` ở header `.feature` của **chính UC này**, và `<rev>` từ header
|
|
244
|
-
tech-doc gộp. `/qc-review` và `/qc-
|
|
266
|
+
tech-doc gộp. `/qc-review-testcase` và `/qc-design-script` **so** khối này với version hiện tại để biết bộ TC còn
|
|
245
267
|
khớp spec không (`steps/qc-stamp.md` · `bin/trace-schema.json` → `qc_artifact_stamp`).
|
|
246
268
|
|
|
247
269
|
**Vì sao cần, khi sổ trace đã có `qc_status`.** `/generate-bdd` hạ `qc_status → not_run` khi spec đổi
|
|
@@ -259,8 +281,8 @@ Test-ID attribute: {attr}
|
|
|
259
281
|
```
|
|
260
282
|
|
|
261
283
|
Đọc `@trace.testid_attr` từ header tech-doc gộp (do `/map-testids` ghi). Bảng §4.5.6 chỉ cho
|
|
262
|
-
**giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-
|
|
263
|
-
locator, `/qc-review` cần nó để biết selector trong script có đúng hợp đồng không.
|
|
284
|
+
**giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-design-script` cần nó để cấu hình
|
|
285
|
+
locator, `/qc-review-script` cần nó để biết selector trong script có đúng hợp đồng không.
|
|
264
286
|
|
|
265
287
|
Thiếu field trong tech-doc → ghi `Test-ID attribute: — (thiếu @trace.testid_attr, chạy /map-testids)`.
|
|
266
288
|
**Đừng bỏ trống và đừng tự đoán** — đoán sai thì mọi locator trượt 100%, và trượt vì lý do
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-17
|
|
4
|
+
source: upstream/qc-base-new/AGT-006-code_reviewer.md §3.1 §3.2 §3.3 §4 (Draft) · §5 Boundary
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Luật soát script — dùng chung cho mọi nền
|
|
8
|
+
|
|
9
|
+
**Nạp file này TRƯỚC file lane.** Lane chỉ nói *"nền này soát thêm gì"*; mọi thứ ở đây đúng cho
|
|
10
|
+
cả `web` · `mobile` · `api`. Viết một bản vì 11 file lane đều cần — 11 bản của một luật là nơi
|
|
11
|
+
drift sống.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1 · Bảy luật của lượt soát *(R01–R07)*
|
|
16
|
+
|
|
17
|
+
| Mã | Luật | Nghĩa khi soát |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **R01** | **Review All Files** | Soát **mọi** file được đưa: spec · Page/Screen/API Object · data. Soát một phần rồi kết luận là kết luận về một thứ chưa đọc |
|
|
20
|
+
| **R02** | **Evidence-Based Findings** | Mỗi lỗi phải có đủ **bốn**: tên file · số dòng (hoặc đoạn code) · mô tả vấn đề · cách sửa đề nghị. Thiếu một trong bốn thì đó là cảm tưởng, không phải finding |
|
|
21
|
+
| **R03** | **No Silent Pass** | Không `APPROVED` một script chưa soát kỹ. Soát đủ mà không thấy lỗi → `APPROVED` là **đúng**, không phải lười |
|
|
22
|
+
| **R04** | **No Rewriting** | Chỉ báo cáo, **không sửa code**. Đề xuất phải đủ rõ để người viết tự sửa được mà không hỏi lại |
|
|
23
|
+
| **R05** | **Positive Observations Required** | Mỗi lượt soát ghi **ít nhất 2–3 điểm tốt**. Một biên bản chỉ có lỗi là biên bản mất cân bằng — người đọc không biết phần nào đang đúng để giữ |
|
|
24
|
+
| **R06** | **Verdict Consistency** | Verdict suy ra từ **số đếm** finding theo §3, không tự nâng/hạ |
|
|
25
|
+
| **R07** | **Traceability First** | Thiếu/sai header artifact ID *(TC-ID · `@trace.verifies`)* ⇒ **BLOCKER ngay, dừng soát**. Không soát tiếp một file không biết nó phục vụ scenario nào |
|
|
26
|
+
|
|
27
|
+
> **R07 chặn cửa TRƯỚC, không phải sau.** Một lượt soát trên file không có trace tag vẫn chạy
|
|
28
|
+
> trót lọt và vẫn in ra verdict — nhưng verdict đó nói về một thứ không neo vào scenario nào.
|
|
29
|
+
> Đó là kiểu hỏng **Nói dối**: biên bản trông hợp lệ, nội dung vô nghĩa.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2 · Bốn mức nặng-nhẹ của một lỗi *(severity)*
|
|
34
|
+
|
|
35
|
+
| Mức | Định nghĩa | Ví dụ |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| **BLOCKER** | Ngăn test chạy đúng, hoặc vi phạm chuẩn lõi | selector thô trong spec · thiếu `await` · lỗi cú pháp · **không có header block** |
|
|
38
|
+
| **MAJOR** | Ảnh hưởng nặng tới khả năng bảo trì hoặc độ tin cậy | hard-code test data · `waitForTimeout` · locator bám class CSS tự sinh |
|
|
39
|
+
| **MINOR** | Vấn đề chất lượng code, script **vẫn chạy được** | thiếu type annotation · đặt tên không nhất quán · logic lặp có thể tách |
|
|
40
|
+
| **SUGGESTION** | Cơ hội cải thiện — **không bắt buộc** | tên biến rõ hơn · thông điệp assertion mô tả hơn |
|
|
41
|
+
|
|
42
|
+
**Ranh giới BLOCKER ↔ MAJOR đo được, không cảm tính:** BLOCKER là *"chạy sẽ sai hoặc không chạy"*;
|
|
43
|
+
MAJOR là *"chạy đúng hôm nay, hỏng khi có người sửa"*.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 3 · Bốn verdict — suy ra từ số đếm, **không override**
|
|
48
|
+
|
|
49
|
+
| Verdict | Điều kiện bắt buộc | Đi tiếp? |
|
|
50
|
+
|---|---|:-:|
|
|
51
|
+
| **APPROVED** | 0 BLOCKER, 0 MAJOR | ✅ |
|
|
52
|
+
| **APPROVED_WITH_SUGGESTIONS** | 0 BLOCKER, 0 MAJOR, ≥1 MINOR hoặc SUGGESTION | ✅ |
|
|
53
|
+
| **REVISION_REQUIRED** | 0 BLOCKER, ≥1 MAJOR | ❌ sửa rồi soát lại |
|
|
54
|
+
| **REJECTED** | ≥1 BLOCKER | ❌ sửa rồi soát lại |
|
|
55
|
+
|
|
56
|
+
**Ngưỡng qua cửa: `≥ APPROVED_WITH_SUGGESTIONS`** — khai ở `AGT-005:132` và `AGT-010:130`.
|
|
57
|
+
Hai mức trên đi tiếp, hai mức dưới quay lại. Các trạm sau *(`/qc-run-script`)* đọc **hai luồng
|
|
58
|
+
này**, không đọc bốn tên.
|
|
59
|
+
|
|
60
|
+
> **Vì sao lane QC dùng 4 mức còn lane DEV *(`/review-code`)* giữ 2.** Lane QC có tài liệu chuẩn
|
|
61
|
+
> định nghĩa severity thành bốn ô đếm được *(§2)*, nên bốn verdict chỉ là **tên của bốn ô đó** —
|
|
62
|
+
> không thêm phán quyết nào. Lane DEV chưa có bảng severity tương ứng, nên 4 tên ở đó sẽ là bốn
|
|
63
|
+
> nhãn phải tự đoán. Đây là **một bất đối xứng có lý do**, không phải chỗ quên đồng bộ.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 4 · Ranh giới — soát cái gì, KHÔNG soát cái gì
|
|
68
|
+
|
|
69
|
+
| | |
|
|
70
|
+
|---|---|
|
|
71
|
+
| ✅ **Soát** | code test đã sinh · Page/Screen/API Object · file data · khớp với `.Test.md` gốc |
|
|
72
|
+
| ❌ **KHÔNG soát** | **cấu trúc file test case** — đó là việc của `/qc-review-testcase`. Áp checklist cấu trúc TC vào một Page Object là bảo người soát đi tìm `#### Expected Result` trong code |
|
|
73
|
+
| ❌ **KHÔNG sửa** | *(R04)* — kể cả lỗi hiển nhiên một dòng |
|
|
74
|
+
| ❌ **KHÔNG chạy** | chạy test là việc của `/qc-run-script`. Ở đây chỉ compile/list để biết script **dịch được** và **thấy đủ số test** |
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 5 · Phép kiểm cơ học bắt buộc — trước khi kết luận
|
|
79
|
+
|
|
80
|
+
Chạy đủ hai lệnh, **dán output vào biên bản**:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
npx tsc --noEmit ← dịch được? (BLOCKER nếu lỗi)
|
|
84
|
+
npx playwright test <spec> --list ← đếm số test collect được (web · api)
|
|
85
|
+
npx wdio <config> --dry-run ← tương đương cho mobile
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Số test collect được phải bằng số TC `Automatable: Y`** của phạm vi này trong
|
|
89
|
+
`AUTOMATION_ASSESSMENT.md`. Lệch là **BLOCKER** — không phải MINOR:
|
|
90
|
+
|
|
91
|
+
- collect **ít hơn** ⇒ có TC không được sinh, và nó sẽ nằm `not_run` vĩnh viễn trong sổ trace
|
|
92
|
+
- collect **nhiều hơn** ⇒ có test không neo vào TC nào, `qc_status` sẽ ghi cho một scenario không tồn tại
|
|
93
|
+
|
|
94
|
+
> Đây là chỗ duy nhất trong lượt soát mà **máy trả lời thay vì người** — nên nó là chỗ đáng tin
|
|
95
|
+
> nhất, và là lý do hai lệnh trên không được bỏ qua kể cả khi "nhìn code thấy ổn".
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 6 · Đường dẫn — lấy từ `§layout` của module, KHÔNG viết cứng
|
|
100
|
+
|
|
101
|
+
Nền đang soát đã được `steps/qc-scope.md` §2b phân giải. Gốc thư mục lấy từ `§layout` của
|
|
102
|
+
module tương ứng:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
web automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
|
|
106
|
+
automation/pages/<feature>.page.ts
|
|
107
|
+
api api-automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
|
|
108
|
+
api-automation/api/<resource>.api.ts
|
|
109
|
+
mobile mobile-automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
|
|
110
|
+
mobile-automation/screens/<feature>.screen.ts
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
> **`tests/` chia theo `{TICKET-ID}`, `pages/`·`api/`·`screens/` để phẳng — có chủ ý.** Một spec
|
|
114
|
+
> **thuộc về** một PRD; một Page Object **được dùng bởi** nhiều PRD. Nhét Page Object vào thư mục
|
|
115
|
+
> PRD là ép nhân bản nó cho mỗi PRD — đúng thứ Page Object Pattern sinh ra để tránh.
|
|
116
|
+
>
|
|
117
|
+
> Thiếu segment `{TICKET-ID}` ở `tests/` thì hai PRD cùng có feature `login` ghi vào **cùng một
|
|
118
|
+
> đường dẫn** và đè nhau **im lặng**. Đó là lý do framework lệch khỏi bố cục phẳng của
|
|
119
|
+
> `Automation-Standards §2.3`: chuẩn giả định `tests/` soi gương theo `test-suites/`, còn ở đây
|
|
120
|
+
> test case sống ở `{qc_dir}/{TICKET-ID}/{platform}/test-cases/` — áp đúng **nguyên tắc** của
|
|
121
|
+
> chuẩn vào layout này thì ra hình dạng trên.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-17
|
|
4
|
+
source: upstream/qc-base-new/API-Testing-Standards.md §5.5 §9.1 (Approved)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Soát script — API xác thực & phân quyền
|
|
8
|
+
|
|
9
|
+
**Nạp `../_shared/review-rules.md` rồi `endpoint.md` cùng lane.** Đây là phần thêm.
|
|
10
|
+
|
|
11
|
+
## Khi nào trigger
|
|
12
|
+
- Soát script kiểm đăng nhập, token, và **quyền truy cập** của từng vai lên từng endpoint.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Thêm gì so với endpoint
|
|
17
|
+
|
|
18
|
+
### A · Fixture token dùng chung *(§5.5)*
|
|
19
|
+
|
|
20
|
+
- Mỗi test tự đăng nhập lại ⇒ **MINOR** — chậm và dễ chạm rate-limit; dùng `fixtures/api.fixture.ts`
|
|
21
|
+
- Token hard-code / token thật commit vào repo ⇒ **BLOCKER**
|
|
22
|
+
- Fixture không phân biệt **vai** ⇒ **MAJOR**: một token dùng cho mọi test thì không kiểm được phân quyền
|
|
23
|
+
|
|
24
|
+
### B · Mọi endpoint được bảo vệ phải có đủ ba ca *(§9.1)*
|
|
25
|
+
|
|
26
|
+
| Ca | Mong đợi |
|
|
27
|
+
|---|---|
|
|
28
|
+
| Không token | **401** |
|
|
29
|
+
| Token sai / hết hạn | **401** |
|
|
30
|
+
| Token đúng nhưng **sai vai** | **403** |
|
|
31
|
+
|
|
32
|
+
- Thiếu bất kỳ ca nào cho một endpoint được bảo vệ ⇒ **MAJOR**
|
|
33
|
+
- Gộp 401 và 403 thành một ca ⇒ **MAJOR** — hai lỗi khác nhau: *chưa biết anh là ai* vs *biết rồi
|
|
34
|
+
nhưng anh không được phép*
|
|
35
|
+
|
|
36
|
+
### C · Assert phải là "bị chặn", không phải "không lỗi"
|
|
37
|
+
|
|
38
|
+
- `expect(res.status()).not.toBe(200)` ⇒ **MAJOR** — 500 cũng qua được phép assert này
|
|
39
|
+
- Assert đúng mã, và assert body **không rò dữ liệu** của tài nguyên bị cấm ⇒ thiếu ⇒ **MINOR**
|
|
40
|
+
|
|
41
|
+
### D · Vòng đời token
|
|
42
|
+
|
|
43
|
+
- Không kiểm token hết hạn / refresh khi hợp đồng có ⇒ **MINOR**
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Kiểm cơ học + Output
|
|
48
|
+
|
|
49
|
+
Như `endpoint.md` Phase 3 và §Output.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-17
|
|
4
|
+
source: upstream/qc-base-new/API-Testing-Standards.md §4 §5 §6 §8 §10 §11 · AGT-010 §3 (Approved)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Soát script — API endpoint *(Playwright API mode + TypeScript)*
|
|
8
|
+
|
|
9
|
+
**Nạp `../_shared/review-rules.md` trước.** Lane này dùng khi `active_platform = system`.
|
|
10
|
+
|
|
11
|
+
> ⚠️ **API Object ≠ Page Object.** Không có màn hình, không có locator, không có wait. Soát API
|
|
12
|
+
> bằng checklist web là đi tìm những thứ không tồn tại rồi kết luận "không có lỗi".
|
|
13
|
+
|
|
14
|
+
## Khi nào trigger
|
|
15
|
+
- Soát script kiểm **endpoint** của một service: CRUD, mã trạng thái, cấu trúc response.
|
|
16
|
+
|
|
17
|
+
## Khi KHÔNG trigger
|
|
18
|
+
- Xác thực / phân quyền → `auth.md` · injection & input validation → `security.md`
|
|
19
|
+
- API gọi phụ trợ **bên trong** một dự án web *(setup/teardown)* → `../web/functional.md`
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Phase 1 — Đọc đủ *(R01)*
|
|
24
|
+
|
|
25
|
+
1. `api-automation/tests/{TICKET-ID}/<feature>-*.spec.ts`
|
|
26
|
+
2. `api-automation/api/<resource>.api.ts` + `base.api.ts`
|
|
27
|
+
3. `data/<resource>.data.ts` · `fixtures/api.fixture.ts` · `helpers/schema.helper.ts`
|
|
28
|
+
4. `.Test.md` + `AUTOMATION_ASSESSMENT.md`
|
|
29
|
+
|
|
30
|
+
**R07 chặn cửa** như mọi lane.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Phase 2 — Năm nhóm soát
|
|
35
|
+
|
|
36
|
+
### A · API Object *(§4 · AGT-010 R01)*
|
|
37
|
+
|
|
38
|
+
- **Mọi HTTP request phải đi qua API Object.** `request.post(...)` thô trong spec ⇒ **BLOCKER**
|
|
39
|
+
- `extends BaseAPI`; class `<Resource>API`; file `<resource>.api.ts`
|
|
40
|
+
- **1 method = 1 endpoint action**; method gộp nhiều endpoint ⇒ **MAJOR**
|
|
41
|
+
- Kiểu trả về `Promise<APIResponse>` — **không parse response trong API Object** ⇒ parse ⇒ **MAJOR**
|
|
42
|
+
- **Không `expect()` trong API Object** ⇒ có ⇒ **MAJOR**
|
|
43
|
+
- "God API Object" gom mọi resource ⇒ **MAJOR**
|
|
44
|
+
|
|
45
|
+
### B · Cấu trúc spec *(§5 — AAA)*
|
|
46
|
+
|
|
47
|
+
- Ba khối rõ: **Arrange** (data, token) → **Act** (gọi API Object) → **Assert**
|
|
48
|
+
- Trộn assert vào giữa chuỗi gọi ⇒ **MINOR**
|
|
49
|
+
- Header block có TC-ID + `@trace.verifies` ⇒ thiếu ⇒ **BLOCKER** *(R07)*
|
|
50
|
+
- Data-driven dùng `for...of` hoặc `test.each`, không copy test 5 lần ⇒ copy ⇒ **MINOR**
|
|
51
|
+
|
|
52
|
+
### C · Assertion *(§6)*
|
|
53
|
+
|
|
54
|
+
- **Assert mã trạng thái là bắt buộc** — thiếu ⇒ **BLOCKER**
|
|
55
|
+
- Assert **cả cấu trúc lẫn giá trị** của body, không chỉ `status === 200` ⇒ chỉ status ⇒ **MAJOR**
|
|
56
|
+
- Kiểm schema cho response có cấu trúc ⇒ thiếu ⇒ **MINOR**
|
|
57
|
+
- Assert header khi hợp đồng có nêu *(content-type, cache)* ⇒ thiếu ⇒ **MINOR**
|
|
58
|
+
- `expect(res.ok()).toBeTruthy()` làm assertion duy nhất ⇒ **MAJOR** — nó đúng cho mọi 2xx/3xx
|
|
59
|
+
|
|
60
|
+
### D · Dữ liệu *(AGT-010 R03)*
|
|
61
|
+
|
|
62
|
+
- Credential, payload, giá trị mong đợi **hard-code trong spec** ⇒ **MAJOR** — để ở `data/`
|
|
63
|
+
- Bản ghi tạo ra phải xoá trong `afterEach`/`afterAll`, kể cả khi fail ⇒ thiếu ⇒ **MAJOR**
|
|
64
|
+
- Test phụ thuộc bản ghi có sẵn trên môi trường ⇒ **MAJOR**
|
|
65
|
+
|
|
66
|
+
### E · Async *(AGT-010 R02)* và chất lượng *(§10 · §11)*
|
|
67
|
+
|
|
68
|
+
- **`waitForTimeout` tuyệt đối không dùng** — API là đồng bộ về bản chất, `await` thẳng ⇒ có ⇒ **BLOCKER**
|
|
69
|
+
- Thiếu `await` trước lời gọi API ⇒ **BLOCKER** *(test xanh giả, chạy xong trước khi có response)*
|
|
70
|
+
- TypeScript strict, không `any` ⇒ **MINOR**
|
|
71
|
+
- `test.only` sót lại ⇒ **BLOCKER**
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Phase 3 — Kiểm cơ học
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
npx tsc --noEmit
|
|
79
|
+
npx playwright test --config=api-automation/playwright.config.ts <spec> --list
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Số test collect được **phải bằng** số TC `Automatable: Y`. Lệch ⇒ **BLOCKER**.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Output
|
|
87
|
+
|
|
88
|
+
Theo `_shared/review-rules.md` §3, kèm ≥2–3 điểm tốt *(R05)*.
|
|
89
|
+
Lưu ý dãy ID của lane này độc lập: `TC-API-*` ≠ `TC-*` *(§7.3)*.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
version: 1.0
|
|
3
|
+
updated: 2026-09-17
|
|
4
|
+
source: upstream/qc-base-new/API-Testing-Standards.md §8 §9.2 (Approved)
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Soát script — API kiểm tra đầu vào & injection
|
|
8
|
+
|
|
9
|
+
**Nạp `../_shared/review-rules.md` rồi `endpoint.md` cùng lane.** Đây là phần thêm.
|
|
10
|
+
|
|
11
|
+
## Khi nào trigger
|
|
12
|
+
- Soát script kiểm **biên của đầu vào** và các mẫu injection lên endpoint.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Thêm gì so với endpoint
|
|
17
|
+
|
|
18
|
+
### A · Kỹ thuật thiết kế phải thấy được trong code *(§8)*
|
|
19
|
+
|
|
20
|
+
- **Phân lớp tương đương**: mỗi lớp có ít nhất một ca. Chỉ kiểm ca hợp lệ ⇒ **MAJOR**
|
|
21
|
+
- **Giá trị biên**: với trường có giới hạn, phải có `min-1` · `min` · `max` · `max+1`.
|
|
22
|
+
Thiếu hẳn phân tích biên cho trường có ràng buộc ⇒ **MAJOR**
|
|
23
|
+
- **Phủ HTTP method**: gọi method không được hỗ trợ phải trả **405**; thiếu ⇒ **MINOR**
|
|
24
|
+
|
|
25
|
+
### B · Payload injection *(§9.2)*
|
|
26
|
+
|
|
27
|
+
- Payload **hard-code rải trong spec** ⇒ **MAJOR** — gom vào `data/`, một bộ dùng cho nhiều endpoint
|
|
28
|
+
- Bộ mẫu thiếu hẳn một họ *(SQL · NoSQL · command · path traversal · XSS lưu trữ)* ⇒ **MINOR**
|
|
29
|
+
kèm nêu rõ họ nào thiếu
|
|
30
|
+
|
|
31
|
+
### C · Mong đợi phải cụ thể
|
|
32
|
+
|
|
33
|
+
- Mong đợi đúng là **400/422 + thông điệp lỗi có cấu trúc**, hoặc dữ liệu được làm sạch
|
|
34
|
+
- Assert kiểu "không sập" ⇒ **MAJOR** — một endpoint trả 200 kèm dữ liệu đã bị nhiễm vẫn "không sập"
|
|
35
|
+
- Assert thông điệp lỗi **không rò** stack trace / tên bảng / phiên bản ⇒ thiếu ⇒ **MINOR**
|
|
36
|
+
|
|
37
|
+
### D · Ranh giới của trạm này
|
|
38
|
+
|
|
39
|
+
- Đây **không** phải kiểm thâm nhập. Soát script, không đánh giá mức độ an toàn của hệ thống.
|
|
40
|
+
Biên bản kết luận *"hệ thống an toàn"* ⇒ **MAJOR** — vượt thẩm quyền của lượt soát *(R04 tinh thần)*
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Kiểm cơ học + Output
|
|
45
|
+
|
|
46
|
+
Như `endpoint.md` Phase 3 và §Output.
|