Principle Test Behavior Not Implementation

作者 cursorccb5507cec15無授權條款10K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫今天更新

Apply when you write, change, or keep a test. Call the code the way its users do and assert the result they observe against a literal expected value. If the test would still pass when every imported function returns undefined, rewrite the assertion or delete the test.

AI 產生的概覽

一套撰寫測試的準則:斷言可觀察行為與字面期望值,而非實作細節。

功能
此技能提供一項測試審查原則:測試應像使用者那樣呼叫程式碼,並針對字面期望值斷言其觀察到的結果。它提供一個檢查方式——若所有被匯入的函式都回傳 undefined 時測試仍能通過,即代表有問題——並列出五類無法通過此檢查的測試形態,例如斷言過弱、僅斷言 mock、自我參照期望、常數釘死,以及 fixture 斷言 fixture。接著說明修正方式:以具體輸入呼叫受測對象並斷言字面輸出或可觀察效果;對於「不存在」的情況,在同一測試中以另一輸入斷言其存在;對於常數,改為測試讀取該常數的機制;對於 mock,斷言其收到的內容或呼叫後的狀態;若不存在這類斷言則刪除該測試。它也指出應保留的測試,例如跨資料表列之間的關係測試,以及 *.test-d.ts 檔案中的編譯期檢查。
適用情境
適用於撰寫、修改或保留測試時,確認該測試確實能因缺陷而失敗。也適合審查現有測試中過弱或與實作耦合的斷言,並判斷某個測試應重寫還是刪除。
執行需求
無需任何工具、套件或憑證;僅為說明性指示,不附帶指令碼。

Test Behavior, Not Implementation

A test calls the code the way its users do and asserts the result they observe against a literal expected value. A test that asserts which calls the code made, or restates a constant the code contains, does neither.

The check: before you keep a test, ask whether it would still pass if every function it imports returned undefined. If yes, it observes no behavior and cannot fail for a defect. Rewrite the assertion or delete the test.

Why: A test that cannot fail for a defect costs CI time and review attention and catches nothing. A constant pin also fails when someone edits the constant or the prompt it restates, so it prevents that edit.

Five shapes that still pass when every imported function returns undefined:

  • Weak or no assertion. No expect, or only toBeDefined, toBeTruthy, not.toThrow, toBeInstanceOf, toBeGreaterThan(0).
  • Mock or absence only. Only toHaveBeenCalled, not.toHaveBeenCalled, toBeUndefined, toEqual([]), toHaveLength(0), not.toBe(wrongValue).
  • Self-referential. The expected value comes from the code under test: expect(f(a)).toBe(f(a)), expect(parsed.url).toBe(buildUrl(...)).
  • Constant pin. The assertion restates a hand-maintained constant, config default, table row, or prompt string: expect(LIMITS.maxTools).toBe(8), expect(PROMPT).toContain("You are").
  • Fixture asserts fixture. The assertion reads data the test built or a value computed in beforeEach, and the subject never runs inside the body.

The fix: call the subject inside the test body with one concrete input and assert the literal output or the observable effect, expect(slugify("Hello, World!")).toBe("hello-world"). For an absence, assert the presence on the other input in the same test. For a constant, test the mechanism that reads it with one input instead of restating the value. For a mock, assert the payload it received or the state after the call, not that it was called. When no such assertion exists, delete the test.

Keep a test of a relation across a table's rows (a key present in two tables, a parent that exists), and a compile-time check in a *.test-d.ts file.

來源與署名

來源:cursor/plugins位於pstack/skills/principle-test-behavior-not-implementation提交ccb5507

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架