Java Language
ユニットテスト
サーチ…
前書き
備考
ユニットテストフレームワーク
Java内での単体テストには、多数のフレームワークが用意されています。これまでに最も人気のあるオプションはJUnitです。それは以下の文書に記載されています:
JUnit4 - JUnit4の機能のための提案されたタグ。まだ実装されていません 。
他の単体テスト・フレームワークも存在し、使用可能なドキュメントがあります。
ユニットテストツール
ユニットテストには他にもいくつかのツールがあります:
Mockito - Mockingフレームワーク。オブジェクトを模倣することができます。所与のユニットの試験を外部装置の動作をリンクしないように、所定の単位のテスト内の外部装置の正常な動作を模倣するために有用。
JBehave - BDDフレームワークテストをユーザーのビヘイビアにリンクすることができます(要件/シナリオの検証が可能)。 書面の時点で利用可能な書類はありません。 ここに外部リンクがあります。
ユニットテストとは何ですか?
これは少しのプライマです。スタブの記事として意図されていても、ドキュメンテーションには例があるため、ほとんどの場合それが入ります。ユニットテストの基礎をすでに知っている場合は、具体的なフレームワークが記述されている発言を読み飛ばしてください。
ユニットテストは、特定のモジュールが期待どおりに動作することを保証することです。大規模アプリケーションでは、真空中でのモジュールの適切な実行を保証することは、アプリケーションの忠実性を保証するための不可欠な要素です。
以下の(些細な)疑似例を考えてみましょう。
public class Example {
public static void main (String args[]) {
new Example();
}
// Application-level test.
public Example() {
Consumer c = new Consumer();
System.out.println("VALUE = " + c.getVal());
}
// Your Module.
class Consumer {
private Capitalizer c;
public Consumer() {
c = new Capitalizer();
}
public String getVal() {
return c.getVal();
}
}
// Another team's module.
class Capitalizer {
private DataReader dr;
public Capitalizer() {
dr = new DataReader();
}
public String getVal() {
return dr.readVal().toUpperCase();
}
}
// Another team's module.
class DataReader {
public String readVal() {
// Refers to a file somewhere in your application deployment, or
// perhaps retrieved over a deployment-specific network.
File f;
String s = "data";
// ... Read data from f into s ...
return s;
}
}
}
したがって、この例は簡単です。 DataReader
はファイルからデータを取得してCapitalizer
渡し、すべての文字を大文字に変換してからConsumer
渡します。しかし、 DataReader
はアプリケーション環境に大きく依存しているため、テストリリースを展開する準備が整うまで、このチェーンのテストを延期します。
さて、どこかのリリースでは、道に沿って、想定し、未知の理由のために、 getVal()
内のメソッドCapitalizer
戻ってから変更toUpperCase()
に文字列をtoLowerCase()
文字列:
// Another team's module.
class Capitalizer {
...
public String getVal() {
return dr.readVal().toLowerCase();
}
}
明らかに、これは予想される動作を破ります。しかし、 DataReader
実行に伴う困難なプロセスのため、次のテスト展開までは気付かないでしょう。だから、このバグがシステムにあって日/週/月が過ぎると、プロダクトマネージャーがこれを見て、 Consumer
関連付けられたチームリーダーにあなたを向かわせます。 "なぜこれが起こっているのですか?あなたは何を変えましたか?"明らかに、あなたは無知です。あなたは何が起こっているのか分かりません。あなたはこれに触れるべきコードを変更しなかった。どうして突然壊れたの?
結局のところ、チームとコラボレーションの議論の後、問題が追跡され、問題が解決されます。しかし、それは疑問を抱く。どのようにこれを防ぐことができましたか?
明らかに2つのことがあります。
テストを自動化する必要がある
手作業によるテストに依存しているため、このバグはあまりにも長く気付かれませんでした。バグが即座に導入されるプロセスを自動化する方法が必要です。今から5週間ではありません。今から5日ではありません。今から5分ではありません。たった今。
この例では、導入され、気付かれていない非常に簡単なバグを1つ表現していることを理解しておく必要があります。工業用アプリケーションでは、数十のモジュールが絶えず更新されているため、これらのモジュールはいたるところで忍び寄る可能性があります。 1つのモジュールで何かを修正するだけで、あなたが "固定"された振る舞いが何らかの形で(内部的にも外部的にも)信頼されていることを認識することができます。
厳格な検証がなければ、システムに忍び込むことになります。これが十分に無視されれば、変更を修正して(そして修正を修正するなど)余計な作業が必要になる可能性があり、努力が加わるにつれて製品が実際に残りの作業で増加する可能性があります。このような状況に陥ることは望ましくありません。
テストはきめ細かく行う必要があります
上の例で指摘した2番目の問題は、バグを追跡するのにかかった時間です。テスターがそれを気づいたときにプロダクトマネージャーがpingし、あなたが調査して、 Capitalizer
が一見悪いデータを戻していたことを知り、あなたの調査結果をCapitalizer
チームにpingし、調査しました。
この簡単な例の量と難しさについて私が上で作ったのと同じ点がここにあります。明らかに、Javaに合理的であれば誰でも、導入された問題をすばやく見つけることができます。しかし、多くの場合、問題を追跡して伝達することはずっと困難です。たぶん、 Capitalizer
チームがあなたにソースのないJARを提供してくれたかもしれません。おそらく彼らは世界の反対側に位置しており、通信時間は非常に限られています(たぶん1日に1回送信される電子メール)。追跡に数週間かかってしまうバグが発生する可能性があります(また、あるリリースではいくつかのバグがあります)。
これを軽減するために、可能な限り緻密なテストを厳密に行いたいと考えています(モジュールが適切に相互作用することを保証するための粗いテストも必要ですが、ここではそれが重要ではありません)。外向きのすべての機能(最低限)がどのように動作するかを厳密に指定し、その機能をテストする必要があります。
単体テストに入る
我々は特にことを保証し、テストを持っていた場合を想像しgetVal()
のメソッドCapitalizer
指定された入力文字列の大文字の文字列を返しました。さらに、コードをコミットする前にテストが実行されたとします。システムに導入されたバグ(つまり、 toUpperCase()
に置き換えられてtoLowerCase()
のバグがシステムに導入されることはありませんになるため)何も問題を起こさないだろう。私たちはそれをテストで捉え、開発者は間違いを認識し、意図した効果をどのように導入するかについての別の解決策が得られるでしょう。
これらのテストの実装方法についてはここではいくつかの抜けがありますが、フレームワーク固有のドキュメント(注釈にリンクされています)に記載されています。うまくいけば、これは単体テストがなぜ重要なのかの例として役立ちます。