特定の言語でユニットテストを行う方法を尋ねる質問はたくさんありましたが、「何を」、「なぜ」、「いつ」を尋ねる質問はありませんでした。
- それは何ですか?
- それは私にとって何をしますか?
- なぜ使用する必要があるのですか?
- いつ使用すべきですか(使用しない場合も)?
- いくつかの一般的な落とし穴と誤解は何ですか
特定の言語でユニットテストを行う方法を尋ねる質問はたくさんありましたが、「何を」、「なぜ」、「いつ」を尋ねる質問はありませんでした。
回答:
ユニットテストは、大まかに言えば、テストコードと分離してコードのビットをテストすることです。頭に浮かぶ直接的な利点は次のとおりです。
テストコードがファイルに書き込んだり、データベース接続を開いたり、ネットワーク経由で何かを実行したりする場合は、統合テストとしてより適切に分類されます。統合テストは良いことですが、単体テストと混同しないでください。単体テストコードは短く、簡潔で、すぐに実行できる必要があります。
単体テストのもう1つの見方は、最初にテストを記述することです。これは、テスト駆動開発(略してTDD)として知られています。TDDには追加の利点があります。
単体テストを今行っていない場合は、それから始めることをお勧めします。概念はそれらの間で非常に移行可能であるため、良い本を入手してください。実質的にすべてのxUnit-bookで十分です。
時々ユニットテストを書くのは面倒です。それがそのようになったら、あなたを助ける誰かを見つけようとしてください、そして、「いまいましいコードを書くだけ」という誘惑に抵抗してください。単体テストは皿洗いとよく似ています。いつも快適なわけではありませんが、比喩的なキッチンを清潔に保ち、清潔に保ちたいと思っています。:)
編集:1つの誤解が思い浮かびますが、それがそれほど一般的であるかどうかはわかりません。ユニットテストでチームがすべてのコードを2回記述したとプロジェクトマネージャーが言うのを聞いたことがあります。それがそのように見えて感じるなら、まあ、あなたはそれを間違っているのです。通常、テストを作成することで開発がスピードアップするだけでなく、他の方法では実現できない便利な「今は完了」のインジケーターが表示されます。
私はダンに反対しません(より良い選択は答えないだけかもしれませんが)...しかし...
ユニットテストは、システムの動作と機能をテストするコードを記述するプロセスです。
テストによってコードの品質が向上することは明らかですが、それは単体テストの表面的な利点にすぎません。実際の利点は次のとおりです。
保守可能で高品質な製品をクライアントに提供することが目的であるため、ユニットテストを行う必要があります。
実際の動作をモデル化するすべてのシステムまたはシステムの一部に使用することをお勧めします。つまり、企業の開発に特に適しています。使い捨て/ユーティリティプログラムには使用しません。テストに問題があるシステムの部分には使用しません(UIは一般的な例ですが、常にそうであるとは限りません)
最大の落とし穴は、開発者がテストするユニットが大きすぎるか、メソッドをユニットと見なしていることです。これは、制御の反転を理解していない場合に特に当てはまります。その場合、ユニットテストは常にエンドツーエンドの統合テストになります。単体テストでは、個々の動作をテストする必要があります-ほとんどのメソッドには多くの動作があります。
最大の誤解は、プログラマーがテストしてはならないということです。悪いまたは怠惰なプログラマーだけがそれを信じています。あなたの屋根を作っている人はそれをテストすべきではありませんか?心臓弁を交換する医師は新しい弁をテストすべきではありませんか?プログラマーだけが自分のコードが意図したとおりに動作することをテストできます(QAはエッジケースをテストできます-プログラマーの意図しないことをするように指示された場合のコードの動作、およびクライアントは受け入れテストを実行できます-コードは実行しますクライアントが実行するために支払ったもの)
「新しいプロジェクトを開いてこの特定のコードをテストするだけ」とは対照的に、ユニットテストの主な違いは、自動化されているため、再現性が高いことです。
コードを手動でテストすると、コードが現在の状態で完全に機能していることがわかります。しかし、1週間後、わずかな変更を加えた場合はどうでしょうか。コードに変更があった場合はいつでも、手動で再テストするつもりですか?おそらくないでしょう:-(
あなたができる場合でも、ワンクリックで、あなたのテストをいつでも実行して、まったく同じ方法では、数秒以内に、彼らはなります何かが壊れている時はいつでもすぐにあなたを示しています。ユニットテストを自動化されたビルドプロセスに統合すると、コードベースの離れた部分で一見まったく関連がないと思われる変更によって何かが壊れた場合でも、バグが発生したことが警告されます。その特定の機能を再テストする必要があります。
これが、単体テストの手動テストに対する主な利点です。しかし、待ってください、もっとあります:
単体テストフレームワークを使用すると、テストを簡単に作成して実行できます。
私は大学でユニットテストを教えたことは一度もありませんでした。私はそれについて読み、「ああ、そうですね、自動化されたテストだと思います。それは私が思うにクールかもしれません」そしてそれから私はそれを忘れていました。
ポイントを実際に理解するまでにかなり時間がかかりました。大規模なシステムで作業していて、小さなモジュールを作成するとします。それはコンパイルされ、あなたはそのペースを通してそれを置き、それは素晴らしい働きをし、あなたは次のタスクに進みます。9か月後、2バージョン後、他の誰かがプログラムの一見無関係な部分に変更を加え、モジュールを破壊します。さらに悪いことに、彼らは変更をテストし、コードは機能しますが、モジュールはテストしません。地獄、彼らはあなたのモジュールが存在することさえ知らないかもしれません。
そして今、あなたは問題を抱えています:壊れたコードがトランクにあり、誰も知りません。最良のケースは、出荷前に内部テスターがそれを見つけることですが、ゲームの後半にあるコードの修正にはコストがかかります。そして、内部テスターがそれを見つけなければ...まあ、それは確かに非常に高価になる可能性があります。
ソリューションは単体テストです。コードを書くときに問題が発生しますが、これは問題ありませんが、手動で行うこともできます。実際の見返りは、まったく別のプロジェクトに取り組んでいるときに、9か月後に問題を見つけることができるということですが、夏のインターンは、これらのパラメーターがアルファベット順になっていると見栄えがよくなると考えています。失敗した方法を書いて、パラメーターの順序を変更するまで誰かがインターンで物を投げます。これが単体テストの「理由」です。:-)
ユニットテストとTDDの哲学的な長所に少し触れてみると、TDD啓蒙への道の私の最初の最初のステップで私を驚かせたいくつかの重要な「電球」の観察があります(オリジナルまたは必ずしもニュースではありません)...
TDDは、2倍の量のコードを書くことを意味しません。テストコードは、通常、作成が非常に迅速で簡単で、設計プロセスの重要な部分であり、非常に重要です。
TDDは、コーディングを停止するタイミングを理解するのに役立ちます!あなたのテストは、あなたが今のところ十分に行ったという自信をあなたに与えて、微調整をやめて次のことに移ることができます。
テストとコードは連携して、より良いコードを実現します。あなたのコードは悪い/バグがあるかもしれません。あなたのテストは悪い/バギーかもしれません。TDDでは、両方が悪い/バギーがかなり低い可能性を利用しています。多くの場合、修正が必要なテストですが、それでも良い結果が得られます。
TDDは便秘のコーディングに役立ちます。どこから始めればよいかほとんどわからないという気持ちをご存知ですか?あと数時間先延ばしにするだけなら、金曜日の午後です。TDDを使用すると、必要なことをすばやく実行して、コーディングをすばやく進めることができます。また、実験用ネズミのように、私たちは皆、その大きな緑色の光に反応し、再びそれを見るのにもっと努力すると思います!
同様に、これらのデザイナータイプは、彼らが取り組んでいるものを見ることができます。彼らはジュース/タバコ/ iPhoneの休憩のために歩き回り、すぐに彼らがどこに着いたかについて視覚的な合図を与えるモニターに戻ることができます。TDDは私たちに似たようなものを提供します。人生が介入するときに私たちがどこに到達したかを確認するのは簡単です...
「頻繁に実行される不完全なテストは、まったく記述されていない完璧なテストよりもはるかに優れている」と言ったのはファウラーだったと思います。私はこれを、コードのカバレッジの残りの部分が途方もなく不完全であっても、テストが最も役立つと思うテストを書く許可を与えていると解釈します。
TDDは、あらゆる種類の意外な方法で将来を支援します。優れた単体テストは、何かが何をすべきかを文書化するのに役立ち、あるプロジェクトから別のプロジェクトにコードを移行するのに役立ち、テストをしていない同僚に対して不当な優越感を与えることができます:)
このプレゼンテーションは、必要なすべてのおいしいテストの優れた紹介です。
Gerard MeszarosによるxUnit Testing Patternsの本をお勧めします。大きいですが、ユニットテストに関する優れたリソースです。これは彼がユニットテストの基本を論じている彼のウェブサイトへのリンクです。 http://xunitpatterns.com/XUnitBasics.html
時間を節約するために単体テストを使用しています。
ビジネスロジック(またはデータアクセス)を構築する場合、テスト機能では多くの場合、まだ完了していない可能性がある画面に何かを入力する必要があります。これらのテストを自動化すると、時間を節約できます。
私にとってユニットテストは、モジュール化されたテストハーネスの一種です。通常、パブリック関数ごとに少なくとも1つのテストがあります。さまざまな動作をカバーする追加のテストを作成します。
コードの開発時に考えたすべての特殊なケースは、単体テストのコードに記録できます。単体テストは、コードの使用方法の例のソースにもなります。
新しいコードが単体テストで何かを壊すことを発見し、コードをチェックインして、フロントエンドの開発者に問題を発見させる方がはるかに高速です。
データアクセステストでは、変更のないテストまたは自分でクリーンアップするテストを作成しようとしています。
単体テストでは、すべてのテスト要件を解決することはできません。開発時間を節約し、アプリケーションのコア部分をテストすることができます。
これは私の見解です。単体テストとは、実際のソフトウェアが意図したとおりに機能することを確認するためのソフトウェアテストを作成することです。これは、Javaの世界ではjUnitから始まり、SimpleTestとphpUnitを使用したPHPのベストプラクティスにもなっています。これは、エクストリームプログラミングのコアプラクティスであり、編集後もソフトウェアが意図したとおりに機能することを確認するのに役立ちます。テストカバレッジが十分であれば、他の問題が発生する恐れがほとんどない状態で、主要なリファクタリング、バグ修正、または機能の追加を迅速に行うことができます。
すべての単体テストを自動的に実行できる場合に最も効果的です。
単体テストは一般にOO開発に関連しています。基本的な考え方は、コードの環境を設定してそれを実行するスクリプトを作成することです。アサーションを記述し、受信する予定の出力を指定してから、上記のようなフレームワークを使用してテストスクリプトを実行します。
フレームワークはコードに対してすべてのテストを実行し、各テストの成功または失敗を報告します。phpUnitは、デフォルトでLinuxコマンドラインから実行されますが、HTTPインターフェースを使用できます。SimpleTestは本質的にWebベースであり、IMOの起動と実行ははるかに簡単です。phpUnitは、xDebugと組み合わせて、コードカバレッジの自動統計を提供できます。
一部のチームは、変更をコミットするたびにユニットテストが自動的に実行されるように、Subversionリポジトリからフックを作成します。
単体テストをアプリケーションと同じリポジトリに保存することをお勧めします。
Kent Beckが普及したTDDアプローチを使用してプロジェクトを開発する場合、NUnit、xUnit、JUnitなどのライブラリーは必須です。
「Introduction to Test Driven Development(TDD)」またはKent Beckの著書「Test Driven Development:By Example」を読むことができます。
次に、テストがコードの「良い」部分をカバーしていることを確認したい場合は、NCover、JCover、PartCoverなどのソフトウェアを使用できます。彼らはあなたのコードのカバー率を教えてくれます。TDDの熟練度に応じて、十分に練習したかどうかがわかります。
ユニットテストとは、コードのユニットが依存するインフラストラクチャを必要とせずに、コードのユニット(たとえば、単一の関数)をテストすることです。つまり、単独でテストします。
たとえば、テストしている関数がデータベースに接続して更新を行う場合、単体テストではその更新を望まない場合があります。統合テストの場合はそうでしょうが、この場合はそうではありません。
したがって、単体テストは、データベースの更新による副作用なしに、テストしている「関数」に含まれる機能を実行します。
関数がデータベースからいくつかの数値を取得し、標準偏差の計算を実行したとします。ここで何をテストしようとしていますか?標準偏差が正しく計算されているか、またはデータがデータベースから返されているか。
単体テストでは、標準偏差が正しく計算されていることをテストしたいだけです。統合テストでは、標準偏差の計算とデータベースの取得をテストします。
ユニットテストは、アプリケーションコードをテストするコードを記述することです。
名前のUnit部分は、コードの小さなユニット(たとえば、1つのメソッド)を一度にテストする意図についてのものです。
xUnitはこのテストを支援するためにあります-それらはこれを支援するフレームワークです。その一部は、どのテストが失敗し、どのテストが合格するかを通知する自動テストランナーです。
また、事前に各テストで必要となる一般的なコードを設定し、すべてのテストが終了したらそれを破棄する機能もあります。
自分でtry catchブロック全体を記述する必要なしに、予期される例外がスローされたことを確認するテストを行うことができます。
あなたが理解していない点は、NUnit(など)のようなユニットテストフレームワークが 小規模から中規模のテストの自動化に。通常は、ボタンをクリックするだけでGUIでテストを実行できます(たとえば、NUnitの場合)。次に、できれば、進行状況バーが緑色のままになることを確認してください。赤くなった場合、フレームワークは、失敗したテストと正確に何が失敗したかを示します。通常の単体テストでは、アサーションを使用することがよくあります。たとえばAssert.AreEqual(expectedValue, actualValue, "some description")
、2つの値が等しくない場合、「一部の説明:予期された<expectedValue>でしたが、<actualValue>でした」というエラーが表示されます。
したがって、結論として、単体テストはテストをより速く、開発者にとってより快適にします。新しいコードをコミットする前にすべての単体テストを実行して、同じプロジェクトの他の開発者のビルドプロセスを中断しないようにすることができます。
テスト駆動開発は、ユニットテストという用語をある程度継承したものです。古いタイマーとして、より一般的な定義について触れます。
ユニットテストは、大規模なシステムで単一のコンポーネントをテストすることも意味します。この単一のコンポーネントは、dll、exe、クラスライブラリなどである可能性があります。マルチシステムアプリケーションの単一のシステムである可能性もあります。したがって、最終的には単体テストは、より大きなシステムの単一の部分を呼び出したいもののテストになります。
次に、すべてのコンポーネントがどのように連携するかをテストすることにより、統合テストまたはシステムテストに進みます。
FoxForward 2007でユニットテストに関するプレゼンテーションに行ったところ、データで機能するものはユニットテストしないように言われました。結局のところ、ライブデータでテストすると結果は予測できません。また、ライブデータでテストしなければ、実際に作成したコードをテストしているわけではありません。残念ながら、それは私が最近行っているコーディングのほとんどです。:-)
設定を保存して復元するルーチンを書いているときに、最近TDDで写真を撮りました。まず、ストレージオブジェクトを作成できることを確認しました。次に、呼び出す必要のあるメソッドが含まれていること。そして、それを私はそれと呼ぶことができた。次に、パラメーターを渡すことができます。次に、特定のパラメーターを渡すことができます。など、いくつかの異なる構文について、指定した設定が保存されることを最終的に確認するまで、それを変更してから復元できるようにしました。
いまは当たり前のことなので、最後までたどり着けませんでしたが、良い練習でした。
がらくたの山を与えられ、クリーンアップの永続的な状態で立ち往生しているように見える場合、新しい機能やコードを追加すると、現在のソフトウェアが家のようなものであるため、現在のセットが壊れることがあります。カード?
では、どうすれば単体テストを実行できますか?
あなたは小さく始めます。私がたった今行ったプロジェクトには、数か月前までユニットテストがありませんでした。カバレッジが低い場合は、カバレッジのないファイルを選択して[テストを追加]をクリックします。
現在、私たちは最大40%を超えており、ほとんどぶら下がっていない果物を選ぶことができました。
(最高の部分は、この低レベルのカバレッジでさえ、すでにコードの多くのインスタンスが間違ったことを実行していて、テストがそれを捕らえたことです。それは人々にさらにテストを追加するように促す大きな動機です。)
これは、なぜユニットテストを実行する必要があるかを示しています。
以下の3つのビデオはJavaScriptでの単体テストをカバーしていますが、一般原則はほとんどの言語に適用されます。
ユニットテスト:数分で時間を節約-エリックマン-https://www.youtube.com/watch?v = _UmmaPe8Bzc
JSユニットテスト(非常に良い)-https://www.youtube.com/watch?v = -IYqgx8JxlU
テスト可能なJavaScriptの記述-https ://www.youtube.com/watch?v= OzjogCFO4Zo
今、私は単に主題について学んでいるだけなので、100%正確ではないかもしれませんが、ここで説明している以上のことはありますが、ユニットテストの基本的な理解は、いくつかのテストコードを書くことです(これは、メインコード)は、関数が必要とする入力(引数)を使用してメインコード内の関数を呼び出し、コードは有効な戻り値を取得するかどうかを確認します。有効な値が返された場合、テストの実行に使用しているユニットテストフレームワークは緑色のライト(すべて良好)を示します。値が無効な場合、赤色のライトが表示され、すぐに問題を修正できます。新しいコードを本番環境にリリースします。テストしないと、実際にはエラーをキャッチできなかった可能性があります。
したがって、現在のコードのテストを記述し、テストに合格するようにコードを作成します。1か月後、メインコードの関数を変更する必要があります。以前にその関数のテストコードを既に作成していたため、今度は再度実行し、コーダーが関数に論理エラーを導入したか、または何かを完全に返したためにテストが失敗する可能性があります。その関数が返すはずのものとは異なります。ここでもテストを実施しないと、そのエラーは他のコードにも影響を及ぼし、気付かれない可能性があるため、追跡が困難になる可能性があります。
また、ブラウザーのページごとに手動で実行する代わりに、コードを実行してテストするコンピュータープログラムがあるという事実により、時間を節約できます(JavaScriptの単体テスト)。Webページのスクリプトで使用される関数を変更すると、その関数はすべて、新しい意図された目的に適切に機能します。ただし、引数として、適切に動作するために新しく変更された関数に依存するコードの別の場所に別の関数があるとしましょう。この依存関数は、最初の関数に加えた変更のために機能を停止する可能性があります。ただし、コンピューターによって自動的に実行されるテストが実施されていない場合、実際に実行されるまで、その関数に問題があることに気付かないでしょう。君は'
繰り返しになりますが、アプリケーションの開発中にテストを実行すると、コーディング中にこの種の問題が発生します。テストが実施されていない場合、アプリケーション全体を手動で実行する必要があり、それでもバグを見つけるのは難しい場合があります。単純に、それを本番環境に送信し、しばらくして親切なユーザーがバグレポートを送信します(これはテストフレームワークのエラーメッセージほどよくありません)。
この件名を最初に聞いて自分で考えたとき、私はまだ混乱しています。まだコードをテストしていないのですか?そして、あなたが書いたコードは、「なぜ別のフレームワークが必要なのですか?」という想定どおりに機能しています...はい、すでにコードをテストしていますが、コンピューターの方が優れています。関数/コードのユニットに対して十分なテストを1回書くだけで、残りの部分は強力なCPUによって処理されます。あなたのコード。
また、必要がない場合はコードを単体テストする必要はありませんが、バグが発生する可能性が高まるにつれてプロジェクト/コードベースが大きくなり始めるため、効果があります。