プロジェクトのどの部分で、単体テストを書くことがほとんど、または本当に不可能ですか? データアクセス?ftp?
この質問に答えがあるとすれば、100% のカバレッジは神話ですよね?
プロジェクトのどの部分で、単体テストを書くことがほとんど、または本当に不可能ですか? データアクセス?ftp?
この質問に答えがあるとすれば、100% のカバレッジは神話ですよね?
ここで私は見つけました(ハッキングされたものを介して、Michael Feathersが答えになる可能性があると言っています:
彼は言います、
次の場合、テストは単体テストではありません。
- データベースと通信します
- ネットワークを介して通信します
- ファイルシステムに触れる
- 他の単体テストと同時に実行することはできません
- それを実行するには、環境に対して特別なこと (構成ファイルの編集など) を行う必要があります。
再び同じ記事で、彼は次のように付け加えています。
一般に、単体テストは小規模であると想定されており、メソッドまたはいくつかのメソッドの相互作用をテストします。データベース、ソケット、またはファイル システムへのアクセスを単体テストにプルすると、それらはもはやそれらのメソッドに関するものではなくなります。それらは、コードと他のソフトウェアとの統合に関するものです。
100%のカバレッジは神話ですが、80%のカバレッジが役に立たないという意味ではありません。もちろん、目標は100%であり、単体テストと統合テストの間で、それに近づくことができます。
単体テストで不可能なことは、顧客が製品に対して行うまったく奇妙なことをすべて予測することです。コードのこれらの気が遠くなるような変質を発見し始めたら、それらのテストをテストスイートにロールバックするようにしてください。
100%のコードカバレッジを達成することは、ほとんどの場合無駄です。これには多くのリソースがあります。
単体テストを行うことは不可能ではありませんが、収穫逓減は常にあります。単体テストで苦痛なことを単体テストすることは価値がないかもしれません。
目標は 100% のコード カバレッジではなく、80% のコード カバレッジでもありません。単体テストが書きやすいからといって、それを書く必要があるわけではありません。
テストの目的は、ユーザーが目に見える問題を最も手頃な方法で検出することです。
テストによってフラグが付けられた問題 (誤検知を含む) のオーサリング、保守、および診断の総コストは、特定のテストでキャッチされる問題に見合う価値がありますか?
テストがキャッチする問題が「費用がかかる」場合は、それをテストする方法を考え出し、そのテストを維持することに労力を費やす余裕があります。テストがキャッチする問題が取るに足らないものである場合、テストを作成 (および保守) することは (コードの変更があったとしても) 取るに足らないものである方がよいでしょう。
単体テストの主な目的は、開発者を実装エラーから保護することです。それだけでも、あまりにも多くの努力が無駄になることを示しているはずです. ある時点の後、正しい実装を得るためのより良い戦略があります。また、ある時点以降、ユーザーに見える問題は、ユーザーレベルまたは統合テストによってのみキャッチできる間違ったものを正しく実装したことが原因です。
何をテストしませんか? 壊れるはずのないもの。
コード カバレッジに関して言えば、実際に記述したコードの 100% を目指す必要があります。つまり、サード パーティのライブラリ コードやオペレーティング システムのコードをテストする必要はありません。そのコードはテスト済みであるためです。そうでない限り。その場合、それをテストしたいと思うかもしれません。または、既知のバグがある場合は、バグの存在をテストして、バグが修正されたときに通知を受け取ることができます。
テストデータベースをセットアップできるため、データアクセスが可能です。
一般に、「テストできない」ものは FTP や電子メールなどです。ただし、これらは通常、信頼できるフレームワーク クラスであるため、抽象化の背後に隠しているかどうかをテストする必要はありません。
また、100% のコード カバレッジだけでは十分ではありません。
GUI の単体テストも、不可能ではありませんが難しいと思います。
巨大で高価な(リソースまたは計算時間のコストで)セットアップを必要とするほとんどのテストは、統合テストです。単体テストは、(理論的には)コードの小さな単位のみをテストする必要があります。個々の機能。
たとえば、電子メールの機能をテストしている場合は、モックメーラーを作成するのが理にかなっています。そのモックの目的は、コードがメーラーを正しく呼び出すことを確認することです。アプリケーションが実際にメールを送信するかどうかを確認することは、統合テストです。
単体テストと統合テストを区別すると非常に便利です。ユニットテストは非常に高速に実行する必要があります。コードをチェックインする前に、すべての単体テストを簡単に実行できるはずです。
ただし、テストスイートが多くの統合テスト(データベースのセットアップと破棄など)で構成されている場合、テストの実行は簡単に30分を超える可能性があります。その場合、開発者はチェックインする前にすべての単体テストを実行しない可能性が非常に高くなります。
だからあなたの質問に答えるために:統合テストとしてよりよく実装されているネットユニットテストを行います(そしてゲッター/セッターもテストしないでください-それは時間の無駄です;-))。
@GarryShutler
私は実際に偽のSMTPサーバー(Wiser)を使用して電子メールを単体テストします。アプリケーションコードが正しいことを確認します。
http://maas-frensch.com/peter/2007/08/29/unittesting-e-mail-sending-using-spring/
そのようなことは、おそらく他のサーバーでも実行できます。それ以外の場合は、APIをモックできるはずです...
ところで:100%のカバレッジはほんの始まりに過ぎません...すべてのコードが実際に一度実行されたということを意味します....エッジケースなどについては何もありません。
ユニット テストでは、ユニットに属さないものはテストしないでください。そのコンテキストでユニットをテストすることは別の問題です。それが簡単な答えです。
私が使用する基本的なルールは、ユニットの境界 (通常はクラス、またはユニットが何であれ) に触れるものはすべてユニット テストし、残りはモックにすることです。一部のデータベース クエリが返す結果をテストする必要はありません。ユニットが正しいクエリを吐き出すことをテストするだけで十分です。
これは、単にテストするのが難しいものを省略してはいけないという意味ではありません。例外処理や同時実行の問題も、適切なツールを使用して十分にテストできます。
完全に決定論的ではないものはすべて、単体テストには使用できません。単体テストが常に同じ初期条件で成功または失敗するようにしたい - スレッド化、ランダムなデータ生成、時間/日付、または外部サービスなどの奇妙さがこれに影響を与える可能性がある場合は、単体テストでそれをカバーするべきではありません. 時間/日付は特に厄介なケースです。通常、現在の日付と時刻の機能に依存するのではなく、(コードとテストによって) 動作する日付を挿入するようにコードを設計できます。
とはいえ、単体テストだけがアプリケーションの唯一のレベルのテストであってはなりません。100% の単体テスト カバレッジを達成することは、多くの場合時間の無駄であり、すぐに収益の減少に対応します。
はるかに優れたのは、一連の高レベルの機能テストと、システムが「すべてが結合されたら」正しく機能することを確認するための統合テストです。これは、定義上、単体テストではテストされません。
「単体テストでテストしてはいけないことは何ですか?」* ゲッターとセッターだけの Bean。理由: 通常、別のテストに費やすべき時間の無駄です。
それらをテストすることはできますが、単体テストにはなりません。単体テストは、境界を越えないものです。たとえば、ネットワークを越えたり、データベースにアクセスしたり、サードパーティと実行/対話したり、テストされていない/レガシーコードベースに触れたりします。
これを超えるものはすべて統合テストです。
タイトルの質問の明白な答えは、APIの内部を単体テストするべきではなく、他の誰かの振る舞いに依存するべきではなく、自分が責任を負わないものをテストするべきではないということです。
残りの部分は、コードをその中に記述できるようにするためだけに十分であり、それ以上でもそれ以下でもありません。
大規模なプロジェクトで作業する場合は、100%のカバレッジが適切な目標ですが、ほとんどのプロジェクトでは、展開前に1つまたは2つのバグを修正しても、徹底的な単体テストを作成する価値があるとは限りません。
フォームの送信、データベースアクセス、FTPアクセスなどを非常に詳細なレベルで徹底的にテストすることは、多くの場合、時間の無駄です。作成中のソフトウェアが非常に高いレベルの信頼性(99.999%のもの)を必要としない限り、単体テストはやり過ぎであり、リアルタイムのシンクになる可能性があります。
非常に大規模で複雑なセットアップが必要なもの。もちろん、ftp(クライアント)をテストすることもできますが、その場合はftpサーバーをセットアップする必要があります。単体テストの場合、再現可能なテスト設定が必要です。あなたがそれを提供することができないならば、あなたはそれをテストすることができません。
FTP、SMTP、I/O 全般は、インターフェイスを使用してテストする必要があります。インターフェイスは、アダプター (実際のコード用) と単体テスト用のモックによって実装する必要があります。
単体テストで実際の外部リソース (FTP サーバーなど) を実行する必要はありません。
サードパーティのコードをテストしないという quamrana の回答には同意しません。これは単体テストの理想的な使い方です。ライブラリの新しいリリースでバグが導入された場合はどうなりますか? 理想的には、新しいバージョンのサードパーティ ライブラリがリリースされたときに、このライブラリの期待される動作を表す単体テストを実行して、期待どおりに動作することを確認します。
構成は、単体テストで十分にテストするのが非常に難しいもう 1 つの項目です。統合テストおよびその他のテストは、構成に対して実行する必要があります。これにより、テストの冗長性が減り、多くの時間が解放されます。構成を単体テストしようとすることは、多くの場合、軽薄です。
そもそもテストコードを単体テストする主な理由は、コードの設計を検証することです。100%のコードカバレッジを取得することは可能ですが、モックオブジェクトまたは何らかの形式の分離または依存性注入を使用せずに行うことはできません。
単体テストはユーザー向けではなく、リリース前にシステムを検証するために使用する開発者およびビルドシステム向けであることを忘れないでください。そのためには、単体テストを非常に高速に実行し、構成と依存関係の摩擦をできるだけ少なくする必要があります。メモリ内でできる限り多くのことを行い、テストからのネットワーク接続の使用を避けてください。
単体テストに必要な状態を設定するコードが、テストするコードよりも大幅に複雑になる場合は、線を引いて、機能をテストする別の方法を見つける傾向があります。その時点で、ユニットテストが正しいことをどのように知っているかを尋ねる必要があります!
FTP、電子メールなどは、サーバーエミュレーションでテストできます。それは難しいですが可能です。
一部のエラー処理はテストできません。すべてのコードには、発生することのないエラー処理があります。たとえば、Javaでは、インターフェイスの一部であるため、多くの例外をキャッチする必要があります。ただし、使用されたインスタンスがそれをスローすることはありません。または、考えられるすべてのケースでケースブロックが存在する場合は、スイッチのデフォルトのケース。
もちろん、不要なエラー処理の一部は削除できます。しかし、将来的にコーディングエラーが発生する場合、これは悪いことです。