スポンサーリンク
概要
「単体テストの考え方/使い方」を読んだので感想を書こうと思います。
スポンサーリンク
書籍概要
どんな本?
単体(unit)テストの原則・実践とそのパターン ― プロジェクトの持続可能な成長を実現するための戦略について解説。
優れたテストを実践すれば、ソフトウェアの品質改善とプロジェクトの成長に役立ちます。逆に間違ったテストを行えば、コードを壊し、バグを増やし、時間とコストだけが増えていきます。生産性とソフトウェアの品質を高めるため、優れた"単体テスト"の方法を学ぶことは、多くの開発者とソフトウェア・プロジェクトのために必須といえるでしょう。
本書“単体テストの考え方/使い方”では、単体テストと統合テストの定義を明確にします。そして、どのようなテストに価値があるのかを学び、どのテストをリファクタリング、もしくは削除するのか、ということについて考え、そのことがプロジェクトの成長にどう繋がるのかを見ていきます。
C#のコード例で解説しますが、どの言語にも適用できる内容です。Manning Publishing: Unit Testing Principles, Practices, and Patterns の翻訳書。
- 著者:Vladimir Khorikov、翻訳:須田智之
- 2022年12月 発行
- 416ページ
- 定価4,488円(税込)
スポンサーリンク
内容のまとめと感想
テスト関係の書籍は多数ありますが、本書はJUnitなど、xUnit系のいわゆるテストコードを実装して対象をテストする自動単体テストに関する書籍です。
これまでもJUnitに関するテストに関する書籍は何度か本ブログでも紹介していますが、本書の大きな特徴はテストの考え方に大きくフォーカスしている点です。
先に挙げた書籍はどちらかといえば、JUnitなどのユニットテストフレームワークの使い方にフォーカスしたもので、実際にこういった自動テストがどういったものなのかを、ハンズオンで学ぶ事に重点を置いたものです。
一方で本書は、それらユニットテストを実際のプロダクトに適応する際に、どういったテストコードを書いたら良いのかといった、考え方を学ぶことができるようになっています。
ユニットテストコードをある程度書いたり読んだ事があり、「モックやスタブだらけで、果たしてこのテストコードに意味があるのだろうか?」、「何をテストしたらいいのだろうか?」と何か腑に落ちないモヤモヤを感じた事があるような人は本書を読むと、ユニットテストで書くべき内容の指針を掴む事ができると思います。
(逆に言えば、ユニットテストの基本的な書き方に関してはあまり言及しないので、ユニットテストを書いたこともないという人はいきなり本書を読むのはオススメしません。まずは基本的な作法を学べる入門書等で学んだ方が良いと思います。)
Googleのソフトウェアエンジニアリングと共通点多し
同様なユニットテストの考え方を学ぶ書籍として、以前に本ブログで紹介した「Googleのソフトウェアエンジニアリング」が挙げられます。
これはテストだけにフォーカスした書籍ではないものの、Googleの経験則による「良いユニットテスト」に関して説明がされており、本書で説明される内容と多くの共通点があります。
お互いの内容を補完する事ができ、理解が深まるので併読する事をオススメします。
インテグレーションテストもカバー
テストピラミッドでいうところの、インテグレーションテストの内容も本書でカバーされています。
一般的にユニットテストとインテグレーションテストは、どちらも同じユニットテストフレームワークで実装する事が多いので、本書では同じコードベースで両者の違いを学ぶ事ができます。
実装や設計に関係する話も言及
良いテストを書くためには必然的に、テストがしやすく責務が分離された設計にする必要となります。
なので本書ではコードをリファクタリングしながら、より良いコード構造に直す方法に関しても学ぶ事ができます。
(DDDっぽいようなコードの構造に関して少しだけ学べる。)
C#による説明
本書ではプログラム言語としては「C#」、テストフレームワークとしては「xUnit.net」が使用されています。
とはいってもあくまで考え方にフォーカスした書籍ですので、 特定の言語やフレームワークに極力依存しない説明がメインで、C#を使った事がないよという人でも読む上で困ることは少ないと思います。
各部のざっくりとしたまとめと感想
本書は全4部、11章で構成されています。各部ごとにざっくりとした内容などを個人メモ的に説明します。
第1部 単体(unit)テストとは?
まず、ユニットテスト(UT)自体の目的や効果といった、「なぜやる必要があるのか?」に関してが書かれています。
UTの存在意義は持続可能な開発を実現するためにあり、開発が進む事によって成長が鈍化することを防ぐことに意義があるとされています。
(テストがない状態や、質の悪いテストしかない状態だと、ソフトの成長に伴いリグレッションが発生したり、適切なリファクタリングができなくなってしまう。)
そのために必要となる価値の高いテストに関しての考え方が、本部では説明がされています。
そしてUTを書くための基本的なスタンスとして、「古典学派」と「ロンドン学派」の2つが紹介されています。
前者が、依存関係も含めて極力本物のオブジェクトを使用したテストを実装することに重点を置いているのに対して、後者は依存クラスをモックスタブで積極的に置き換えてテスト対象にフォーカスする事に重点に置いています。
モックスタブを多用する事で、壊れやすく、リグレッションの検出もされにくいといった、デメリットが多くあり、価値の高いテストを書くために著者は古典学派のテストを推しています。(Googleのソフトウェアエンジニアリングでも同様。)
第2部 単体テストとその価値
第1部で説明のあった価値の高いテストを書くための、考え方やノウハウが多く示されているのが2部になります。
UTが満たすべき考え方(4本の柱)、モックやスタブといったテストダブルの適切な使い方、テストの手法(何をチェックする?)、リファクタリングの手法といった形で説明が行われます。
前半は第一部で説明があった内容を深掘りしていくようなもので、後半は実際のコードベースをどのようにリファクタリングしていくか?といった実践的な内容になっています。(関心事が分離できていないコードを、ヘキサゴナルアーキテクチャへリファクタリングしていくという内容。この辺りはUT色は薄め。)
有効なテストを書くために、内部の実装詳細ではなく、観測可能な振る舞いをテストするという事が大切とこの部では説明されています。
これは、第一部で説明があった古典学派のテスト手法に関するもので、privateメソッド(メンバ)や実現する機能の一部のクラスだけをテストするような、実装の詳細のテストはやめようねという事につながるかと思います。(これもGoogleソフトウェアエンジニアリングで言及されている内容)
第3部 統合(integration)テスト
第3部では、統合テスト(IT)に関して、その目的や書き方などに関して説明がされている章です。
UTは速度および、分離の観点からDBやファイル、通信などの外部とのやりとりはテストダブルに置き換えているのに対して、ITは実際にDBなどを使用してテストするのが特徴です。(ただし、管理下にない外部のAPIなどに関してはテストダブルによって置き換える)
ログに対するテストに関して書かれているのも興味深いです。一般的な内部向けのログは実装詳細なのでテストすべきではないが、ユーザが見れるような類のサポートログ情報などは、外部から観測可能な振る舞いとしてモックによってテストすべきとしています。
ITで一般的によく行われるのは、DBとの接続を行った状態でテストになるため、DBを使用したテストに関するプラクティスに関しても書かれています。マイグレーションなどのデータの状態の保持方法や、トランザクション、データの後始末などなど、DBテストにおいて必要であったり、考慮が必要な部分に関して幅広く触れています。
第4部 単体テストのアンチ・パターン
プライベートメソッドのテストなど、UTにおけるアンチパターンが書かれています。
これまでの1~3部と比較すると付録的な短い内容になりますが、どの内容も統制の取れていないUTでやりがちな内容だと思うので、定期的に見直したい内容です。
まとめ
UTに関して、どういったテストをすべきなのか?といった考え方を学ぶ事ができる書籍です。リファクタリングを通して、良いコードに設計し直す方法に関しても学ぶ事ができます。
個人的には、「Googleソフトウェアエンジニアリング」を読んでユニットテストに関しての「もやもや」がかなりクリアになりましたが、本書で書かれた内容と多くの共通点がありました。先にこちらを読んでいても同様の結果が得られたと思います。
UTは書いた事があるが、何かしっくりこなかったり、どうテストしたらいいんだろうか?などなど、迷った時に一度読んでみると良いと思います。