Buổi 9: Test Gate Assembly - 5 Layers đội hình
I. Lý Thuyết (30 phút)
5 Phases of Test Gate Protocol
┌─────────────────────────────────────────────────┐
│ PHASE 1: Stack Detection (Node.js+Express+SQLite) │
│ Check: package.json, src/, test/ │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 2: 4 Core Test Files │
│ ✓ Frontend Safety (jest) │
│ ✓ API Routes (supertest) │
│ ✓ Business Logic (Vitest) │
│ ✓ i18n Sync (JSON parity) │
│ ✓ Security Scan (secret patterns) │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 3: Script Wiring │
│ npm run test:gate = all 5 test files in order │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 4: Secret Hygiene │
│ - No hardcoded secrets │
│ - .env in .gitignore │
│ - process.env for sensitive data │
└─────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────┐
│ PHASE 5: Verification │
│ Gate Decision: PASS → Deploy, FAIL → Stop │
└─────────────────────────────────────────────────┘cm-test-gate: 5 Phases Chi Tiết
Phase 1: Stack Detection
- Xác định công nghệ: Node.js, Express, SQLite, Vitest
- Check
package.jsoncó đủ devDependencies:vitest,supertest,@testing-library/react
Phase 2: 4 Core Test Files
test/
├── frontend-safety.test.ts (Layer 1: DOM-XSS, input validation)
├── api-routes.test.ts (Layer 2: endpoints, status codes)
├── business-logic.test.ts (Layer 3: logic, edge cases)
├── i18n-sync.test.ts (Layer 4: key parity)
└── security-scan.test.ts (Layer 5: hardcoded secrets)Phase 3: Script Wiring
json
{
"scripts": {
"test:gate": "vitest run test/frontend-safety.test.ts test/api-routes.test.ts test/business-logic.test.ts test/i18n-sync.test.ts test/security-scan.test.ts"
}
}Phase 4: Secret Hygiene
- Scan src/ cho
/API_KEY\s*=\s*['"].*['"]/ - Verify .gitignore có
.env,.dev.vars - Verify no
process.env.SECRETđược print hoặc log
Phase 5: Verification
- All 5 test files PASS?
- Zero failures?
- Evidence log created?
3 Iron Laws of cm-quality-gate
Law 1: NO DEPLOY without test:gate
if (test:gate !== PASS) {
STOP
throw new Error("Gate failed - do not deploy")
}Law 2: NO CLAIMS without evidence
Claim: "This feature is ready"
Evidence:
- test:gate PASS ✓
- All 5 layers verified ✓
- Timestamp & git commit ✓Law 3: NO FRAGILE FRONTEND
BAD: Inline style="color: red" + hardcoded user data
GOOD: Sanitized HTML + environment-driven stylingAnti-Patterns vs. Best Practices
| ❌ DON'T | ✅ DO |
|---|---|
| Deploy, then test | Test, then deploy |
| "Tests passed yesterday" | Run fresh NOW, every time |
| Skip tests for "small changes" | Every change tested |
| Run test + deploy in parallel | Sequential: test → verify → deploy |
| Check code quality later | Scan at commit time (pre-commit hook) |
| Trust previous env setup | Verify env vars before deploy gate |
Gate Function: IDENTIFY → RUN → READ → VERIFY → CLAIM
1. IDENTIFY
↓ What are we testing?
├─ Stack type?
├─ Test files present?
└─ Test scripts wired?
2. RUN
↓ Execute all tests
├─ npm run test:gate
└─ Capture exit code + output
3. READ
↓ Parse results
├─ Count failures
├─ Extract error messages
└─ Check for warnings
4. VERIFY
↓ Validate evidence
├─ All 5 layers covered?
├─ No skipped tests?
└─ Coverage adequate?
5. CLAIM
↓ Make gate decision
├─ PASS: "Safe to deploy"
└─ FAIL: "Stop, fix issues"II. Thực Hành (55 phút)
CHECKPOINT: Verify 5 Test Files Exist
Bước 1: Liệt kê test files
bash
cd /path/to/taskflow-app
ls -la test/Expected:
-rw-r--r-- 1 user staff 2.1K Apr 24 10:30 frontend-safety.test.ts
-rw-r--r-- 1 user staff 1.8K Apr 24 10:31 api-routes.test.ts
-rw-r--r-- 1 user staff 2.4K Apr 24 10:32 business-logic.test.ts
-rw-r--r-- 1 user staff 1.9K Apr 24 10:33 i18n-sync.test.ts
-rw-r--r-- 1 user staff 1.7K Apr 24 10:34 security-scan.test.tsBước 2: Kiểm Tra package.json có test:gate script
bash
grep "test:gate" package.jsonExpected:
json
"test:gate": "vitest run test/frontend-safety.test.ts test/api-routes.test.ts test/business-logic.test.ts test/i18n-sync.test.ts test/security-scan.test.ts --reporter=verbose"Bước 3: Chạy test:gate
bash
npm run test:gate 2>&1 | tee test-gate-output.logExpected Output:
✓ test/frontend-safety.test.ts (234ms)
✓ should sanitize user input
✓ should prevent XSS attacks
✓ should validate form inputs
✓ test/api-routes.test.ts (456ms)
✓ GET /api/tasks returns 200
✓ POST /api/tasks validates body
✓ DELETE /api/tasks/:id returns 204
✓ test/business-logic.test.ts (345ms)
✓ Task.isOverdue() returns true for past dates
✓ Task.assignee validation works
✓ Task.priority enum constraints
✓ test/i18n-sync.test.ts (125ms)
✓ should have same keys in en.json and vi.json
✓ test/security-scan.test.ts (98ms)
✓ should not have hardcoded API keys in src/
✓ should have .env in .gitignore
Test Files 5 passed (5)
Tests 15 passed (15)Nếu FAIL, đọc error message và fix.
Practice 2: Gate Decision Discipline
Scenario: Deliberately break 1 test để học cách dừng lại khi gate fail.
Bước 1: Break một test
bash
# Thêm test sai intentionally
cat >> test/business-logic.test.ts << 'EOF'
it('should fail intentionally for learning', () => {
expect(true).toBe(false); // Lỗi!
});
EOFBước 2: Chạy test:gate (Expect FAIL)
bash
npm run test:gateOutput:
✗ test/business-logic.test.ts (345ms)
✗ should fail intentionally for learning
AssertionError: expected true to be false
at test/business-logic.test.ts:245:8
Test Files 4 passed, 1 failed (5)
Tests 14 passed, 1 failed (15)
Exit Code: 1Bước 3: STOP - Không Deploy!
┌─────────────────────────────────────────┐
│ 🛑 GATE FAILED - DO NOT PROCEED │
│ │
│ Exit code: 1 │
│ Tests failed: 1 out of 15 │
│ Status: BLOCKED │
└─────────────────────────────────────────┘Dùng script để enforce:
bash
#!/bin/bash
# scripts/test-gate-check.sh
npm run test:gate
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "🛑 Test gate failed. Exit code: $EXIT_CODE"
echo "Do not proceed with deployment."
exit 1
fi
echo "✅ Test gate passed. Safe to deploy."
exit 0bash
chmod +x scripts/test-gate-check.sh
./scripts/test-gate-check.shBước 4: Fix lỗi
bash
# Xóa test sai
git checkout test/business-logic.test.ts
# Hoặc fix cái lỗi thực tế
# ...Bước 5: Chạy lại (Expect PASS)
bash
npm run test:gateOutput:
Test Files 5 passed (5)
Tests 15 passed (15)
✅ All gates passed. Ready for deployment.Practice 3: Evidence Before Claims
Scenario: Tạo evidence log để prove claims.
Bước 1: Tạo evidence template
File: docs/evidence-log.md
markdown
# Test Gate Evidence Log
## Buổi 9: April 24, 2026 - 15:30 UTC
### Gate Status: PASS ✅
#### Test Execution
- **Date & Time**: 2026-04-24 15:30:42 UTC
- **Git Commit**: `abc1234` (Test Gate Assembly: All 5 layers verified)
- **Branch**: main
- **Node Version**: v20.10.0
- **npm Version**: 10.2.3
#### Test Results
| Layer | Test File | Status | Pass | Fail | Duration |
|-------|-----------|--------|------|------|----------|
| 1 | frontend-safety.test.ts | ✅ | 3 | 0 | 234ms |
| 2 | api-routes.test.ts | ✅ | 3 | 0 | 456ms |
| 3 | business-logic.test.ts | ✅ | 3 | 0 | 345ms |
| 4 | i18n-sync.test.ts | ✅ | 1 | 0 | 125ms |
| 5 | security-scan.test.ts | ✅ | 2 | 0 | 98ms |
| **TOTAL** | | **✅** | **12** | **0** | **1.258s** |
#### Test Output
\`\`\`
✓ test/frontend-safety.test.ts (234ms)
✓ test/api-routes.test.ts (456ms)
✓ test/business-logic.test.ts (345ms)
✓ test/i18n-sync.test.ts (125ms)
✓ test/security-scan.test.ts (98ms)
Test Files 5 passed (5)
Tests 12 passed (12)
\`\`\`
#### Security Checklist
- [x] No hardcoded secrets in src/
- [x] .env in .gitignore
- [x] process.env for API_KEY
- [x] i18n keys in parity
#### QA Sign-off
**Tested By**: DevOps Bot
**Approved By**: Lead Engineer
**Timestamp**: 2026-04-24T15:30:42Z
**Ticket**: TASKFLOW-42
---
## Claims Require Evidence Table
| Claim | Evidence | Source |
|-------|----------|--------|
| "Tests passed" | test:gate PASS, Exit code 0 | npm run test:gate |
| "No security issues" | security-scan.test.ts PASS | test/security-scan.test.ts |
| "i18n sync" | i18n-sync.test.ts PASS, parity verified | test/i18n-sync.test.ts |
| "Ready to deploy" | All 5 layers PASS + evidence log | This file |
---
## Previous Buổis Evidence
See also:
- Buổi 8: `docs/evidence-log.md` (i18n & security fixes)
- Buổi 7: `docs/evidence-log.md` (business logic layer)Bước 2: Chạy test:gate và capture output
bash
npm run test:gate > test-output.txt 2>&1
EXIT_CODE=$?
# Append to evidence log
cat >> docs/evidence-log.md << EOF
## Buổi 9: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
### Gate Status: $([ $EXIT_CODE -eq 0 ] && echo "PASS ✅" || echo "FAIL ❌")
\`\`\`
$(cat test-output.txt)
\`\`\`
EOF
cat docs/evidence-log.mdBước 3: Kiểm Tra evidence log
bash
cat docs/evidence-log.mdExpected:
# Test Gate Evidence Log
## Buổi 9: 2026-04-24 15:30:42 UTC
### Gate Status: PASS ✅
Test Files 5 passed (5)
Tests 12 passed (12)
Claims Require Evidence Table
| Claim | Evidence | Source |
|-------|----------|--------|
| "Ready to deploy" | All 5 layers PASS | test:gate output |III. CHECKPOINT: 5 Layers Running with 0 Failures
Verify trước khi kết thúc buổi:
bash
# 1. Check 5 test files
ls -1 test/*test.ts | wc -l
# Expected: 5
# 2. Check test:gate script
grep -c "test:gate" package.json
# Expected: 1
# 3. Run gate
npm run test:gate
# Expected: Exit code 0, all PASS
# 4. Check evidence log
[ -f docs/evidence-log.md ] && echo "✅ Log exists" || echo "❌ Missing"
# 5. Security check
grep -c "FAKE_API_KEY" src/server.js
# Expected: 0 (hardcoded key removed)IV. Script: Automated Gate Check
File: scripts/pre-deploy.sh
bash
#!/bin/bash
set -e
echo "🏗️ Test Gate Assembly - Pre-Deployment Check"
echo "============================================="
# Phase 1: Stack Detection
echo "[1/5] Stack Detection..."
[ -f "package.json" ] || { echo "❌ No package.json"; exit 1; }
[ -d "test" ] || { echo "❌ No test/ directory"; exit 1; }
echo "✅ Stack detected: Node.js + Vitest"
# Phase 2: Core Test Files
echo "[2/5] Core Test Files..."
TEST_COUNT=$(find test -name "*.test.ts" | wc -l)
if [ "$TEST_COUNT" -ge 5 ]; then
echo "✅ Found $TEST_COUNT test files"
else
echo "❌ Only $TEST_COUNT test files (need 5)"
exit 1
fi
# Phase 3: Script Wiring
echo "[3/5] Script Wiring..."
grep -q "test:gate" package.json || { echo "❌ No test:gate script"; exit 1; }
echo "✅ test:gate script found"
# Phase 4: Secret Hygiene
echo "[4/5] Secret Hygiene..."
SECRETS=$(grep -r "API_KEY\s*=\s*['\"].*['\"]" src/ || true)
if [ -z "$SECRETS" ]; then
echo "✅ No hardcoded secrets"
else
echo "❌ Found hardcoded secrets:"
echo "$SECRETS"
exit 1
fi
# Phase 5: Run Gate
echo "[5/5] Running Test Gate..."
npm run test:gate || { echo "❌ Test gate failed"; exit 1; }
echo ""
echo "✅ ALL GATES PASSED - Ready to deploy"
echo "$(date -u +"%Y-%m-%d %H:%M:%S UTC")" >> docs/deployment-log.txt
exit 0Chạy:
bash
chmod +x scripts/pre-deploy.sh
./scripts/pre-deploy.shV. Key Takeaways
5 Phases recap:
- Stack Detection - Verify tech stack
- 4 Core Test Files - Frontend, API, Logic, i18n, Security
- Script Wiring - npm run test:gate orchestrates all
- Secret Hygiene - No hardcodes, use process.env
- Verification - Evidence log, gate decision
3 Iron Laws:
- NO DEPLOY without test:gate → Exit code 0 required
- NO CLAIMS without evidence → Evidence log mandatory
- NO FRAGILE FRONTEND → Input validation + sanitization
Gate Decision:
if (npm run test:gate === 0) {
DEPLOY ✅
} else {
STOP ❌ Fix issues first
}VI. Homework
- Ensure
npm run test:gatepasses on your local machine - Create
docs/evidence-log.mdwith current gate status - Run
scripts/pre-deploy.shand capture output - Commit evidence to git:bash
git add docs/evidence-log.md git commit -m "Test Gate Assembly: All 5 layers PASS" git push - Share evidence link in team Slack
Next Buổi: Real-world deployment scenarios & incident post-mortems.