property-based-testing
作者 trailofbits這份 property-based-testing 技能指南涵蓋如何在多種語言與 smart contracts 中撰寫、審查與改進 PBT。可用來辨識 roundtrip、idempotence、invariant、parser、validator 與 normalization 等情境,選擇合適的 generators,並判斷何時 property-based-testing 比 example-based tests 更有優勢。
這個技能獲得 83/100,代表它是個相當扎實的目錄項目:它提供足夠明確的觸發規則與工作流程指引,能比一般通用提示更有幫助;但遇到邊界情況與語言特定的實作細節時,使用者仍應預期需要一些人工判斷。
- 對常見 PBT 模式提供明確的自動偵測觸發條件,例如 encode/decode 配對、parsers、normalizers、validators、pure functions 與 smart contracts。
- 在整個流程中都有扎實的操作內容:設計 properties、產生 tests、審查 failures,以及為了可測試性進行重構。
- 廣泛涵蓋語言與工具,且搭配七個參考檔案補足工作流程,沒有空泛的佔位內容,安裝決策價值高。
- SKILL.md 沒有 install command,因此採用時需要使用者手動把這個技能接到自己的環境,或自行推斷設定方式。
- 帶有 experimental/test 訊號,且部分文件偏向參考資料;因此使用者可能需要自行解讀指引,而不是直接照著一條可完整執行的端到端流程操作。
property-based-testing 技能概覽
這個 property-based-testing 技能是用來做什麼的
property-based-testing 技能能幫你撰寫、審查與改進屬性導向測試(property-based tests),尤其是在範例型測試已經無法提供足夠信心時特別有用。當你需要驗證 roundtrip、invariants、不變條件、parsers、validators、normalizers、排序邏輯,或 smart contract 的狀態規則時,這個 property-based-testing 技能尤其實用。
誰最適合使用
最適合的情境是:使用具成熟 PBT 函式庫的語言的工程師、正在檢查薄弱測試的 code reviewer,以及希望先以 properties 定義功能的開發者。若你正在判斷是否要安裝 property-based-testing,關鍵問題在於:你的程式是否具有可重用的結構、可逆的轉換,或是應該在大量輸入下都成立的規則。
它跟一般測試提示有什麼不同
不同於一般的測試提示,這個技能是圍繞「找出要驗證的性質、選擇 property、設計 strategy、解讀失敗結果」來組織的。這很重要,因為導入最大的阻礙通常不是語法,而是如何挑出有用的 property,並在不過度過濾的前提下產生有效輸入。這個技能的適用範圍也夠廣,能用在多個生態系的 property-based-testing for Skill Testing,包括 smart contracts。
如何使用 property-based-testing 技能
安裝並載入正確的脈絡
使用 npx skills add trailofbits/skills --skill property-based-testing 安裝,然後先打開 SKILL.md。如果你想更快做決策,也建議再讀 README.md,以及最貼近你任務的參考檔案:references/generating.md、references/reviewing.md 和 references/interpreting-failures.md。
把模糊想法轉成可用提示
一個好的 property-based-testing usage 提示,應該要說清楚目標、操作,以及你在意的保證。更好的輸入例如:「替這個 serializer 的 decode(encode(x)) 加上 PBT,並把輸入限制在合法 UTF-8 與大小上限內。」較差的輸入則是:「替這個模組寫 property tests。」前者讓技能有真實的 property、有效的資料範圍邊界,以及明確的輸出形式。
你的需求中應該提供什麼
請包含語言、測試函式庫、函式簽章、已知不變條件、非合法輸入時的行為,以及任何範例或規格。如果你是拿 property-based-testing guide 來做 code review,請貼上現有測試,並說明你想要的是找 bug、重構,還是品質稽核。如果程式有 parsing 或 validation 路徑,請明確說明遇到格式錯誤資料時應該怎麼處理;這能避免測試寫得太空泛,也能避免不當使用 assume()。
建議的工作流程
先把程式映射到某種 property 類型:roundtrip、idempotence、不變條件、排序,或 oracle。接著設計能「以建構方式」產生合法輸入的 strategy,而不是靠大量過濾。最後在把失敗當成 bug 之前,先參考 references/interpreting-failures.md 來解讀失敗案例。若是 smart contracts,請先確認 EVM 特有的說明,並把 state model 保持得明確。
property-based-testing 技能 FAQ
property-based-testing 會取代一般測試嗎?
不會。這個技能最有價值的地方,是在一般範例容易漏掉邊界情況,或是某一個 property 就能涵蓋很多行為的時候。請保留用來防止回歸的範例測試,並在比起少數幾個案例、一個通用規則更清楚的地方使用 property-based-testing。
這份 property-based-testing guide 對新手友善嗎?
如果目標行為很簡單,而且 property 很明確,例如 roundtrip 或 idempotence 檢查,那就算友善。但如果規格本身不夠明確,就會變得比較難,因為 PBT 需要先有清楚的合約,generator 才會有用。
什麼情況下不該使用這個技能?
如果行為主要由 UI 驅動、具有高度非決定性,或根本無法表述成穩定的 property,就不要先選它。當唯一可用的 oracle 是一長串重新實作、只是把 production code 再鏡像一次的邏輯時,也不是很合適。
它適用我的語言或框架嗎?
這個技能支援許多生態系,包括 Hypothesis、fast-check、proptest、jqwik、ScalaCheck、FsCheck、StreamData、QuickCheck,以及像 Echidna 和 Medusa 這類 smart contract fuzzers。如果你的技術棧不在這份清單內,底層方法仍然有幫助,但你可能需要調整測試語法與 strategy API。
如何改進 property-based-testing 技能
提供最強的 property,不只是目標
最好的結果來自於把「確切要保證什麼」講清楚。例如:對 Unicode 字串來說,normalize(normalize(x)) == normalize(x) 就比「測試 normalize」更好。當 property 夠具體、可被反例推翻,而且和已知合約直接相關時,property-based-testing 技能的表現會更好。
提供會影響 generator 的限制條件
常見失敗模式包括:非合法輸入、過度過濾的 strategy,以及 property 太弱,抓不到真實 bug。你可以透過說明可接受範圍、格式規則、大小限制,以及是否預期會丟出例外,來提升輸出品質。如果某個 property 只應該在驗證之後才成立,也請明確說出來。
從失敗範例持續迭代
當第一個測試失敗時,不要只要求修正。請提供縮小後的 counterexample、原本想要的規則,以及任何定義邊界行為的文件。這樣技能才能分辨是真 bug 還是 property 定錯,並產出更強的第二輪測試或重構建議。
