テストにJUnitを使用する理由


131

たぶん私の質問は初心者のものですが、私が使用する状況を本当に理解できません

単純なアプリケーションを作成する場合でも、大きなアプリケーションを作成する場合でも、System.outステートメントを使用してテストします。

JUnitを使用してテストクラスを作成する必要があります。同じメソッドを呼び出す必要がある場合、プロジェクトに不要なフォルダーを作成し、それらが返すものを確認すると、すべてに注釈を付けるオーバーヘッドが発生します。

クラスをSystem.out作成して一度にテストしますが、Testクラスを作成しないのはなぜですか?

PS。私は今学んでいる大きなプロジェクトに取り組んだことがありません。

それで、目的は何ですか?



7
プログラムで何かを変更するたびに、出力を手動で調べる以前のすべての作業が無効になり、最初からやり直す必要があることを知っていますか?
–ThorbjørnRavn Andersen 2013

「テスト」だけでなく「巧妙なテスト」も非常に重要です。以下にその良い例を示します。wp.me
11

回答:


139

これはテストではなく、「出力を手動で見る」ことです(このビジネスではLMAOとして知られています)。より正式には、「異常な出力を手動で探す」(LMFAO)として知られています。(下記の注を参照)

コードを変更するときはいつでも、それらの変更の影響を受けるすべてのコードに対してアプリとLMFAOを実行する必要があります。小さなプロジェクトでも、これは問題が多く、エラーが発生しやすくなります。

コードを変更するたびに、50k、250k、1m LOC以上、およびLMFAOにスケールアップします。不愉快なだけでなく、不可能です。入力、出力、フラグ、条件の組み合わせをスケールアップしており、すべての可能なブランチを実行することは困難です。

さらに悪いことに、LMFAOは、Webアプリのページにアクセスする、レポートを実行する、数十のファイルやマシンにまたがる何百万ものログ行を調べる、生成および配信された電子メールを読み取る、テキストメッセージをチェックする、ロボットのパスをチェックする、ボトルに詰めるソーダ、100のWebサービスからのデータの集計、金融取引の監査証跡の確認...アイデアがわかります。「出力」は数行のテキストを意味するのではなく、「出力」はシステム全体の動作を意味します。

最後に、単体テストと動作テストシステムの動作を定義します。テストは継続的インテグレーションサーバーで実行でき、正確性をチェックできます。もちろん、そうすることもできSystem.outますが、CIサーバーは、そのうちの1つが間違っているかどうかを知ることはありません。間違っている場合は、単体テストであり、フレームワークを使用することもできます。

私たちがどれほど優れていても、人間は優れた単体テストフレームワークやCIサーバーではありません。


注:LMAO テスト中ですが、非常に限られた意味でです。プロジェクト全体またはプロセスの一部として意味のある方法で繰り返すことはできません。REPLで段階的に開発することと似ていますが、これらの段階的なテストを形式化することはありません。


3
最初の文は-1で、これは完全かつ完全に真実ではありません。
Michael Borgwardt 2012

50

プログラムの動作が正しいかどうかを検証するためのテストを作成します。

で出力ステートメントの内容を調べて、プログラムの動作が正しいかどうかを確認するのは、手作業、つまり視覚的なプロセスです。

あなたはそれを主張することができます

目視検査が機能し、コードが意図したとおりに機能することを確認します。これらのシナリオでは、コードが正しいことを確認したら、問題ありません。

まず最初に、コードが正しく機能するかどうかに興味があるのは素晴らしいことです。それはいい。あなたは時代遅れです!悲しいことに、これにはアプローチとしての問題があります。

目視検査の最初の問題は、コードの正しさを再度確認することができなくなることから、溶接不良です。

第2の問題は、使用される一対の目が、目の所有者の脳と密接に結合していることです。コードの作成者が目視検査プロセスで使用される目も所有している場合、正当性を検証するプロセスは、目視検査官の脳に内在化されたプログラムに関する知識に依存します。

