特徴量が増え続けるMLシステムで「壊れないテスト設計」に出会った話【単体テストの考え方/使い方・書評】

特徴量が増え続けるMLシステムで「壊れないテスト設計」に出会った話【単体テストの考え方/使い方・書評】

特徴量が「増え続ける」システムの怖さ

機械学習モデルを長期運用するシステムには、一般的なWebアプリとは異なる変化圧力がある。特徴量だ。

モデルの精度を上げるために特徴量を追加する。不要になった特徴量を削除する。定義が変わって既存の特徴量を更新する。こうした変更は、運用フェーズに入ってからも継続的に発生する。しかも1つの特徴量の変更が、パイプライン全体の入出力スキーマに影響する。

理想は「特徴量単位で独立して開発・テストできる設計」だ。ある特徴量を追加しても、他の特徴量のテストが壊れない。削除しても同様。その設計に到達する過程で、本書の核心概念が正確に地図として機能した。

特に刺さった原則3選

原則①:関数型コアと命令型シェルに分ける

本書の設計パターンの中で、MLシステムへの応用可能性が最も高いのがこれだ。

  • 関数型コア:副作用なしの純粋関数。「特徴量の値を受け取り、変換・計算した結果を返す」だけの層。
  • 命令型シェル:DBやAPIなど外部依存を持つ調整役。「どの特徴量をどのソースから取得し、コアに渡すか」を担う層。

この分離を特徴量エンジニアリングに適用すると、各特徴量の計算ロジックが純粋関数として独立する。入力と出力だけが定義されるため、テストは「この値を渡したらこの値が返る」という形で完結する。外部DBへの接続も、他の特徴量への依存も不要だ。

結果として、特徴量単位での独立した開発・テストが可能になった。ある特徴量の計算ロジックを変更しても、他の特徴量のテストに影響しない。これが「特徴量の追加・削除に耐える設計」の正体だった。

原則②:関数型コアはユニットテスト、命令型シェルは統合テストでテストする

設計を分けたら、テストの種類も分ける。これが本書のもう一つの核心だ。

  • 関数型コア(純粋関数)へのテスト:ユニットテスト。入力を渡して出力を検証するだけ。モック不要。実行が速く、リファクタリング耐性が極めて高い。特徴量ごとに独立して実行できる。
  • 命令型シェル(コントローラー)へのテスト:統合テスト。外部DBへの実際の接続、パイプライン全体の疎通確認。主要なパスだけをカバーする。

この役割分担がテストピラミッドを自然に実現する。ユニットテストを多く・速く・特徴量単位で実行し、統合テストはパイプラインの結合部分だけを確認する。特徴量の計算ロジックを変えたとき、ユニットテストだけが走れば十分だ。統合テストを毎回通す必要がない。

原則③:「必要なテストか」を問う——カバレッジは目的ではなく結果

本書は「テストを増やせ」とは言わない。むしろ逆だ。

価値のあるテストとは、将来の変更を安全にするテストだ。そのフィルターを通したとき、「書くべきテスト」は自然に絞られる。著者が示す4つの特性——リグレッション保護・リファクタリング耐性・高速フィードバック・保守性——をすべて高いレベルで満たすテストは、実は多くない。

MLシステムの文脈で特に重要なのは「リファクタリング耐性」だ。特徴量の定義が変わるたびにテストを直していては、テストが変更の障壁になる。「このテストは特徴量の振る舞いを検証しているのか、それとも実装の詳細を検証しているのか」を問うことで、負債になるテストを事前に弾ける。

カバレッジは「意味のあるテストを書いた結果として上がるもの」であり、上げることを目標にした瞬間に手段と目的が逆転する。

この本が向いていない人

  • 「pytestの書き方」を求めている人:本書はテストの構文やライブラリの使い方ではなく、何をどうテストすべきかという設計思想の本。pytest入門書と組み合わせる必要がある。
  • 実験・探索フェーズのMLコードに使いたい人:PoC段階や使い捨てのノートブックには本書の原則はオーバースペックだ。本書が力を発揮するのは、長期運用・チーム開発・継続的な変更が前提のシステムに対してだ。
  • テストを一切書いていない段階の人:まず「テストを書き始める」ための入門書を先に読むことを勧める。本書はテストを書いていて「何かがおかしい」「変更が怖い」と感じてから読む本だ。

今日から試せること

手元のMLシステムの特徴量計算コードを1つ選んで、「これは純粋関数か?」を問うだけでいい。

入力を受け取り、DBもAPIも触らず、計算結果だけを返す関数になっているか。なっていなければ、外部依存の部分を引数として外に出すリファクタリングが次のアクションだ。それだけで、その特徴量は独立してテスト可能になる。

特徴量の変更を「怖い作業」から「安全な作業」に変えるための、最初の一手がここにある。

Bitnami