コンテンツにスキップ

Writing Good Unit Tests

チェック

  • [ ] 本文を確認した
  • [ ] 概要を確認した
  • [ ] タグを確認した
  • [ ] inbox/ 直下へ移行した

概要

良い unit test は coverage を満たすためではなく、振る舞いへの confidence を得るために書く、という記事。 内部関数や技術層をそのまま mock するのではなく、public interface と system edge を意識して test する。 browser app なら user event と network mock、backend なら場合によって in-memory database を使うなど、dogma より confidence を重視する。

本文

記事は、後から coverage を満たすために unit test を追加すると、coverage が vanity metric になりやすいという経験から始まる。 大事なのは line coverage ではなく、deployment confidence と behavioral integrity。

まず、function ではなく behavior を test する。 src/tests/ を 1 対 1 で mirror し、内部関数ごとに test を書くと、refactor のたびに test が壊れる。 内部実装を変更しても test suite を変えなくてよいなら、振る舞いを test できている。 test のためだけに visibility を上げるのは避ける。

次に、内部ではなく edge を mock する。 frontend で hook や store を mock すると、React Query へ置き換えるだけで test が壊れる。 代わりに HTTP request を mock し、UI event や画面表示で behavior を確認する。 system edge は、network、third-party service、time、randomness、I/O など。

backend では、database を常に mock すべきとは限らない。 in-memory database で数千 test を高速に回せるなら、mock より実際の behavior に近い確認ができる。 dogma ではなく、速く、安定し、confidence が高い方法を選ぶ。

要点

  • Coverage ではなく confidence を目的にする。
  • 内部関数ではなく public behavior を test する。
  • Mock は internal layer ではなく system edge に置く。
  • In-memory database は pragmatic な選択肢になりうる。
  • Test のために設計を歪めない。

タグ

testing #unit-test #test-design #frontend #backend