元のコーダーの頭脳と提携していないというだけの理由で、新しい目が入り、コードの正当性を検証することは困難です。目のペアの所有者は、問題のコードを完全に理解するために、コードの原作者と会話する必要があります。知識を共有する手段としての会話は、信頼できないことで有名です。元のコーダーが新しいペアの目で利用できない場合、問題になるポイント。その場合、新しい目は元のコードを読み取る必要があります。

ユニットテストでカバーされていない他の人のコードを読み取ることは、ユニットテストに関連付けられているコードを読み取るよりも困難です。他の人のコードを読むことはせいぜい扱いにくい作業ですが、最悪の場合、これはソフトウェアエンジニアリングで最も困難な作業です。雇用者が求人を宣伝するときに、プロジェクトがグリーンフィールド(またはまったく新しい)プロジェクトであることを強調するのには理由があります。コードを最初から作成することは、既存のコードを変更するよりも簡単であるため、宣伝された仕事が潜在的な従業員にとって魅力的に見えるようになります。

単体テストでは、コードをコンポーネントに分割します。次に、コンポーネントごとに、プログラムの動作を示すストールを設定します。各単体テストは、プログラムのその部分が特定のシナリオでどのように動作するかを物語っています。各単体テストは、クライアントコードの観点から何が起こるかを説明するコントラクトの句のようなものです。

これは、新しい目が問題のコードに関するライブで正確なドキュメントの2つのストランドを持っていることを意味します。

まず、コード自体、実装、コードの実行方法があります。次に、元のコーダーが一連の正式なステートメントで記述した、このコードどのように動作するかのストーリーを伝えるすべての知識があります。

ユニットテストは、元の作者がクラスを実装したときに持っていた知識を取り込み、正式に記述します。それらは、クライアントが使用したときのそのクラスの動作の説明を提供します。

役に立たないユニットテストを記述したり、問題のコードのすべてをカバーしたり、古くなったり、古くなったりする可能性があるため、これを行うことの有用性に疑問を投げかけるのは正しいことです。単体テストが模倣するだけでなく、知識のある良心的な作成者が実行時にコードの出力ステートメントを視覚的に検査するプロセスを改善することをどのように保証しますか?最初に単体テストを記述してから、そのテストに合格するためのコードを記述します。終了したら、コンピューターにテストを実行させます。テストは高速で、繰り返しのタスクを実行するのに優れており、ジョブに最適です。

テストするコードを削除するたびにレビューを行い、ビルドごとにテストを実行して、テストの品質を確認します。テストが失敗した場合は、すぐに修正してください。

テストの実行プロセスを自動化して、プロジェクトのビルドを実行するたびにテストが実行されるようにします。また、テストによってカバーされ、実行されるコードのパーセンテージの詳細を示すコードカバレッジレポートの生成を自動化します。私たちは高いパーセンテージを目指して努力しています。一部の企業では、コードの動作の変更を説明するための十分な単体テストが記述されていない場合、コードの変更がソースコード管理にチェックインされないようにします。通常、2番目のペアは、変更の作成者と共にコードの変更を確認します。レビューアは変更を検討し、変更が理解可能でテストによって十分にカバーされていることを確認します。したがって、レビュープロセスは手動です。ただし、テスト(単体テストと統合テスト、および場合によってはユーザー受け入れテスト)がこの手動レビュープロセスに合格すると、自動ビルドプロセスの一部になります。これらは、変更がチェックインされるたびに実行されます。A サーバーは、ビルドプロセスの一部としてこのタスクを実行します。

自動的に実行されるテストは、コードの動作の整合性を維持し、コードベースへの将来の変更によるコードの破壊防ぐのに役立ちます

最後に、テストを提供することで、コードを積極的にリファクタリングすることができます。これは、変更によって既存のテストに影響が及ばないという知識で、大きなコードの改善を安全に行えるためです。

