今回は、JUnitテストのセットアップ、作成、実行方法に関する簡単なJUnitチュートリアルを使用して、ユニットテストの基本をおさらいします。
JUnitとは何か、また、どうやって始めればよいのでしょうか?基本を理解し、ユニットテスト の利用をさらに拡大しましょう。
ユニットテストとは
いきなりJUnitに入るのではなく、まずユニットテストと回帰テストのおさらいと、それらがなぜ重要であるかについて押さえておきましょう。その過程でいくつかのサンプルを見ていきます。
ユニットテストはホワイトボックステストの一種であり、テストケースは内部構造に基づいて作成されます。テスターは特定のパスを通るための入力を選択し、適切な出力を決定します。ユニットテストの目的は、個々のコンポーネントやメソッド/クラスを調べて機能を検証し、動作が期待どおりであることを確認することです。
「ユニット」の範囲については解釈が分かれますが、原則としては、独立したタスクを実行する最小限のコードを含むユニットです(単一のメソッドやクラスなど)。ユニットテストで範囲を制限するのにはもっともな理由があります --プロジェクトのさまざまな側面を組み込んだテストを構築すると、単一のメソッドの機能からコードの複数の部分の相互作用にフォーカスがずれてしまいます。テストが失敗した場合、なぜそれが失敗したのか分からず、失敗のポイントがテスト対象のメソッドの中にあったのか、それともそのメソッドに関連した依存関係にあったのか、判断に悩むことになります。
回帰テスト
ユニットテストを補完するために、回帰テストでは、コードに加えた変更をテストすることで、最新の修正、拡張、またはパッチが既存の機能を壊していないことを確認します。既存のコードを変更したり、新しい機能のパッケージを追加したりするなど、コードの変更は避けられません。コードは確実に変更されます。この変更の中に最大の危険があります。それを考えると、回帰テストは必須です。
JUnitとは
JUnitは、Javaプログラミング言語向けのユニットテストフレームワークであり、回帰テストで大きな役割を果たします。オープンソースのフレームワークで、繰り返し可能な自動テストの作成と実行に使用されます。
どんなものにも言えますが、JUnitフレームワークは時とともに発展してきました。注目すべき大きな変更は、JUnit 4のリリース時にアノテーションが導入されたことです。これによってJUnitの構成と可読性が向上しました。この記事の残りの部分は、Junit 4および5の使用法に基づいて書かれています。
JUnitのセットアップ
では実践に移りましょう。
EclipseやIntelliJなどの一般的なIDEでは、デフォルトでJUnit機能がインストールされています。IDEを使用せず、MavenやGradleなどのビルドシステムのみを使用している場合、Junit 4/5のインストールはそれぞれpom.xmlまたはbuild.gradleによって処理されます。Junit 5は3つのモジュールに分割されていますが、そのうちの1つは、Junit 4および3のアノテーション/構文をサポートする由緒あるモジュールです(ただし、Junit 3の使用は率直に言って悲惨であり、通常、かなり古いプロジェクトでしか見られません)。
JUnit 4
JUnit 4をMavenに追加するには、pom.xmlに以下を追加します。バージョンに注意してください。
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
Gradleの場合は、build.gradleに次の行を追加します。
apply plugin: 'java'
dependencies {
testCompile 'junit:junit:4.12'
}
JUnit 5
JUnit 5の追加は少し異なります。JUnit 5はモジュラー形式であるため、BOMを使用してすべてをインポートします。特定のクラスだけが必要な場合は、個々のグループまたは成果物を指定できます。
JUnit 5をMavenに追加するには、pom.xmlに次の行を追加します。
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
Gradleの場合は、build.gradleに次の行を追加します。
apply plugin: 'java'
dependencies {
implementation 'org.junit:junit-bom:5.2.0'
}
通常は必要ではありませんが、手動でクラスパスを設定する必要がある場合など、JUnitフレームワークを使用できるようにする jarファイルもあります。GitにはJUnitのコードがあります。JUnit 4には、直接ダウンロードできるjarファイルがあります。Junit 5には、(私がこれを書いている)現時点で、既成のjarファイルはありませんが、簡単にコードをコンパイルしてjarファイルを生成できます。
ユニットテストの作成:JUnitの仕組み
ここまででユニットテストおよびセットアップについて簡単な説明が終わりましたので、次に実際のテストの構築と実行に移りましょう。JUnitの作成を分かりやすく説明するために、基本的なサンプルから始めたいと思います。以下のサンプル画像は、華氏(°F)を摂氏(℃)に変換する簡単なメソッド( 左 )と、メソッドに関連するJUnit( 右 )を示しています。JUnitには番号が付いています。これらのセクションについて以下で詳しく説明します。
セクション1とセクション2
これらは、テストフレームワークを利用するために必要なJUnitライブラリのインポートです。インポート対象のライブラリは、JUnitの特定の機能まで細かく指定することもできますが、通常、すべての機能にアクセスできるようアスタリスクでインポートします。
セクション3
ここからテストクラスが始まりますが、ここで注意すべき重要な点は、クラス名+Testというテストクラスの命名規則です。
セクション4
ここで初めてJUnit固有の構文であるアノテーションが出てきます。アノテーションはJUnitを作成する際に非常に重要です。JUnitは、アノテーションに従って、コードの処理セクションで何をすべきかを判断します。この例では、@Testアノテーションがあります。@Testアノテーションは、アノテーションが付加されているpublic voidメソッドがテストケースとして実行できることをJUnitに通知します。
他にも多くのアノテーションがありますが、よく使われるのは @Before(@Testの前に何らかのステートメント/前提条件を実行します。public void)、@After(@Testの後に何らかのステートメント、たとえば一時変数の削除や変数の削除などを実行します。public void)、@Ignore (テスト実行時に一部のステートメントを無視します。@BeforeClassと@AfterClassは、すべてのテストケースの前と後にステートメントを実行するために使用されることに注意してください。public static void)などです。
セクション5
ここで注目すべきことは、やはり命名規則です。test+メソッド名という構造になることに注意してください。
セクション6
ここでは、クラスオブジェクトの新しいインスタンスを作成します。これはテスト対象メソッドを呼び出すために必要です。このオブジェクトインスタンスがなければ、メソッドをテストすることはできません。
セクション7
メソッドに関連する変数を設定する必要があるので、ここでメソッドに対応する変数を宣言します。テストが意味を持つよう、これらの変数には意味のある値が与えられるべきです(パラメーターがオブジェクトである場合、オブジェクトをインスタンス化するか、モック化することができます)。
セクション8
この変数宣言はオプションであると言えるかもしれませんが、コーディング規約とコードの可読性という点で、記述する価値があります。テスト対象メソッドの結果をこの変数に割り当て、必要に応じてアサーションなどで使用します。
セクション9
アサートメソッド(org.junit.Assertクラスに含まれます)は、テストケースの合格/不合格のステータスの判定に使用されます。失敗したアサーションだけが記録されます。アノテーションと同様に、多くのアサートオプションがあります。上記のJUnitの例では、assertEquals(expected, actual, delta)を使用しています。このメソッドは、ユーザー定義の期待される結果、呼び出されたメソッドの結果である実際値、期待値と実際値の間に許容される差異を指定するためのデルタを取ります。アサーションの目的は検証です。アサーションがなくてもJUnitを実行することはできますが、アサーションがなければ、テストの意味がないとも言えるでしょう。アサーションがないと、検証が行われず、せいぜいスモークテストの役にしかたちません。スモークテストでは、テストエラーが発生した場合にのみフィードバックが与えられます。
JUnitの実行方法
お好きな方法を選んでください。ここでは3つの方法、コマンドライン、IDE(EclipseとIntelliJ)、ビルドシステム(MavenとGradle)からJUnitを実行する方法を見ていきます。
コマンドラインからJUnitを実行する方法
コマンドラインから直接JUnitを実行するには、いくつかの要件があります。JDKがパス上にあること、Junitのjarファイル、およびテストケースが必要です。コマンドは次のとおりです(この例はJunit 4用です)。
java -cp /path/to/junit.jar org.junit.runner.JUnitCore <test class name>
注意:実務の場面では、ビルドシステムを使わずに、コマンドラインから手動でテストを実行することはまずありませんが、機能としては可能です。
IDEからJUnitを実行する方法
Eclipse
Eclipseから実行するには、パッケージエクスプローラーでJUnitテストの場所として指定した場所に移動し、テストを選択します。右クリックし、[Run As] > [JUnit Test] をクリックします。テストが実行され、まだJUnitウィンドウが開いていない場合は新しいウィンドウが開きます。
IntelliJ
IntelliJでのテスト実行は、Eclipseとほぼ同じです。プロジェクトウィンドウでテストを右クリックし、[Run ‘testName’] をクリックします。Eclipseと同様に、JUnitウィンドウが開き、テストの結果が表示されます。
ビルドシステムを使用してJUnitを実行する方法
Maven
Mavenでのテストの実行は簡単です。コマンドラインで適切な場所にいることを確認し、プロジェクトpom.xmlが正しく構成されていることを確認してください。次のコマンドを実行してJUnitを実行します。
テストスイート全体を実行する場合:
mvn test
単一/特定のテストを実行する場合:
mvn -Dtest=TestName test
Gradle
Gradleでも、Mavenと同様に、テストの実行は簡単です。
テストスイート全体を実行する場合:
gradlew test
単一/特定のテストを実行する場合:
gradlew -Dtest.single=testName test
(注意:MavenおよびGradleはそれ自体が非常に複雑です – ここに示されているのは、基本をカバーする最小限の事項です)。
ユニットテストの継続
今回の例は非常に単純なコードの断片を使いましたが、これはユニットテストの始まりにすぎません。より複雑なメソッドはデータベースやその他のメソッドを呼び出しますが、機能を安定的に検証するには、他のメソッド呼び出しを出来る限り切り離す必要であり、そのために モックを使用します。モックは、検証対象のコードユニットを分離するのに役立ちます(MockitoとPowerMockは一般的に使用されるフレームワークです)。モックの詳細については、私の同僚の記事「モックとアサーションを含むJavaユニットテストを自動化する方法」をお読みください。
ところで、ユニットテストはこれほどすばらしいのに、誰もがユニットテストを好きではないのはなぜでしょうか?それは単純に、ユニットテストが簡単ではないからでしょう。ユニットテストには開発スキルと時間が必要ですが、開発者にとってはあまり楽しい作業ではないことが多いのです。また、テストスイートを維持するには努力と時間が必要です。
しかし、ユニットテストの利点は明らかです。
- 隔離された小さい範囲でのテスト
- 個々のメソッドまたはメソッドの一部の動作を保証する
- コードの追加や変更がアプリケーションを壊していないことを保証するのに役立つ
- 境界分析 – 無効/不正な入力のチェック
- メソッドのあらゆる側面をテストする(カバレッジ)
- カバレッジ
したがって、 Parasoft Jtestのような強力なユニットテストツールを導入すると、JUnitに関連する多くの苦痛を緩和し、開発者の貴重な時間を節約することができます。Parasoft Jtestの単体テストアシスタントは、直感的なワンクリックアクションでテスト作成をガイドすることで、JUnitのテスト生成時間を短縮し、時間という頭の痛い問題に対処します。また、不安定なテスト環境(およびその他のリスク)、アサーションに関する推奨事項などを検出する自動推奨機能は、保守性の問題を軽減します。
痛みを和らげ、ユニットテストを向上させる方法について詳しくは、 Parasoft Jtest 単体テストアシスタントの無料試用版をダウンロードしてください。Jtestは無料で簡単にセットアップできます。 ここにあるチュートリアルを実行すると、効率的に作業を開始できます。
(この記事は、開発元Parasoft社 Blog 「JUnit Tutorial: Setting Up, Writing, and Running Java Unit Tests」2018年8月2日の翻訳記事です。)
Parasoft Jtestについて
Java対応静的解析・単体テストツール Parasoft Jtest
Jtestは、テスト工数の大幅削減とセキュアで高品質なJavaシステムの開発を強力にサポートするJava対応テストツールです。1,000個以上のコーディング規約をもとにソースコードを静的に解析し、プログラムの問題点や処理フローに潜む検出困難なエラーを検出します。さらに、JUnitを用いた単体テストについて、作成、実行、テストカバレッジ分析、テスト資産の管理といった単体テストに係る作業をサポートし、単体テストの効率化を促進します。