spec-lite 1.6.0 → 1.7.1
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/README.md +6 -0
- package/package.json +1 -1
- package/skills/archive/SKILL.md +63 -52
- package/skills/artifact-audit/SKILL.md +3 -2
- package/skills/artifact-migrate/SKILL.md +3 -3
- package/skills/plan/SKILL.md +5 -0
- package/skills/spec-brownfield-feature/SKILL.md +21 -4
- package/skills/spec-frd/SKILL.md +25 -3
- package/skills/spec-test-exec/SKILL.md +254 -0
- package/skills-overview.md +20 -7
- package/templates/main/feature/selector-contract-template.md +88 -0
- package/templates/main/feature/test-design-template.md +14 -2
- package/templates/test-executions/test-exec-dm-template.md +83 -0
- package/templates/test-executions/test-exec-e2e-auto-template.md +300 -0
- package/templates/test-executions/test-exec-e2e-manual-template.md +231 -0
- package/templates/test-executions/test-exec-func-auto-template.md +155 -0
- package/templates/test-executions/test-exec-func-manual-template.md +203 -0
- package/templates/test-executions/test-exec-nfr-template.md +88 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-test-exec
|
|
3
|
+
description: Sinh bundle test-executions cho MỘT feature — render Test Cases trong test-design.md thành các doc thực thi theo harness (func-manual/auto, e2e-manual/auto, nfr, dm). Đọc-xuống từ test-design (source of truth), inherit TC-F* nguyên văn, KHÔNG đẻ ID mới. Mỗi lần chạy = bundle đánh số mới, ephemeral per test cycle.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# spec-test-exec
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Sinh một **cycle bundle test-executions** cho một feature vào `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` — render các Test Case đã thiết kế ở `test-design.md` thành **doc thực thi** theo từng **harness** (manual GUI walk / automation / tool đặc thù / migration script). Plane 2 tầng: feature group (`{F-XXX}-{slug}/`) → cycle bundle (`{NNN}-{cycle-slug}/`); `{NNN}` reset per-feature (xem `conventions.md` §8.1).
|
|
11
|
+
|
|
12
|
+
**Vị trí trong 3 layer** (xem `conventions.md` §8):
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
frd.md ──(/spec-test | /spec-test-design)──▶ test-design.md ──(/spec-test-exec)──▶ test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/
|
|
16
|
+
[DESIGN — TC là gì] [SOURCE OF TRUTH] [EXECUTION — chạy bằng harness gì]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Cốt lõi — đọc xuống, KHÔNG sáng tạo:**
|
|
20
|
+
- test-design.md là **source of truth** của bộ Test Case. Skill này **chỉ đọc** test-design → route TC vào doc theo section nguồn + harness.
|
|
21
|
+
- **Inherit `TC-F*` nguyên văn** — KHÔNG đẻ ID mới, KHÔNG renumber. (`{PREFIX}_E2E_*` nếu dùng chỉ là title `test.describe` trong code, không phải ID artifact.)
|
|
22
|
+
- Mỗi lần chạy = **bundle đánh số mới** (snapshot độc lập từ test-design hiện tại). **KHÔNG** carry-over result, **KHÔNG** link chuỗi với bundle cũ.
|
|
23
|
+
|
|
24
|
+
**KHÔNG versioned:** doc test-exec không mang `template_version`/`migrations` — derived, ngoài scope `/artifact-audit` + `/artifact-migrate` (xem `conventions.md` §7 + §8.1).
|
|
25
|
+
|
|
26
|
+
## When to Use
|
|
27
|
+
|
|
28
|
+
- Một feature đã có `test-design.md` và cần sinh doc thực thi để bắt đầu một **chu kỳ test** (regression release, sprint test, UAT...).
|
|
29
|
+
- test-design.md vừa cập nhật (qua `/spec-test`) → cần một bundle thực thi mới phản ánh TC hiện tại.
|
|
30
|
+
|
|
31
|
+
## When NOT to Use
|
|
32
|
+
|
|
33
|
+
- Feature **chưa có** `test-design.md` → chạy `/spec-test` (qua integration) hoặc `/spec-test-design` (bootstrap) trước.
|
|
34
|
+
- Muốn **thêm/đổi TC** → KHÔNG sửa ở đây (test-exec chỉ đọc). Sửa test-design qua `/spec-test`, rồi sinh lại bundle.
|
|
35
|
+
- Chỉ muốn cập nhật **kết quả thực thi** (Test Result) → edit doc trong bundle trực tiếp (đó là việc của owner khi chạy test), không chạy lại skill.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Process
|
|
40
|
+
|
|
41
|
+
### Bước 1: Xác định feature
|
|
42
|
+
|
|
43
|
+
`/spec-test-exec` thao tác trên **đúng một feature**.
|
|
44
|
+
|
|
45
|
+
**Nếu có ARGUMENT:**
|
|
46
|
+
- Parse: feature ID (`F-012`, `012`) hoặc slug (`F-012-bulk-import`, `bulk-import`).
|
|
47
|
+
- Quét `.specs/main/feature/*/test-design.md`, tìm feature khớp.
|
|
48
|
+
- Không khớp → báo lỗi:
|
|
49
|
+
> Không tìm thấy feature có test-design.md khớp với "{argument}". Kiểm tra `.specs/main/feature/`.
|
|
50
|
+
|
|
51
|
+
**Nếu không có ARGUMENT:**
|
|
52
|
+
|
|
53
|
+
Quét `.specs/main/feature/`. Liệt kê features **có `test-design.md`**, kèm các cycle bundle hiện có trong feature group:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
Features có test-design.md:
|
|
57
|
+
|
|
58
|
+
[1] F-012 — bulk-import test-design: approved cycles: 001-regression, 002-release-2.0
|
|
59
|
+
[2] F-031 — checkout test-design: draft cycles: —
|
|
60
|
+
|
|
61
|
+
Chọn số feature:
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Không feature nào có test-design.md → dừng:
|
|
65
|
+
> Chưa có feature nào có test-design.md. Chạy `/spec-test` hoặc `/spec-test-design` trước.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Bước 2: Gate check + phát hiện section điều kiện
|
|
70
|
+
|
|
71
|
+
Đọc `.specs/main/feature/{F-XXX}-{slug}/test-design.md`.
|
|
72
|
+
|
|
73
|
+
**Check 1 — test-design.md tồn tại:** nếu không → dừng (đã xử lý ở Bước 1).
|
|
74
|
+
|
|
75
|
+
**Check 2 — status (cảnh báo, KHÔNG block):**
|
|
76
|
+
|
|
77
|
+
Nếu `status` **không phải** `approved`:
|
|
78
|
+
> ⚠ `test-design.md` của **{F-XXX}** đang ở `status: {status}` (chưa approved — có thể còn placeholder TBD ở Test Data / Strategy / Out of Scope).
|
|
79
|
+
>
|
|
80
|
+
> Bundle sinh ra sẽ kế thừa các placeholder đó. Tiếp tục? (yes / no — default yes)
|
|
81
|
+
|
|
82
|
+
`no` → dừng, gợi ý approve test-design trước.
|
|
83
|
+
|
|
84
|
+
**Check 3 — phát hiện section required-emptyable rỗng (quyết định nfr/dm):**
|
|
85
|
+
|
|
86
|
+
Đọc 2 section của test-design:
|
|
87
|
+
- `## Non-Functional Test Cases` — có TC block (`### TC-F...`) không?
|
|
88
|
+
- `## Data & Migration Test Cases` — có TC block không?
|
|
89
|
+
|
|
90
|
+
Quy tắc (xem `conventions.md` §8.2):
|
|
91
|
+
- Section có ≥1 TC → **sẽ sinh** doc tương ứng (`test-exec-nfr.md` / `test-exec-dm.md`).
|
|
92
|
+
- Section rỗng (chỉ heading, không TC) → **BỎ QUA** doc đó.
|
|
93
|
+
|
|
94
|
+
Báo lại cho user:
|
|
95
|
+
```
|
|
96
|
+
test-design F-012:
|
|
97
|
+
Functional TC: 8 Validation TC: 12 E2E TC: 3 NFR TC: 2 DM TC: 0
|
|
98
|
+
→ Sẽ sinh: func-manual, func-auto, e2e-manual, e2e-auto, nfr (BỎ dm — section rỗng)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Bước 3: Cấp feature group + cycle bundle
|
|
104
|
+
|
|
105
|
+
**Feature group** `{F-XXX}-{slug}/` — mirror tên thư mục `main/feature/{F-XXX}-{slug}/`. Chưa tồn tại → tạo mới; đã có → dùng lại (gom cycle).
|
|
106
|
+
|
|
107
|
+
**Cycle number `{NNN}`** — đánh số **per-feature** (reset trong mỗi feature group):
|
|
108
|
+
- Quét max `{NNN}` của các cycle bundle **trong feature group đó**:
|
|
109
|
+
- `.specs/test-executions/{F-XXX}-{slug}/*/` (active)
|
|
110
|
+
- `.specs/archive/**/` thuộc cùng feature (cycle đã archive)
|
|
111
|
+
- `{NNN}` mới = max + 1, zero-padded 3 chữ số. Feature group rỗng → `001`.
|
|
112
|
+
|
|
113
|
+
**Cycle slug** — kebab-case mô tả **chu kỳ test** (vd `regression`, `release-2.0`, `smoke`). KHÔNG nhúng `{F-XXX}` (đã ở tầng feature group). Hỏi user (mặc định gợi ý theo ngữ cảnh):
|
|
114
|
+
|
|
115
|
+
> Cycle mới: `F-012-bulk-import/003-regression`. Đổi cycle-slug? (Enter để giữ)
|
|
116
|
+
|
|
117
|
+
**Cảnh báo clobber:** nếu tên cycle trùng một bundle đã có trong feature group → cảnh báo, KHÔNG ghi đè (đề nghị số mới hoặc archive cycle cũ trước).
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Bước 4: Route TC → bucket + completeness check
|
|
122
|
+
|
|
123
|
+
**Đọc toàn bộ TC từ test-design**, gom theo section nguồn:
|
|
124
|
+
|
|
125
|
+
| Section test-design | Bucket scope | TC fields đọc được |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| `## Functional Test Cases` | func | Type, **Autoable**, Priority, Covers, Scenario, Preconditions, Steps, Expected, Test data |
|
|
128
|
+
| `## Validation Test Cases` | func | TC ID, Covers VR, Field, Input, Expected, Polarity (**Autoable=YES** uniform) |
|
|
129
|
+
| `## E2E Test Cases` | e2e | Type (journey/consistency/integrity), Priority, Covers FAC, Spans, Preconditions, Steps, Expected |
|
|
130
|
+
| `## Non-Functional Test Cases` | nfr | Type, Priority, Covers NFR, Preconditions, Steps, Expected |
|
|
131
|
+
| `## Data & Migration Test Cases` | dm | Type, Priority, Covers DM, Preconditions, Steps, Expected |
|
|
132
|
+
|
|
133
|
+
**Route vào doc:**
|
|
134
|
+
|
|
135
|
+
| Doc | Lấy TC nào |
|
|
136
|
+
| --- | --- |
|
|
137
|
+
| `test-exec-func-manual` | **TOÀN BỘ** Functional + Validation TC (bất kể Autoable) |
|
|
138
|
+
| `test-exec-func-auto` | Functional + Validation TC có **`Autoable ∈ {YES, MAYBE}`** (Validation đều YES) |
|
|
139
|
+
| `test-exec-e2e-manual` | **TOÀN BỘ** E2E TC |
|
|
140
|
+
| `test-exec-e2e-auto` | **TOÀN BỘ** E2E TC (cùng tập với e2e-manual — hai harness thay thế) |
|
|
141
|
+
| `test-exec-nfr` | Non-Functional TC *(bỏ doc nếu rỗng)* |
|
|
142
|
+
| `test-exec-dm` | Data & Migration TC *(bỏ doc nếu rỗng)* |
|
|
143
|
+
|
|
144
|
+
**Completeness check (BẮT BUỘC trước khi ghi):**
|
|
145
|
+
- Tập `TC-F*` ở 4 **scope bucket** (func ∪ e2e ∪ nfr ∪ dm) phải **bằng** tập TC trong `test-design > Traceability Matrix`.
|
|
146
|
+
- Mỗi `TC-F*` rơi **đúng 1 scope bucket** (func/e2e/nfr/dm) — không lọt, không trùng scope. *(Cùng 1 TC xuất hiện ở cả func-manual lẫn func-auto là ĐÚNG — đó là hai harness của cùng scope func, không tính trùng.)*
|
|
147
|
+
- func-auto là **tập con** của func-manual (chỉ Autoable=YES/MAYBE) — phần `Autoable=NO` chỉ ở manual.
|
|
148
|
+
- Lỗi (TC không route được / TC thừa không có trong Matrix / section nguồn không parse được) → **dừng, báo cụ thể**, KHÔNG ghi bundle nửa vời.
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
### Bước 5: Sinh doc từ template
|
|
153
|
+
|
|
154
|
+
Với mỗi doc cần sinh, copy từ `templates/test-executions/test-exec-{...}-template.md` rồi điền:
|
|
155
|
+
|
|
156
|
+
**Frontmatter (`conventions.md` §8.5):**
|
|
157
|
+
- `id: test-exec-{kind}-{F-XXX}-{NNN}-{cycle-slug}` · `type: test-exec-{kind}` · `feature_id: {F-XXX}` · `status: draft`
|
|
158
|
+
- `test_design_ref: main/feature/{F-XXX}-{slug}/test-design.md` (từ `.specs/` root — không phụ thuộc độ sâu bundle)
|
|
159
|
+
- func/e2e: `alt_harness_{auto|manual}: ./test-exec-{...}.md` (relative, cùng bundle)
|
|
160
|
+
- Markdown link tới test-design trong body: bundle sâu 2 tầng → `../../../main/feature/{F-XXX}-{slug}/test-design.md`.
|
|
161
|
+
- **KHÔNG** `template_version`/`migrations`.
|
|
162
|
+
|
|
163
|
+
**Inherit (đọc xuống — KHÔNG suy diễn lại):**
|
|
164
|
+
- `TC-F*` ID, `Covers`, `Type`, `Priority`, `Preconditions`, `Steps`, `Expected` → copy **nguyên văn** từ test-design vào bảng Coverage + Test Cases của doc.
|
|
165
|
+
- `Autoable` (func) → copy y nguyên; func-auto chỉ chứa YES/MAYBE.
|
|
166
|
+
|
|
167
|
+
**Testid cho doc automation (chủ yếu e2e-auto):** đọc `.specs/main/feature/{F-XXX}-{slug}/selector-contract.md` (nếu có) — đây là **nguồn testid chung** mà code đã/đang gắn theo cùng contract. Khi điền **POM index §7.1 của e2e-auto** (và func-auto nếu có UI component test dùng testid): dùng **đúng** testid handle trong contract, neo theo `Flow › Step`. **KHÔNG tự đặt testid mới** ở đây (lệch nguồn → vỡ "một-nguồn-hai-bên-đọc"). Biểu thức locator `getByTestId(...)` + file POM `.ts` vẫn do owner viết ở source tree. Feature không có selector-contract → để placeholder + note "feature chưa có selector-contract".
|
|
168
|
+
|
|
169
|
+
**Placeholder cho owner điền khi chạy** (KHÔNG tự bịa):
|
|
170
|
+
- **Test Result / Status (CI)** → `—` (chưa chạy).
|
|
171
|
+
- **Test File / POM file path + biểu thức locator** → `_Pending — {owner}_` (sống ở source tree). *(Testid handle thì đã có từ selector-contract — xem trên, không để trống.)*
|
|
172
|
+
- **Tool / Command / Layer** (nfr/auto) → gợi ý theo Type nếu suy được (vd NFR performance → `k6`), còn lại để placeholder.
|
|
173
|
+
- Account/Role matrix, Env tiers, Seed, Fixtures → giữ skeleton template để owner điền theo môi trường.
|
|
174
|
+
|
|
175
|
+
**Coverage tables:** điền từ Traceability Matrix (AC/VR/FAC/NFR/DM → TC IDs) — KHÔNG dựng matrix cạnh tranh; coverage master vẫn ở test-design.
|
|
176
|
+
|
|
177
|
+
Hiển thị **tóm tắt bundle** (không dump toàn bộ) cho user xem trước khi ghi:
|
|
178
|
+
```
|
|
179
|
+
Cycle F-012-bulk-import/003-regression — sẽ ghi 5 doc:
|
|
180
|
+
func-manual : 20 TC (8 func + 12 val) [toàn bộ]
|
|
181
|
+
func-auto : 18 TC (Autoable YES/MAYBE) [2 TC Autoable=NO chỉ ở manual]
|
|
182
|
+
e2e-manual : 3 TC
|
|
183
|
+
e2e-auto : 3 TC
|
|
184
|
+
nfr : 2 TC
|
|
185
|
+
(dm: bỏ — rỗng)
|
|
186
|
+
Completeness: 25/25 TC ở Traceability Matrix đều routed ✓
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
### Bước 6: Ghi bundle + báo cáo
|
|
192
|
+
|
|
193
|
+
**[6.1]** Tạo `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` (tạo feature group nếu chưa có), ghi từng doc (status `draft`).
|
|
194
|
+
|
|
195
|
+
**[6.2]** KHÔNG cascade, KHÔNG đụng test-design (đọc-xuống one-way). KHÔNG ghi Change History vào test-design (test-exec không phải nguồn cascade).
|
|
196
|
+
|
|
197
|
+
**[6.3] Báo cáo:**
|
|
198
|
+
```
|
|
199
|
+
✓ .specs/test-executions/F-012-bulk-import/003-regression/ (từ test-design.md)
|
|
200
|
+
✓ test-exec-func-manual.md — 20 TC
|
|
201
|
+
✓ test-exec-func-auto.md — 18 TC (Autoable YES/MAYBE)
|
|
202
|
+
✓ test-exec-e2e-manual.md — 3 TC
|
|
203
|
+
✓ test-exec-e2e-auto.md — 3 TC
|
|
204
|
+
✓ test-exec-nfr.md — 2 TC
|
|
205
|
+
(dm bỏ qua — test-design Data & Migration rỗng)
|
|
206
|
+
|
|
207
|
+
Bước tiếp theo (team chọn harness theo kỹ năng — xem terms/003/004):
|
|
208
|
+
- func: chạy func-manual (QC) HOẶC func-auto (DEV/SE). Lưu ý auto-only LỌT exploratory + Autoable=NO.
|
|
209
|
+
- e2e: chọn 1 trong e2e-manual (QC) / e2e-auto (SE) — thay thế hoàn toàn.
|
|
210
|
+
- nfr: SDET/specialist chạy bằng tool tương ứng.
|
|
211
|
+
- Xóa doc harness không dùng (sinh hết để team chọn).
|
|
212
|
+
- Điền Test Result / Status khi chạy.
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Common Rationalizations
|
|
218
|
+
|
|
219
|
+
| Rationalization | Reality |
|
|
220
|
+
| --- | --- |
|
|
221
|
+
| "Thêm TC ngay trong bundle cho nhanh" | test-exec chỉ đọc xuống. TC mới phải vào test-design trước (qua `/spec-test`) rồi sinh lại — nếu không sẽ vỡ traceability + ID authority. |
|
|
222
|
+
| "Đổi TC ID cho gọn lại" | ID `TC-F*` do test-design làm chủ, stable. Renumber ở đây phá liên kết với test code + Traceability Matrix. |
|
|
223
|
+
| "Auto chạy pass hết là xong" | func-auto LỌT exploratory + `Autoable=NO` (visual). Manual-only mới đầy đủ scope func (terms/004). |
|
|
224
|
+
| "Sinh thiếu vài doc cho nhanh" | Sinh hết (6 hoặc 4) để team chọn harness. Thiếu = ép harness sai với kỹ năng team. |
|
|
225
|
+
| "Regenerate đè bundle cũ" | Mỗi cycle = bundle số mới. Đè bundle đã có Test Result = mất lịch sử thực thi. |
|
|
226
|
+
|
|
227
|
+
## Red Flags
|
|
228
|
+
|
|
229
|
+
- Có `TC-F*` ở test-design Traceability Matrix nhưng không xuất hiện ở doc nào → completeness fail (lọt).
|
|
230
|
+
- Một `TC-F*` rơi vào >1 scope bucket (vd vừa func vừa e2e) → routing bug.
|
|
231
|
+
- func-auto chứa TC `Autoable=NO` → sai filter.
|
|
232
|
+
- Doc test-exec mang `template_version` → sai (test-exec không versioned).
|
|
233
|
+
- Ghi đè bundle cũ đang có Test Result mà không cảnh báo.
|
|
234
|
+
- Bịa Test Result / Locators / Tool thay vì để placeholder.
|
|
235
|
+
- Sửa test-design trong lúc chạy skill (skill này read-only với test-design).
|
|
236
|
+
|
|
237
|
+
## Verification
|
|
238
|
+
|
|
239
|
+
Trước khi ghi bundle:
|
|
240
|
+
|
|
241
|
+
- [ ] Đúng một feature; test-design.md tồn tại (cảnh báo nếu draft, không block).
|
|
242
|
+
- [ ] nfr/dm: chỉ sinh khi section nguồn có TC; rỗng → bỏ doc.
|
|
243
|
+
- [ ] Feature group `{F-XXX}-{slug}/` (mirror main/feature); `{NNN}` = max cycle **trong feature group đó** (active + archived) + 1 (reset per-feature); cycle-slug mô tả chu kỳ.
|
|
244
|
+
- [ ] Route đúng: func ← Functional+Validation (manual=toàn bộ, auto=Autoable YES/MAYBE); e2e ← E2E (cả 2 harness cùng tập); nfr ← Non-Functional; dm ← Data & Migration.
|
|
245
|
+
- [ ] **Completeness**: mọi `TC-F*` ở Traceability Matrix routed đúng 1 scope bucket — không lọt/trùng.
|
|
246
|
+
- [ ] Inherit `TC-F*` + fields nguyên văn; KHÔNG ID mới, KHÔNG renumber.
|
|
247
|
+
- [ ] Frontmatter: `id/type/feature_id/test_design_ref/alt_harness_*` đúng; KHÔNG `template_version`.
|
|
248
|
+
- [ ] Test Result/Status/biểu thức locator + file POM = placeholder, không bịa.
|
|
249
|
+
- [ ] Doc automation (e2e-auto, func-auto): testid trong POM §7.1 / locator reference lấy từ `selector-contract.md` (nếu feature có), KHÔNG tự đặt testid mới; feature thiếu contract → placeholder + note.
|
|
250
|
+
|
|
251
|
+
Sau khi ghi:
|
|
252
|
+
|
|
253
|
+
- [ ] Bundle tại `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` với 6 (hoặc 4) doc, status `draft`.
|
|
254
|
+
- [ ] KHÔNG đụng test-design (one-way đọc xuống, không cascade, không Change History).
|
package/skills-overview.md
CHANGED
|
@@ -261,10 +261,11 @@ Sau khi main artifacts đã sẵn sàng (từ greenfield hoặc brownfield), m
|
|
|
261
261
|
| `/spec-new [requirement]` | `prd.md`, `domain.md`, frd(s), crd(s) | `.specs/integrations/{slug}/spec.md` |
|
|
262
262
|
| `/spec-tech [number]` | `sad.md`, `domain.md`, cdd(s), fdd(s), `spec.md` | `.specs/integrations/{slug}/tech.md` |
|
|
263
263
|
| `/spec-test [number]` | `spec.md`, frd(s), test-design(s), `tech.md` *(optional)* | `.specs/integrations/{slug}/test.md`, `feature/{F-XXX}/test-design.md` |
|
|
264
|
+
| `/spec-test-exec [F-XXX]` *(feature-level, sau khi có test-design)* | `feature/{F-XXX}/test-design.md` | `.specs/test-executions/{F-XXX}-*/{NNN}-*/test-exec-*.md` |
|
|
264
265
|
| `/plan` | `spec.md`, `tech.md`, `domain.md` | `plan.md`, `todo.md` |
|
|
265
266
|
| `/build` | `plan.md`, `todo.md` | *(source code)* |
|
|
266
267
|
| `/review-integration` | `spec.md`, `tech.md`, `plan.md`, `todo.md`, *(source code)* | *(findings report)* |
|
|
267
|
-
| `/archive` | `.specs/integrations/` | `.specs/archive/` |
|
|
268
|
+
| `/archive` | `.specs/integrations/`, `.specs/test-executions/` | `.specs/archive/{integrations,test-executions}/` |
|
|
268
269
|
|
|
269
270
|
### `/spec-new [requirement]`
|
|
270
271
|
|
|
@@ -327,6 +328,18 @@ QC review: override priority defaults, fill placeholders (env / data / OOS / str
|
|
|
327
328
|
|
|
328
329
|
---
|
|
329
330
|
|
|
331
|
+
### `/spec-test-exec [F-XXX]`
|
|
332
|
+
|
|
333
|
+
Sinh **bundle test-executions** (bản thực thi) cho **một feature** từ `test-design.md`. Layer EXECUTION — `test-design.md` là **source of truth**, skill **đọc-xuống một chiều** (KHÔNG cascade, KHÔNG sửa test-design). Feature-level, chạy *sau* khi feature đã có test-design (không thuộc per-integration pipeline).
|
|
334
|
+
|
|
335
|
+
**Cách chạy:** `/spec-test-exec` (list feature có test-design) hoặc `/spec-test-exec F-012`.
|
|
336
|
+
|
|
337
|
+
**Output:** cycle bundle `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` (plane 2 tầng — feature group → cycle bundle, `{NNN}` reset per-feature, ephemeral per chu kỳ test). Mỗi lần chạy = cycle mới.
|
|
338
|
+
|
|
339
|
+
Route TC theo **section nguồn + Autoable**, sinh **tới 6 doc** (4 nếu feature không NFR/DM): `func-manual` (toàn bộ Functional+Validation), `func-auto` (Autoable=YES/MAYBE), `e2e-manual` + `e2e-auto` (toàn bộ E2E), `nfr`, `dm` *(nfr/dm bỏ nếu section rỗng)*. **Sinh hết để team chọn harness** theo kỹ năng (e2e: manual⇄auto thay thế hoàn toàn; func: auto-only lọt exploratory/visual). **Inherit `TC-F*` nguyên văn** (không đẻ ID) + completeness check mọi TC ở Traceability Matrix rơi đúng 1 scope bucket. KHÔNG versioned. Chi tiết: `conventions.md` §8, `terms/003`+`004`.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
330
343
|
### `/plan`
|
|
331
344
|
|
|
332
345
|
Tạo `plan.md` và `todo.md` từ `spec.md` + `tech.md`. Là SDD wrapper quanh `planning-and-task-breakdown`.
|
|
@@ -385,17 +398,17 @@ Review implementation sau `/build` theo năm trục: correctness, readability, a
|
|
|
385
398
|
|
|
386
399
|
### `/archive`
|
|
387
400
|
|
|
388
|
-
Di chuyển
|
|
401
|
+
Di chuyển artifact đã hoàn thành / không còn active sang `.specs/archive/` — hỗ trợ **cả 2 plane** và **namespace theo loại**.
|
|
389
402
|
|
|
390
|
-
**Bước 1 —
|
|
403
|
+
**Bước 1 — Chuẩn bị:** Tạo lazy subfolder theo loại — `.specs/archive/integrations/` và/hoặc `.specs/archive/test-executions/`.
|
|
391
404
|
|
|
392
|
-
**Bước 2 — Liệt kê:** Quét `.specs/integrations
|
|
405
|
+
**Bước 2 — Liệt kê:** Quét `.specs/integrations/` (mỗi `{id}-{slug}/`) và `.specs/test-executions/` (mỗi cycle bundle `{F-XXX}-{slug}/{NNN}-{cycle-slug}/`, + tùy chọn cả feature group). Hiển thị 2 section đánh số liên tục. Cả hai rỗng → dừng.
|
|
393
406
|
|
|
394
|
-
**Bước 3 — Xác nhận:**
|
|
407
|
+
**Bước 3 — Xác nhận:** Preview source → namespaced dest (`integrations/{slug}/ → archive/integrations/{slug}/`; cycle bundle → `archive/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/`). Dedupe nếu chọn cả feature group lẫn cycle con.
|
|
395
408
|
|
|
396
|
-
**Bước 4 — Di chuyển:** Move
|
|
409
|
+
**Bước 4 — Di chuyển:** Move giữ nguyên cấu trúc nguồn dưới subfolder loại (test-exec giữ 2 tầng). Dest đã tồn tại → bỏ qua + cảnh báo (no-overwrite). Feature group nguồn rỗng sau khi archive cycle → dọn thư mục rỗng.
|
|
397
410
|
|
|
398
|
-
**Bước 5 — Kết quả:** Liệt kê
|
|
411
|
+
**Bước 5 — Kết quả:** Liệt kê đã archive, bị bỏ qua (nếu có), và số còn lại mỗi plane.
|
|
399
412
|
|
|
400
413
|
---
|
|
401
414
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: selector-contract-{feature}
|
|
3
|
+
type: selector-contract
|
|
4
|
+
status: draft
|
|
5
|
+
owner: "{DEV / QC}"
|
|
6
|
+
feature_id: "{Feature ID}"
|
|
7
|
+
template_version: 1
|
|
8
|
+
migrations:
|
|
9
|
+
- to: 1
|
|
10
|
+
note: "baseline"
|
|
11
|
+
referenced_by:
|
|
12
|
+
- conventions.md > 3. Main Artifacts > 3.3 Feature level > selector-contract.md
|
|
13
|
+
- skills/spec-frd/SKILL.md > Process > Bước 4c (derive) + Bước 7e (save)
|
|
14
|
+
- skills/spec-brownfield-feature/SKILL.md > Process > Bước 4f (define từ flows) + Bước 6 (generate)
|
|
15
|
+
- skills/plan/SKILL.md > Process > Bước 2 (load) + Bước 3 (ràng buộc FE task gắn testid)
|
|
16
|
+
- skills/spec-test-exec/SKILL.md > Process > Bước 5 (testid cho POM automation)
|
|
17
|
+
- templates/test-executions/test-exec-e2e-auto-template.md > §1 Context (Testid source) + §7.1 Page Object Index
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<!--
|
|
21
|
+
Canonical format cho .specs/main/feature/{F-XXX}-{slug}/selector-contract.md.
|
|
22
|
+
|
|
23
|
+
SELECTOR CONTRACT — hợp đồng `data-testid` giữa CODE (FE gắn) và AUTOMATION TEST (QC/SE dùng).
|
|
24
|
+
Đây là MỘT loại trong họ "*-contract.md". Sau này có thể thêm api-contract.md, seed-contract.md…
|
|
25
|
+
Mỗi loại = file riêng (một nguồn, một consumer rõ ràng) — KHÔNG gộp chung một contract.md.
|
|
26
|
+
|
|
27
|
+
NGUỒN — derive HOÀN TOÀN từ frd.md > User Flows:
|
|
28
|
+
- Mỗi element user TƯƠNG TÁC (click/fill) hoặc test ASSERT trong flow → một row testid.
|
|
29
|
+
- Mỗi element neo vào một BƯỚC (step) của flow → cột "Flow › Step". KHÔNG neo theo màn hình:
|
|
30
|
+
bước ↔ màn KHÔNG 1:1 (nhiều bước chung một màn, hoặc một flow đi qua nhiều màn) → step mới là khóa chính xác.
|
|
31
|
+
- testid đặt theo QUY ƯỚC (conventions.md §3.3): {feature-slug}-{element}[-{qualifier}].
|
|
32
|
+
- fdd KHÔNG phải nguồn — fdd là tech design của module C-XXX, không mô tả UI element.
|
|
33
|
+
|
|
34
|
+
MỘT NGUỒN — HAI BÊN ĐỌC (⇒ drift bất khả thi):
|
|
35
|
+
- CODE (qua /plan → /build): FE gắn ĐÚNG các data-testid trong bảng này.
|
|
36
|
+
- TEST AUTO (qua /spec-test-exec): POM của test-exec-e2e-auto / func-auto dùng ĐÚNG các testid này.
|
|
37
|
+
Vì cả hai trích CÙNG MỘT file → testid code-gắn và testid test-tìm KHÔNG THỂ lệch nhau.
|
|
38
|
+
|
|
39
|
+
CHỈ phục vụ nhánh AUTOMATION. Manual buckets (func-manual, e2e-manual) dùng mắt người
|
|
40
|
+
điều hướng qua sản phẩm — KHÔNG cần testid, bỏ qua file này.
|
|
41
|
+
|
|
42
|
+
THUẦN MÔ TẢ (main spec): file này khai báo testid CẦN CÓ, KHÔNG track trạng thái implementation
|
|
43
|
+
("FE gắn chưa" thuộc tầng code/execution — plan/todo + test-exec, không phải ở đây).
|
|
44
|
+
LOCATOR THÔ cũng KHÔNG ở đây: file chứa GIÁ TRỊ testid (cái handle ổn định), KHÔNG chứa biểu thức
|
|
45
|
+
`page.getByTestId(...)` — biểu thức locator sống trong POM `.ts` ở repo code thật.
|
|
46
|
+
|
|
47
|
+
RE-DERIVE khi frd User Flows đổi (element mới → thêm row). Vì thuần mô tả, không có trạng thái
|
|
48
|
+
implementation cần giữ → re-derive là overwrite sạch.
|
|
49
|
+
|
|
50
|
+
VERSIONED: là main artifact nên MANG template_version + migrations, thuộc scope /artifact-audit +
|
|
51
|
+
/artifact-migrate như mọi main artifact khác.
|
|
52
|
+
-->
|
|
53
|
+
|
|
54
|
+
# Selector Contract: {Feature Name}
|
|
55
|
+
|
|
56
|
+
**Feature**: {F-XXX} | **Derived from**: frd.md › User Flows | **Status**: {status}
|
|
57
|
+
|
|
58
|
+
> Hợp đồng `data-testid` cho các element mà automation test (e2e-auto / func-auto) **tương tác** hoặc **assert**.
|
|
59
|
+
> Đây là nguồn DUY NHẤT cho cả FE (gắn testid lúc code) lẫn POM (dùng testid lúc viết test) → hai bên không thể lệch.
|
|
60
|
+
> **Quy ước tên** (conventions.md §3.3): `{feature-slug}-{element}[-{qualifier}]` — vd `order-customer`, `order-submit`, `order-row-{id}`.
|
|
61
|
+
|
|
62
|
+
## Testid Contract
|
|
63
|
+
|
|
64
|
+
> Mỗi row = một element trong frd User Flows mà test auto chạm tới. Element manual-only / không-tương-tác KHÔNG cần ở đây.
|
|
65
|
+
> Chỉ liệt kê element test thật sự dùng — đừng gắn testid tràn lan (testid là API công khai cho test; gắn thừa = đóng băng cả thứ đáng được tự do đổi).
|
|
66
|
+
|
|
67
|
+
| **testid** | **Element** | **Flow › Step** | **Interaction** |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `{slug}-{element}` | {mô tả element, vd: input tên khách} | {Flow 1 › "nhập tên khách"} | action |
|
|
70
|
+
| `{slug}-{element}` | {vd: badge đếm đơn} | {Flow 1 › "xem danh sách đơn"} | assert |
|
|
71
|
+
|
|
72
|
+
> **Flow › Step**: neo testid vào đúng bước trong frd User Flows (`{Flow N} › "{nhãn bước}"`). Một màn nhiều bước thì mỗi bước là một row riêng.
|
|
73
|
+
> **Interaction**: `action` (click/fill/select — test tương tác) · `assert` (đọc/verify — test khẳng định) · `nav` (điều hướng).
|
|
74
|
+
|
|
75
|
+
## Notes *(nếu có)*
|
|
76
|
+
|
|
77
|
+
> Ghi chú để DEV + QC thống nhất các trường hợp quy ước chưa phủ:
|
|
78
|
+
> - Element mơ hồ (vd hai nút cùng nhãn "Lưu") → cần qualifier phân biệt.
|
|
79
|
+
> - List động → testid kèm id: `{slug}-row-{id}`.
|
|
80
|
+
> - Element QC cần assert nhưng frd flow chưa nêu rõ → thêm row + ghi lý do.
|
|
81
|
+
|
|
82
|
+
## Change History
|
|
83
|
+
|
|
84
|
+
> Derive từ frd User Flows — re-derive (overwrite) khi flows đổi. Operation = `manual` (sinh kèm `/spec-frd`/`/spec-brownfield-feature`, ngoài integration).
|
|
85
|
+
|
|
86
|
+
| **Date** | **Integration** | **Operation** | **Summary** |
|
|
87
|
+
|---|---|---|---|
|
|
88
|
+
| {YYYY-MM-DD} | manual | create | Initial testid skeleton derive từ frd User Flows |
|
|
@@ -5,7 +5,7 @@ status: draft
|
|
|
5
5
|
owner: "{QC}"
|
|
6
6
|
feature_id: "{Feature ID — match frd.md}"
|
|
7
7
|
frd_ref: "feature/{F-XXX}-{slug}/frd.md"
|
|
8
|
-
template_version:
|
|
8
|
+
template_version: 3
|
|
9
9
|
migrations:
|
|
10
10
|
- to: 1
|
|
11
11
|
note: "baseline"
|
|
@@ -17,6 +17,11 @@ migrations:
|
|
|
17
17
|
- { section: "Test Strategy > Environments", reason: "env assignment/scheduling là execution concern — design chỉ cần env requirement ở per-TC Preconditions" }
|
|
18
18
|
update:
|
|
19
19
|
- { section: "Test Data", change: "đổi thành 'Test Data Requirements' — bỏ cột Nguồn (fixture/factory = provisioning) + Refresh (cadence = execution), thêm cột 'Yêu cầu data (shape)'" }
|
|
20
|
+
- to: 3
|
|
21
|
+
note: "Thêm field Autoable (YES/MAYBE/NO) cho TC — test-design là SOURCE OF TRUTH route TC vào func-auto (YES/MAYBE) vs func-manual (toàn bộ + NO); hai track chỉ đọc, không tự quyết. Phân loại theo oracle của Expected: lập trình được (giá trị/state/record/HTTP/message/route)=YES, lập trình được nhưng setup nặng=MAYBE, visual (màu/layout/icon/animation)=NO. Mọi Validation TC = YES theo định nghĩa (không cần cột riêng)."
|
|
22
|
+
update:
|
|
23
|
+
- { section: "Functional Test Cases", change: "thêm field 'Autoable' (YES/MAYBE/NO) vào mỗi TC block + rule phân loại theo oracle ở đầu section" }
|
|
24
|
+
- { section: "Validation Test Cases", change: "ghi rõ mọi VR-derived TC = Autoable=YES (uniform, không thêm cột)" }
|
|
20
25
|
---
|
|
21
26
|
|
|
22
27
|
<!--
|
|
@@ -76,11 +81,18 @@ Cover User Stories và Acceptance Criteria trong frd.
|
|
|
76
81
|
|
|
77
82
|
TC ID format: `TC-F{NNN}-{seq}` — đánh số tăng dần toàn feature. ID **stable** (không tái sử dụng seq khi xóa, không renumber). Nếu xóa TC → ID đó retire, seq mới tiếp tục tăng từ max.
|
|
78
83
|
|
|
84
|
+
**Autoable** — test-design là **source of truth** cho field này; cả `test-exec-func-auto` lẫn `test-exec-func-manual` **chỉ đọc**, không tự quyết. Route TC vào đâu: func-auto cover `YES/MAYBE`, func-manual cover **toàn bộ** + `NO`. Phân loại theo **oracle của Expected** (cái mà outcome được verify):
|
|
85
|
+
|
|
86
|
+
- `YES` — oracle **lập trình được**: giá trị / state / record / HTTP status / error-message text / route / computed result. *(Mọi Validation TC ⇒ YES theo định nghĩa.)*
|
|
87
|
+
- `MAYBE` — oracle lập trình được **nhưng** chỉ tới được qua setup nặng: multi-entity seed, cross-service integration, prior state phức tạp.
|
|
88
|
+
- `NO` — oracle **visual**: màu / spacing / layout / icon-asset render / animation / "trông đúng". Hiếm có `TC-F*` — assertion visual thuần thường không thành AC nên thành exploratory (không ID) ở manual, không phải TC này.
|
|
89
|
+
|
|
79
90
|
### TC-{F_ID}-001: {Title ngắn — verb-first}
|
|
80
91
|
|
|
81
92
|
| Field | Value |
|
|
82
93
|
| --- | --- |
|
|
83
94
|
| **Type** | Functional — positive / negative |
|
|
95
|
+
| **Autoable** | YES / MAYBE / NO — phân loại theo oracle (rule ở đầu section) |
|
|
84
96
|
| **Priority** | P0 / P1 / P2 |
|
|
85
97
|
| **Covers** | `US-{F_ID}-001`, `AC-{F_ID}-001` |
|
|
86
98
|
| **Scenario** | `TS-{F_ID}-001` |
|
|
@@ -105,7 +117,7 @@ TC ID format: `TC-F{NNN}-{seq}` — đánh số tăng dần toàn feature. ID **
|
|
|
105
117
|
|
|
106
118
|
## Validation Test Cases
|
|
107
119
|
|
|
108
|
-
Derive 1:1 từ Verification Rules trong frd. Mỗi `VR-F{NNN}-{seq}` cần ít nhất:
|
|
120
|
+
Derive 1:1 từ Verification Rules trong frd. **Mọi Validation TC ⇒ `Autoable=YES`** (oracle input→accept/reject, logic thuần — không phụ thuộc visual); uniform nên không thêm cột. Mỗi `VR-F{NNN}-{seq}` cần ít nhất:
|
|
109
121
|
- 1 positive (rule pass)
|
|
110
122
|
- 1+ negative — mỗi nhánh fail là 1 case riêng (vd VR "email format" → 1 case cho missing `@`, 1 case cho missing domain, ...)
|
|
111
123
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: test-exec-dm-{F-XXX}-{NNN}-{slug}
|
|
3
|
+
type: test-exec-dm
|
|
4
|
+
status: draft
|
|
5
|
+
owner: "{SE / DBA}"
|
|
6
|
+
feature_id: "{F-XXX}"
|
|
7
|
+
test_design_ref: "main/feature/{F-XXX}-{slug}/test-design.md"
|
|
8
|
+
referenced_by:
|
|
9
|
+
- conventions.md > Test Execution Artifacts > test-exec-dm.md
|
|
10
|
+
- terms/003-test-exec-buckets.md
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
Canonical format cho .specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/test-exec-dm.md.
|
|
15
|
+
EXECUTION layer — ephemeral per test cycle, harness "migration script trên dataset prod-like", owner SE/DBA.
|
|
16
|
+
Cover Data & Migration (DM) — backfill, schema migration, data cũ không mất/hỏng. Xem terms/003.
|
|
17
|
+
|
|
18
|
+
KHÔNG versioned: không template_version / migrations, ngoài scope /artifact-audit + /artifact-migrate.
|
|
19
|
+
Derived từ test-design.md → test-design đổi thì REGENERATE.
|
|
20
|
+
|
|
21
|
+
CHỈ TẠO file này khi frd.md có `DM-F*` (test-design § Data & Migration Test Cases không rỗng).
|
|
22
|
+
Feature không đụng migration → KHÔNG tạo test-exec-dm.md.
|
|
23
|
+
|
|
24
|
+
Source of truth: test-design.md > Data & Migration Test Cases.
|
|
25
|
+
- ID = TC-F{NNN}-{seq} inherit từ test-design (Covers DM-F*). KHÔNG tạo ID mới.
|
|
26
|
+
- Coverage master = test-design.md > Traceability Matrix.
|
|
27
|
+
-->
|
|
28
|
+
|
|
29
|
+
# Data & Migration Test Execution: {Feature Name}
|
|
30
|
+
|
|
31
|
+
**Feature**: {F-XXX} | **Owner**: {owner} | **Status**: {status}
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 1. Context
|
|
36
|
+
|
|
37
|
+
| **Field** | **Detail** |
|
|
38
|
+
|---|---|
|
|
39
|
+
| **Feature Summary** | {1–2 câu — migration/backfill scope} |
|
|
40
|
+
| **DM covered** | {DM IDs — `DM-F{NNN}-001`, ...} |
|
|
41
|
+
| **Source** | [test-design.md](../../../main/feature/{F-XXX}-{slug}/test-design.md) — TC IDs (Data & Migration Test Cases) + Traceability Matrix |
|
|
42
|
+
| **Migration artifact** | {ref script/EF migration: `{migration-name}` hoặc path} |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Dataset & Migration Setup
|
|
47
|
+
|
|
48
|
+
> Migration chạy trên dataset **prod-like** — không phải seed nhỏ. Phải snapshot trước để so khớp.
|
|
49
|
+
|
|
50
|
+
| **Field** | **Detail** |
|
|
51
|
+
|---|---|
|
|
52
|
+
| **Dataset** | {vd: 10.000 bản ghi địa chỉ format cũ — nguồn / cách load} |
|
|
53
|
+
| **Pre-condition chung** | Migration script đã review · dataset prod-like đã load vào env test |
|
|
54
|
+
| **Snapshot before** | count + checksum trước migration (baseline để assert) |
|
|
55
|
+
| **Rollback plan** | {cách revert nếu migration fail — backup/restore / down-migration} |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. DM Execution
|
|
60
|
+
|
|
61
|
+
> **Input:** test-design.md § Data & Migration Test Cases (TC ID, expected — đếm/so khớp).
|
|
62
|
+
> **Test Result:** `—` (chưa chạy) | `✅ Pass` | `❌ Fail` | `⛔ Blocked` | `🔴 HOLD`
|
|
63
|
+
|
|
64
|
+
| **TC ID** | **Covers** | **Pre-condition** | **Migration Command** | **Expected** | **Test Result** | **Priority** |
|
|
65
|
+
|---|---|---|---|---|---|---|
|
|
66
|
+
| `TC-F{NNN}-060` | `DM-F{NNN}-001` | Dataset prod-like loaded ({N} bản ghi cũ) · snapshot baseline | `{migration-command}` | count sau = count trước ({N}/{N}) · 0 null · format mới parse đúng | — | 🔴 P0 |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 4. Exit Criteria
|
|
71
|
+
|
|
72
|
+
- [ ] Mọi DM P0 TC pass — data cũ nguyên vẹn (count + checksum khớp)
|
|
73
|
+
- [ ] 0 bản ghi mất / null / lỗi parse sau migration
|
|
74
|
+
- [ ] Rollback đã verify chạy được (dry-run hoặc trên copy)
|
|
75
|
+
- [ ] Test Result column updated đầy đủ
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 5. Change Log
|
|
80
|
+
|
|
81
|
+
| **Date** | **Cycle** | **Changes** | **Author** |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| {YYYY-MM-DD} | {cycle/release} | Initial DM execution (derive từ test-design.md) | {Author} |
|