テスト駆動開発には注意が必要です。つまり、テスト可能にするためにコードを記述する必要があります。これには、インターフェイスへのコーディングと、依存性注入などの手法を使用して、協調オブジェクトをインスタンス化することが含まれます。TDDを非常によく説明しているKent Beckの仕事をチェックしてください。見上げインターフェイスにコーディングし、研究


13

System.outのようなものを使用してテストする場合、考えられるユースケースのごく一部をテストするだけです。これは、ほぼ無限の量の異なる入力を受け入れる可能性のあるシステムを扱っている場合、完全ではありません。

単体テストは、さまざまなデータ入力の非常に大規模で多様なセットを使用して、アプリケーションでテストをすばやく実行できるように設計されています。さらに、最良の単体テストは、有効と見なされるものの端にあるデータ入力などの境界ケースも考慮します。

人間がこれらのさまざまな入力をすべてテストするには数週間かかる場合がありますが、マシンでは数分かかる場合があります。

次のように考えてください。静的なものを "テスト"していません。ほとんどの場合、アプリケーションは常に変更されています。したがって、これらの単体テストは、コンパイルまたは展開サイクルのさまざまな時点で実行されるように設計されています。おそらく最大の利点はこれです:

コードで何かを壊したとしても、それがデプロイされた後ではなく、QAテスターがバグをキャッチしたときではなく、クライアントがキャンセルされたときではなく、そのことをすぐに知ることができます。問題のコードの一部を壊したことが最後のコンパイル以降に発生した可能性が高いことが明らかであるため、グリッチをすぐに修正できる可能性も高くなります。したがって、問題を修正するために必要な調査作業の量が大幅に削減されます。


9

私は他のいくつかのSystem.outができないことを追加しました:

  • 各テストケースを独立させる(重要です)

    JUnitはそれを実行できます。新しいテストケースインスタンスが作成されて@Before呼び出されるたびに。

  • ソースからテストコードを分離する

    JUnitはそれを行うことができます。

  • CIとの統合

    JUnitはAntとMavenでそれを行うことができます。

  • テストケースを簡単に配置して組み合わせる

    JUnitは@Ignoreスイートをテストできます。

  • 結果を確認しやすい

    JUnitは多くのAssertメソッド(assertEqualsassertSame...)を提供します

  • モックとスタブを使用すると、テストモジュールに集中できます。

    JUnitでできること:モックとスタブを使用すると、正しいフィクスチャーをセットアップし、テストモジュールのロジックに集中できます。


9

単体テストは、コードが意図したとおりに機能することを確認します。また、バグを修正するために新しい機能を構築するために後で変更する必要がある場合に備えて、コードが意図したとおりに機能することを確認するのにも非常に役立ちます。コードのテストカバレッジが高いと、多くの手動テストを実行しなくても、機能の開発を継続できます。

手動によるアプローチSystem.outは良いですが、最善ではありません。これは、実行する1回限りのテストです。現実の世界では、要件は変化し続けており、ほとんどの場合、既存の関数やクラスに多くの変更を加えます。つまり、すでに記述されたコードをテストするたびにではありません。

のようなJUnitにはいくつかのより高度な機能もあります

ステートメントをアサートする

JUnitは特定の条件をテストするメソッドを提供します。これらのメソッドは通常、アサートで始まり、エラーメッセージ、予想される結果、および実際の結果を指定できます

これらのメソッドのいくつかは

  1. fail([message])-テストを失敗させます。コードの特定の部分に到達していないことを確認するために使用される場合があります。または、テストコードが実装される前にテストに失敗する。
  2. assertTrue(true)/ assertTrue(false)-常にtrue / falseになります。テストがまだ実装されていない場合、テスト結果を事前定義するために使用できます。
  3. assertTrue([message,] condition)-ブール値conditionが真であることを確認します。
  4. assertEquals([message,] expected, actual)-2つの値が等しいかどうかをテストします(equals実装されている場合はメソッドに従い、そうでない場合は==参照比較を使用します)。注:配列の場合、チェックされるのは参照であり、内容ではありませんassertArrayEquals([message,] expected, actual)。そのために使用します。
  5. assertEquals([message,] expected, actual, delta)-2つのfloat値またはdouble値が相互に特定の距離にあり、delta値によって制御されるかどうかをテストします。
  6. assertNull([message,] object) -オブジェクトがnullであることを確認します

