6分で読めるby hana_boy

単体テスト実装時の観点

単体テスト観点表

概要

以下書籍を基に、単体テスト実装時の観点についてまとめました。

「単体テストの考え方/使い方」
著者:Vladimir Khorikov
訳:須田 智之
出版年:2022年
出版社:マイナビ出版
リンク:https://www.amazon.co.jp/%E5%8D%98%E4%BD%93%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E8%80%83%E3%81%88%E6%96%B9-%E4%BD%BF%E3%81%84%E6%96%B9-Vladimir-Khorikov/dp/4839981728

背景

単体テストのテストコードを実装する際、基本的にテスト対象のコードに沿って実装します。

テストコードを実装するファイルは、ビジネスロジック等を記載している箇所に依存するため、可能な限りテストコードを実装しやすいアーキテクチャで、プロダクション・コードを実装した方がよいです。

上記のような観点を持ってテストを作成する場合、アーキテクチャの修正をした方が良いと判断される可能性があります。

そのため、アーキテクチャに影響する可能性がある実装時の観点と、アーキテクチャに影響しないテスト観点を分けて記載しております。

単体テスト実装時の観点

観点

思想としては、「単体テストの考え方/使い方」に書いてある内容を基に書いています。

観点GoodパターンBadパターン理由
ControllerやConsoleのテストファイルにて、ビジネスロジックの観点の単体テストを書いていないかどうか。HelperやTraitにビジネスロジックを記載し、単体テストではそのインスタンスorメソッドのレスポンスについてテストする。複雑なビジネスロジックも、ControllerやConsoleのテストファイルに記載する。Controllerでビジネスロジックをテストする場合、同じロジックを他のControllerで使うときに、同じ観点のテストを2つ以上作る必要があるため。
1つのテストメソッドの中で、複数の観点のテストを記載していないかどうか。観点ごとに、テストを分割して実装する。
データプロバイダの利用を検討する。
Assertした後に、テストデータを作成して、再びAssertする。単体テストが失敗した際、どの観点にてテストが失敗したかが、分かりにくくなるため。
ロジックを修正した際、どのテストコードを修正すればいいか分からなくなるため。
Mockを使わずに単体テストを実装できる場合でも、Mockを利用していないかどうか。なるべくMockは利用しない。
外部メソッドを呼び出す場合のみMockを利用するようにする。
AssertDatabaseHas()メソッド等でテストできるにも関わらず、Mockを利用する。Responseに影響のないリファクタリングを行った際、正しい挙動にもかかわらずテストが失敗する可能性があるため。
プライベート関数をテストしていないかどうか。プライベート関数をテストしたい場合、プライベート関数を利用するpublicの関数をテストする。プライベート関数をテストするために、アクセス修飾子を変更してテストする。リファクタリングを行った際、正しい挙動にもかかわらずテストが失敗する可能性があるため。
テストコードのロジックに、プロダクション・コードのロジックを使用していないかどうか。テストコードで、同じロジックを使う必要がある場合は、期待する返り値を定義して、ロジックを使わないようにする。テストコード内で、プロダクションコードのロジックを使って値を作成する。テストコード内で同じロジックを使ってテストした場合、通るのが当たり前のテストになってしまうため。
プロダクション・コードの中に、テストでのみ使用するメソッドが含まれていないかどうか。インターフェースを使い、プロダクション用とテスト用でクラスを分ける。プロダクション・コードの中に、テストでしか使わないメソッドを記載する。障害が起こった際などでコードを見たときに、そのロジックがプロダクション・コードに影響しているかどうかわからないため。
「メソッドが呼び出されているかどうか」自体を観点にテストしていないかどうか。Responseの値や、DBやファイルの値をテストする。
「メソッドが呼び出された結果どうなったか」という観点でテストを作る。
テストコード内で操作を行い、「メソッドが呼び出された」ことをテストする。リファクタリングを行った際、正しい挙動にもかかわらずテストが失敗する可能性があるため。
テストコードが、AAAパターンとなっているかどうか。
参考:https://tech.pepabo.com/2021/08/23/writing-unit-test-with-aaa/
AAAパターンとなっていない場合、「データ作成→動作実行→結果や影響チェック」となるような順番で実装する。Assertした後にデータ作成(Arrange)する。上から下に向かってテストするため、可読性が落ちるため。