imu-note
いむたろ
いむたろ
@imutaroh
新卒エンジニア / データ基盤 × AI

What — テストは約束が破られた瞬間に名指しで教える装置

テストが守るのは文法ではなく約束。build も run も通るのに、約束が破られた瞬間に「どこが」を名指しで教えてくれる。

約束とは「この関数や API は、この入力に対してこう振る舞う」という取り決めのこと。たとえば「200 なら body を返す」「503 が続いたらリトライする」「全ての行に LOAD TS が付く」。

コードのミスは 2 種類に分かれ、守る道具が違う。

ミスの種類咎める道具
文法のミス型が合わない・未使用変数go build / go vet
約束のミス動くけど結果がおかしいテストだけ

テストは咎めるだけでなく、何が原因かを瞬時に出してくれるので、ドキュメントの役割も持つ。

How — 正常系・異常系・想定外で分けて書く

「事前に想定できたか」で 3 つに読み分ける。テストに書けるのは前の 2 つだけ。

区分テストに書けるか
正常系200 なら body を返す書く
異常系503 が続く。想定したエラーが出るか、リトライできるか書く
想定外まだ見たことがない入力書けない。本番で見つけ次第ハンドリングし、異常系テストに昇格する

エラーハンドリングは想定外の入力への振る舞いを決める別の道具で、テストの代わりにはならない。

テスト名は 2 つの型のどちらかに収める。

  • {条件} なら {結果}: 入力や状況で振る舞いが分かれるとき。分岐 1 つにつき 1 本
  • {対象} は {不変条件}: 入力によらず常に成り立つ性質。全ての行に LOAD TS が付く、など
It("{入力や状況} なら {戻り値・副作用・呼ばれないもの}", func() { ... })
It("{出力の対象} は {常に成り立つこと}", func() { ... })

// 条件が思いつかないとき: 何を渡すと違う結果になるか、を先に列挙する
// 結果が思いつかないとき: Expect に何を載せるか、を先に決める

どこまで書く — 4 つの問いで止める

テストは書こうと思えば無限。異常系は特に。1 本書くたびに次の 4 つで足を止める。

  • これを黙って変えたら、それを頼りにしている他の関数や結果に影響が出るか
  • 型やコンパイラがすでに保証していないか
  • 他のテストが経路上でそこを通っていないか。通るなら新たに書かない(経路ベースで作る)
  • fake のコストに見合う確信が増えるか。動くけど壊れているのに気付けない箇所か
Success

書けるのは正常系と異常系だけで、想定外は本番で拾って異常系に昇格させる。書く量は 4 つの問いで止める。

関連