ヘキサゴナルアーキテクチャの基本構造と単体・結合テスト(単体テストの考え方/使い方の読書メモ)

単体テストの考え方/使い方を読んだ。タイトルが単体テストだが、手動テスト・結合テスト・E2Eテストまで含めたテスト全般に適用できる普遍的な考え方を開発者目線で述べており、何をどうテストすべきか、テストすべきでないか、モックをどこに使うかといった判断を的確に行えるようになる。その考え方をベースにアプリケーションの設計論にまで踏み込んで解説しており、現実の開発への適用をイメージしやすかった。テスト駆動開発のような特定の方法論を展開するものではないので、あらゆる開発スタイルの人に読んでほしい本。ヘキサゴナルアーキテクチャドメイン駆動設計の基本的な知識があると読みやすいと思う。

以下勉強メモ。

  • アプリケーションサービス層とドメイン層に明確に分離する。
    • アプリケーションサービス層
      • ドメイン層のクラスをインスタンス化し呼び出すだけ。状態やドメインロジックを持たない。
      • プロセス外依存とドメイン層の間の仲介、例えばDBを読み取ってドメイン層に渡したり、ドメイン層からの出力をDBに書き込んだりはここの責務。
      • 結合テスト(統合テスト)で保護する。
      • プロセス外依存のうち、管理下にない依存のみモックに置き換えて、やり取りをテストする。管理下にある依存(自アプリしか使わないDBなど)は観測できる境界とはみなさずそのまま使ってテストを構築することでリファクタリング耐性を確保する。
    • ドメイン
      • プロセス外依存を持たない。
      • 単体テストで保護する。ただし単純でロジックを含まないコードは単体テストしない。
      • モックを使う必要がない。
    • 分離できていないと、過度に複雑で、カプセル化ができておらず関心事の流出したコードになり、適切なテストができなくなる。
  • 観測できる境界における入出力をテストする。中身はブラックボックスとして扱う。つまり処理結果の確認で直接DB等の内部状態を見たりしない。これによりリファクタリング耐性を確保する。
  • 結合テストやE2Eテストは、単体テストよりもリファクタリング耐性・退行に対する保護が強いので、テストの実行時間が許容できる範囲で充実させる。ドメインロジックは単体テストで検証することで実行時間を抑えることができる。極端に言えば、実行時間が十分に短いならアプリ全体をブラックボックスとして全テストケースをE2Eテストとすればよい。

似たような話は他の本でも触れているはずだが結構忘れているのと、テストという観点から納得感のある解説がされていて腑に落ちたのでよかった。

自社ではテストケースのドキュメントを書かないといけないルールだが、このアプローチと整合させるにはどうするのがいいか。ドキュメントを考える前に、そもそも機能要件・不具合修正内容に対して十分テストできているのかをどうレビューし記録するのが良いのだろう。コードメトリクスで保証できるものではないので、機能要件・不具合修正内容に対するテストケースとして入力と出力の一覧を書き出して、これをレビューことになるだろう。手動テストであってもここに手順を入れない(入れるとしてもメモ程度)ことで機能レベルのリファクタリング耐性を確保し作業効率の低下も防ぐ。次にこのテストケースを結合テストまたは単体テストとして実装できるなら実装し、例えばテスト名で紐づける。

しかしこれだと二重管理になっている。そもそもドキュメントは開発者以外でも読めて、開発者も非開発者も俯瞰しやすくレビューできるようにすることが目的なので、手動テストと自動テストで分離し、手動テストはドキュメントを普通に手書きする一方、自動テストについてはテストの実装からドキュメントを生成するのが良いだろう。生成するツールが見当たらないので自作するしかないか…。