🚥

TypeScript を前提とした楽観的テスト基準について

2025/03/07に公開

みなさん、テスト書いてますか?

この記事は「テスト書いてますか?」という質問に「100%書いています」と答えられない私が、
どのような基準でテストを書く/書かないを決めているのかについて書きます。

Q.なぜ書かないのか?

A. TypeScriptで型安全なコードを書いているから。

日頃開発しているアプリでは、おおよそシンプルなmap, filter的な処理がコードの80%以上です。
インフラを意識しない視点では、次のようなデータの流れです。

  • Prisma でデータを取得(DBから取得したデータに型が付いている)
  • tRPC経由でレスポンス(バックエンドの型情報がフロントで参照できる)
  • TanStack Query経由でレスポンスされたデータを取得
  • Reactで表示

このようなデータのリレーにおいては、型安全であることが非常に重要です。
型のない言語で書いていたら、引数/戻り値の型をテストでチェックしないと安全に開発を進められないと思います。しかし適切にTypeScriptを使っていれば、引数/戻り値のデータ構造の取り扱いが適切かどうかは、テストを書かなくても型チェックで保証されます。

ちなみに「適切にTypeScriptを使う」とは、以下のようなことを指します。

  • any, as といった型の安全性を脅かす可能性のあるキーワードを慎重に扱う
  • TypeScriptの外側から入ってくる値をパースする

「パース?バリデーションじゃないの?」と思った方は、以下の記事を読んでみてください。

https://zenn.dev/mj2mkt/articles/2024-10-11-parse-dont-validate

Q.どのようなケースでテストを書いているのか?

A. 以下のようなケースでテストを書いています。

  • プリミティブな値を扱う処理
    • 文字列
    • 数値
    • 日付
  • 閾値を考慮する処理
  • 正規表現を使用している処理
  • ユーティリティー

簡単にテストを書くケースを示します。

  • DataURLをパースする処理
  • 年度の計算(日本時間 4/1 00:00を境界とする)
  • 2次元配列の列のインデックスをExcelの"A,B,...Z,AA,AB..."へ変換する処理
  • Setの拡張クラス(Pythonのset相当のメソッドを用意)

こういった処理を扱うコードは、実装だけ読んでも正しく実装されているかすぐに分からなかったりします。だからしっかりテストケースが書かれていないと安心して使えません。私のチームではPRにいつでもテストをリクエストできます。だから自分ではテストが必要だと思わないケースでも、コードに不安を感じるメンバーがいたらテストを書く、という感じです。

ときどき開発過程でいくつかの値をハードコードして正しいことを確認し、テストを残さない人がいるんですが、そういうコードにはテストを書いてもらわないとPRを通さないですね。

一つの基準として「開発過程でconsole.logを仕込むなら、代わりに単体テストを検討してください」と伝えています。あるコードについて実装している本人が正しさを確認したくなるなら、他のメンバーはもっと難しく感じるはずです。そういうケースではテストを書いています。

まとめ

どのような基準でテストを書く/書かないを決めているのかについて、
チームメンバーのレベルに依存しているのであいまいな基準です。

しかし、適切にTypeScriptを使いつつ型レベルプログラミングをかなり頑張っているので単体テストのカバレッジの低さほどにはコードに危うさを感じずに開発できています。

TypeScriptの安全性にガッツリ頼っている開発スタイルなので、TypeScript様様ですね。

Discussion