彼の講演で TDD、どこがうまくいかなかったのか 、イアンクーパーは、ケントベックの当初の意図をTDDのユニットテストの背後に押し出し(クラスのメソッドではなく、動作をテストするため)、テストを次のように結合しないように主張します実装。
一般的なサービスとリポジトリのセットを持つシステムでのsave X to some data source
のような動作の場合、テストを実装の詳細に結合せずに、リポジトリを介してサービスレベルで一部のデータの保存を単体テストするにはどうすればよいですか(特定のメソッドを呼び出すような)?この種のカップリングを回避することは、実際には何らかの努力の価値がありませんか?
saving X to data source
は外部依存関係と通信することを意味するため、特定の例は通常、特定のメソッドが呼び出されたかどうかをチェックしてテストする必要があるケースです。したがって、テストする必要がある動作は通信は期待どおりに発生しています。
しかし、これは悪いことではありません。アプリケーションとその外部依存関係の間の境界インターフェースは実装の詳細ではありませんです。実際、これらはシステムのアーキテクチャで定義されています。つまり、そのような境界は変更される可能性が低い(または変更が必要な場合は、最も頻度の低い種類の変更になります)。したがって、テストをrepository
インターフェースに結合しても、あまり問題は発生しません(問題がある場合は、インターフェースがアプリケーションから責任を盗んでいないかどうかを検討してください)。
ここで、UI、データベース、およびその他の外部サービスから切り離された、アプリケーションのビジネスルールのみを検討します。これは、コードの構造と動作の両方を自由に変更できる必要がある場合です。これは、アプリケーションの全体的な動作に変更がない場合でも、テストと実装の詳細を組み合わせると、運用コードよりも多くのテストコードを変更しなければならない場所です。ここで、State
ではなくInteraction
をテストすることで、速度を上げることができます。
PS:状態または相互作用によるテストがTDDの唯一の真の方法であるかどうかを言うのは私の意図ではありません-私はそれが適切なツールを適切な仕事に使用することの問題であると信じています
その話の私の解釈は:
それは話では述べられていませんが、アドバイスの想定されるコンテキストは次のようなものだと思います:
したがって、コンポーネントをテストすることは、何かがまだ合理的にユニットテストと呼ばれる可能性がある最大のスコープです。これは、一部の人々、特に学者がこの用語を使用する方法とはかなり異なります。これは、典型的な単体テストツールチュートリアルの例とは異なります。ただし、ハードウェアテストではそのオリジンに一致します。ボードとモジュールはユニットテスト済みであり、ワイヤーとネジではありません。または、少なくとも、ねじをテストするために模擬ボーイングを構築しないでください...
それから外挿して、自分の考えのいくつかを投げ入れ、
それを適切かつクリーンに行う場合、モックツールはほとんど必要ありません。システムごとに数回しか使用されません。
データベースは一般に共同作業者であるため、あざけるのではなく、偽造されます。これを手作業で実装するのは面倒です。幸いなことに、そのようなもの すでに存在 。
基本的なテストパターンは、一連の操作(ドキュメントの保存と再読み込みなど)を実行することです。動作することを確認します。これは他のテストシナリオと同じです。このようなテストが失敗する原因となる可能性のある(機能する)実装変更はありません。
例外は、データベースレコードが書き込まれるが、テスト中のシステムでは決して読み取られない場合です。例えば監査ログなど。これらは出力なので、モックする必要があります。テストパターンは、一連の操作を実行することです。指定されたメソッドと引数で監査インターフェースが呼び出されたことを確認します。
ここでも、 mockito のようなタイプセーフなモッキングツールを使用している場合、インターフェースメソッドの名前を変更してもテストエラーは発生しません。テストをロードした状態でIDEを使用すると、メソッドrenameとともにリファクタリングされます。使用しない場合、テストはコンパイルされません。
私の提案は、状態ベースのテストアプローチを使用することです。
[〜#〜] given [〜#〜]テストDBは既知の状態にあります
[〜#〜] when [〜#〜]サービスは引数Xで呼び出されます
[〜#〜] then [〜#〜]読み取り専用リポジトリメソッドを呼び出して戻り値を確認することにより、DBが元の状態から予期された状態に変更されたことをアサートします
そうすることで、サービスの内部アルゴリズムに依存せず、テストを変更する必要なく、その実装を自由にリファクタリングできます。
ここでの唯一の結合は、DBからデータを読み取るために必要なサービスメソッド呼び出しとリポジトリ呼び出しへの結合です。