等々。ここにあるすべての例については、完全なJavadocを参照してください。

スイート

テストスイートを使用すると、ある意味で複数のテストクラスを1つのユニットに結合して、一度にすべてを実行できます。テストクラスMyClassTestを組み合わせて、次のMySecondClassTest名前の1つのスイートに結合する簡単な例AllTests

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ MyClassTest.class, MySecondClassTest.class })
public class AllTests { } 

6

JUnitの主な利点は、出力を手動で確認する必要がなく、自動化されていることです。あなたが書く各テストはあなたのシステムに残ります。これは、予期しない副作用のある変更を行った場合、変更ごとに手動ですべてをテストすることを覚えておかなくても、テストがそれをキャッチして失敗することを意味します。


4

JUnitは、Javaプログラミング言語の単体テストフレームワークです。これはテスト駆動開発で重要であり、xUnitと総称されるユニットテストフレームワークのファミリーの1つです。

JUnitは、「最初にテストしてからコーディングする」という考え方を推進しています。これは、最初にテストしてから実装できるコードのテストデータを設定することに重点を置いています。このアプローチは、「少しテスト、少しコード、少しテスト、少しコード...」のようなもので、プログラマの生産性とプログラムコードの安定性を高め、プログラマのストレスとデバッグに費やす時間を削減します。

機能JUnitは、テストの作成と実行に使用されるオープンソースフレームワークです。

テストメソッドを識別するための注釈を提供します。

期待される結果をテストするためのアサーションを提供します。

テストを実行するためのテストランナーを提供します。

JUnitテストにより、コードをより速く記述でき、品質が向上します

JUnitはエレガントでシンプルです。複雑さが軽減され、時間がかかりません。

JUnitテストは自動的に実行でき、独自の結果をチェックして即座にフィードバックを提供します。テスト結果のレポートを手作業で調べる必要はありません。

JUnitテストは、テストケースを含むテストスイート、さらには他のテストスイートに編成できます。

JUnitは、テストが正常に進行している場合は緑色のバーにテストの進行状況を示し、テストが失敗した場合は赤色に変わります。


2

なぜJUnitが必要なのかについて、少し異なる見方があります。

実際にすべてのテストケースを作成できますが、面倒です。ここに問題があります:

  1. 代わりに、0または-1またはエラーメッセージをSystem.out追加if(value1.equals(value2))して返すことができます。この場合、これらすべてのメソッドを実行して結果をチェックし、失敗したテストケースと合格したテストケースを維持する「メイン」テストクラスが必要です。

  2. さらにテストを追加したい場合は、それらをこの「メイン」テストクラスにも追加する必要があります。既存のコードへの変更。テストクラスからテストケースを自動検出する場合は、リフレクションを使用する必要があります。

  3. すべてのテストとテストを実行するためのメインクラスはEclipseによって検出されないため、これらのテストを実行するには、カスタムのデバッグ/実行構成を作成する必要があります。ただし、これらのきれいな緑/赤の出力はまだ表示されません。

JUnitが行っていることは次のとおりです。

  1. これにはassertXXX()、状態から役立つエラーメッセージを出力し、「メイン」クラスに結果を伝えるのに役立つメソッドがあります。

  2. 「メイン」クラスはランナーと呼ばれ、JUnitによって提供されるため、何も記述する必要はありません。そしてそれは反射によって自動的にテスト方法を検出します。@Testアノテーション付きの新しいテストを追加すると、それらは自動的に検出されます。

  3. JUnitはEclipse統合とmaven / gradle統合も備えているため、テストを簡単に実行でき、カスタム実行構成を作成する必要はありません。

