Install any skill in seconds. Free to start, no credit card required.
Get Started Free →利用測試快照來達到文件化的非常規使用方式。當用戶請求 (1) 使用快照進行文件化,(2) 將快照作為範例展示,(3) "snapshot 文件化",(4) "快照測試文件",(5) "測試快照作為文件",(6) "為測試保留結果快照",(7) "為測試增加說明快照" 時使用此技能。This skill guides the unconventional use of test snapshots for documentation purposes, transforming test snapshots into living documentation that showcases behavior, examples, and API usage.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 156% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 54% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 102% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 198% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 94% | 0% |
此技能指導如何將測試快照(Snapshot)轉化為文件化的非常規使用方式,讓快照不僅是測試驗證工具,更是行為展示、API 範例和教學材料。
| 面向 | 傳統斷言 | 文件化快照 | |------|---------|-----------| | 主要目標 | 驗證正確性 | 行為展示 + 驗證 | | 可讀性 | 取決於測試名稱 | 快照本身即文件 | | 維護成本 | 低 | 中(需更新說明) | | 適用場景 | 單元測試 | API 範例、教學 |
typescriptexpect({ explain: '說明 / 描述 / 邏輯解釋', // 必填(標題/描述/邏輯/複合式) result: { /* ... */ }, // 必填(始終保留) }).toMatchSnapshot()
typescriptexpect({ explain: '說明 / Description', // 必填 tags?: 'tag1, tag2, tag3', // 可選 '#id'?: '自定義索引ID', // 可選:用於來回檢查 snap 與 test 檔案 result: { /* ... */ }, // 必填 input?: { target, source }, // 可選 }).toMatchSnapshot()
explainresult 中各欄位的來源或意義,幫助理解輸出結構typescript// 短句範例 explain: '✅ 新增鍵 / Add keys' // 複雜範例:說明 result 中各欄位的來源 explain: '✅ 多個物件合併(不同類型):所有屬性被合併 result 中 - first: 來自第一個物件 - second: 來自第二個物件 - third: 來自第三個物件 - fourth: 來自第四個物件'
, (逗號 + 空格)分隔的多重標籤tag1, tag2, tag3(非陣列)tagstypescript// ✅ 正確 tags: 'basic, root-level, keys' // ❌ 錯誤(陣列形式) tags: ['basic', 'root-level']
target / source{ array: [...] }、{ options: {} })input 複雜度判定
│
▼
屬性數量 ≤ 3 且 無深度嵌套?
│
├─ 是 → 保留 input
│
└─ 否 → 移除 input(依賴 result 推導)typescript// ✅ 簡單案例:保留 input(來自函式參數) input: { array: [1, 2, 3] } input: { target: { a: 1 }, source: { b: 2 } } // ✅ 複雜案例:移除 input // (依賴快照差異顯示輸入輸出變化)
#id - 自訂索引 ID(來回檢查用)typescript// ✅ 使用 #id 方便來回檢查 it('should merge objects correctly', () => { const result = merge(target, source); expect({ explain: '✅ 基本合併 / Basic merge', '#id': 'merge-basic-001', // 自定義索引 ID tags: 'basic, merge', input: { ... }, result: { ... }, }).toMatchSnapshot(); });
使用場景:
#id 快速找到對應的測試#id 找到原始測試當需要在同一個快照檔案中展示多個結果時(例如比較不同函式的輸出),建議使用 result{FeatureName} 的命名模式,而非 {FeatureName}Result。
原因:Jest 快照檔案通常按照描述(describe)名稱的字母順序排序,使用 result 前綴可以將所有結果集中在一起,方便查閱與維護。
| 模式 | 範例 | 優勢 | |------|------|------| | 推薦 | resultDeepmerge, resultLodash | 快照中所有結果會依 feature 名稱排序,方便管理 | | 不推薦 | deepmergeResult, lodashResult | 結果會散落在各字母區塊,難以快速瀏覽 |
typescript// ✅ 正確:使用 result 前綴 it('should compare merge results', () => { const deepmergeResult = mergeDeep(target, source); const lodashResult = _.merge(target, source); expect({ explain: '比較 deepmerge 與 lodash merge 的行為差異', resultDeepmerge: deepmergeResult, resultLodash: lodashResult, }).toMatchSnapshot(); });
typescript// ❌ 錯誤:使用 Result 後綴(快照會散開) expect({ deepmergeResult: deepmergeResult, lodashResult: lodashResult, }).toMatchSnapshot();
補充說明:
result 是固定的關鍵字 prefix,表示這是一個輸出結果{FeatureName} 是具體的功能或函式名稱(使用 PascalCase 或 camelCase)| 類別 | 標籤範例 | 說明 | |------|---------|------| | 測試類型 | basic, advanced, edge-case | 測試複雜度 | | 資料結構 | object, array, nested, deep | 輸入資料類型 | | 功能特性 | clone, merge, replace | 合併行為 | | 應用場景 | config, preferences, state | 實際應用 | | 對照組 | good-example, bad-example | 展示正確/錯誤用法 |
- 或 _ 分隔詞彙:nested-object, deep_mergetypescript// ✅ 正確 tags: 'basic, nested-object, merge' // ❌ 錯誤 tags: '基礎, 巢狀, 合併'
typescriptit('should add keys to empty target', () => { const target = {}; const source = { key1: 'value1', key2: 'value2' }; const result = merge(target, source); expect({ explain: '✅ 新增至空物件 / Add to empty object', tags: 'basic, root-level, keys', input: { target, source }, // 來自函式參數 result, }).toMatchSnapshot(); });
typescriptit('should merge array of objects', () => { const input = [{ a: 1 }, { b: 2 }]; const result = deepmergeAll(input); expect({ explain: '合併物件陣列', input: { input }, // 參數名稱為 input result, }).toMatchSnapshot(); });
typescriptit('should deeply merge nested objects', () => { const target = { user: { name: 'Alice', settings: { theme: 'dark' } } }; const source = { user: { age: 30, settings: { language: 'en' } } }; const result = merge(target, source); expect({ explain: 'Deep nested merge preserves nested structure', tags: 'nested, deep, object-merge', result, }).toMatchSnapshot(); });
Other measured skills in the registry, with their headline benchmark lift.