私はJUnitの専門家ではないので、現時点で理解していることは、今後さらに追加される予定です。


最初の部分では、ユニットテストをsystem.out.printlnステートメントよりも少し良くするためにJUnitがなかった場合に何をしたかを書いたと思います。たぶん、JUnitは一部のプログラマーによるそのような試みの結果であり、この自動化を実行するために別のテストフレームワークを作成する必要性を感じたため、JUnitが生まれたのかもしれません。
Saurabh Patil 2016

1

テストフレームワークを使用せずにテストケースを作成することはできません。そうしないと、テストフレームワークを作成して、テストケースに正義を与える必要があります。TestNGフレームワークを使用できることを除いて、JUnitフレームワークに関するいくつかの情報を次に示します。

ジュニットとは?

JUnitは、Javaプログラミング言語とともに広く使用されているテストフレームワークです。この自動化フレームワークは、単体テストとUIテストの両方に使用できます。さまざまなアノテーションを使用してコードの実行フローを定義するのに役立ちます。Junitは、「最初にテストしてからコーディングする」という考えに基づいて構築されており、テストケースの生産性とコードの安定性を向上させるのに役立ちます。

JUnitテストの重要な機能-

  1. これは、ユーザーがテストケースを効率的に記述して実行できるようにするオープンソースのテストフレームワークです。
  2. テスト方法を識別するためのさまざまなタイプの注釈を提供します。
  3. テストケースの実行結果を検証するためのさまざまなタイプのアサーションを提供します。
  4. また、テストを効果的に実行するためのテストランナーも提供します。
  5. 非常にシンプルなので、時間を節約できます。
  6. テストスーツの形式でテストケースを整理する方法を提供します。
  7. シンプルでエレガントな方法でテストケースの結果を提供します。
  8. jUnitをEclipse、Android Studio、Maven&Ant、Gradle、Jenkinsと統合できます

0

JUNITは、Java開発者が通常受け入れる方法です。期待される同様の入力を関数に提供し、それに応じて、記述されたコードが完全に記述されているか、テストケースが失敗した場合は、別のアプローチを実装する必要があるかもしれません。JUNITは開発を迅速化し、機能の欠陥をゼロにします。


0

JUNIT:観察と調整

これがJUNITの私の見方です。

JUNITを使用すると、
1)システムに新しいユニットが追加されたときのシステムの動作を観察できます。
2)システムの「新しい」ユニットを受け入れるようにシステムを調整します。
何?丁度。

実生活

親族が大学のホステルの部屋を訪問するとき、
1)あなたはもっと責任があるふりをします。
2)椅子の上ではなく靴の棚にある靴、椅子の上ではない戸棚の服のように、必要なすべてのものを保管します。
3)すべての密輸品を取り除きます。
4)所有するすべてのデバイスでクリーンアップを開始します。

プログラミング用語で

システム:コード
UNIT:新機能。
JUNITフレームワークはJAVA言語で使用されるため、JUNIT = JAVA UNIT(多分)です。

十分な防弾コードがすでにあるが、新しい要件が発生し、コードに新しい要件を追加する必要があるとします。この新しい要件により、一部の入力(テストケース)のコードが壊れる可能性があります。

この変更を適用する簡単な方法は、ユニットテスト(JUNIT)を使用することです。
そのためには、コードベースを構築するときに、コードに対して複数のテストケースを作成する必要があります。また、新しい要件が発生した場合は、すべてのテストケースを実行して、失敗したテストケースがないかどうかを確認するだけです。いいえの場合、あなたはBadA **アーティストであり、新しいコードをデプロイする準備ができています。
テストケースのいずれかが失敗した場合は、コードを変更し、緑のステータスになるまでテストケースを繰り返し実行します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.