タイトル
TOPJavaテスト → This Page

JUnit(JUnit3)の概要~利用方法【ユニットテスト - テスト】

前提

このページに記載している内容は2011/01/16に書かれたものです。
掲載している画面や方法が将来的に変更されている場合があります。
また、解説に使っている eclipse のバージョンは 3.6.1 です。
eclipseのバージョンによって若干異なる部分があるかもしれません。
「初心者にも分かる JUnit(JUnit3)」を目指して頑張って解説します。

特徴

・最もメジャーに使われている(使われていた?)テスト
・eclipseと連携していて簡単にテスト実行&失敗したテストの理由を表示
・テストメソッドの名称が固定
・テストメソッドに引数を渡せない
・例外が発生するテストが複雑
・テスト前後処理のバリエーションが少ない
・テストメソッドの数だけインスタンスが生成される
 (→これは分離の思想でわざとこう設計されているのでメリットもある)

導入方法

そうとう古いバージョンでなければeclipseに標準で用意されています。

利用方法

テスト対象クラスの作成

まずはテスト対象となるクラスを作成します。
今回は以下のような検証用クラスを作ってみました。

ValidatorUtility.java
package jp.co.junit3.sample;

/**
 * 検証ユーティリティクラス
 */
public class ValidatorUtility {

	/**
	 * ブランクチェック
	 * 
	 * @param value
	 *            値
	 * @return ブランク有無
	 */
	static public boolean isBlank(String value) {
		if (value == null || value.length() == 0) {
			return true;
		}
		return false;
	}

	/**
	 * int値チェック
	 * 
	 * @param value
	 *            文字列
	 * @return int値判定有無
	 */
	static public boolean isInt(String value) {
		if (isBlank(value)) {
			return false;
		}
		try {
			Integer.parseInt(value);
		} catch (NumberFormatException e) {
			return false;
		}
		return true;
	}

}

テストソース用フォルダの作成

とっととテストクラスを作りたいところですが、ここはぐっと我慢してまずはテストソース用フォルダを作成しましょう。
実ソースとテストソースが同じフォルダにあった場合、ある程度の規模のプロジェクトになるとかなり鬱陶しいことになるので。

画面左側の「プロジェクト・エクスプローラー」でプロジェクトを右クリックしてしてメニューから「新規」>「ソース・フォルダ」を選択します。
図:メニュー「新規」「ソース・フォルダ」

「新規ソース・フォルダ」画面が表示されたら「フォルダー名」に test と入力して「完了」ボタンを押します。
図:「新規ソース・フォルダ」画面

するとプロジェクトの src フォルダと同列の場所に test フォルダが作成されたと思います。
図:作成後

テストクラスの作成

ではテストクラスを作ってみましょう。

画面左側の「プロジェクト・エクスプローラー」でテスト対象となるクラスを右クリックしてメニューから「新規」>「その他」を選択します。
図:メニュー「新規」「その他」

「新規」画面が表示されたらツリーから「Java」>「JUnit」>「JUnitテスト・ケース」を選択して
「次へ」ボタンを押します。
図:「新規」画面

「新規JUnitテスト・ケース」画面が表示されたらまずは「ソース・フォルダー」右側の「参照」ボタンを押します。
図:「新規JUnitテスト・ケース」画面

「ソース・フォルダーの選択」画面が表示されたら先ほど作成した test フォルダーを選択して「OK」ボタンを押します。
図:「ソース・フォルダーの選択」画面

「新規JUnitテスト・ケース」画面に戻ったら「ソース・フォルダー」欄の内容が変わっていると思います。
画面の各種項目は以下のようになっています。
項目概要
新規JUnit3テスト/新規JUnit4テスト 本ページはJUnit3の解説なので「新規JUnit3テスト」を選択しましょう。
パッケージ テストクラスを作成する先のパッケージです。基本的にはそのままでいいでしょう。
名前 テストクラス名です。基本的にはそのままでいいでしょう。
スーパークラス テストクラスの継承元となるクラスです。基本的にはそのままでいいでしょう。
setUpBeforeClass JUnit3では使用できません。
tearDownAfterClass JUnit3では使用できません。
setUp テストクラスにsetUpメソッドを自動生成してくれます。今回はチェックをつけましょう。
tearDown テストクラスにtearDownメソッドを自動生成してくれます。今回はチェックをつけましょう。
コンストラクター テストクラスにコンストラクターを自動生成してくれます。今回はチェックをつけましょう。
コメントの生成 コメントを自動生成してくれます。今回はチェックをつけましょう。
テスト元クラス テスト元のクラスです。基本的にはそのままでいいでしょう。
上記項目を正しく設定したら「次へ」ボタンを押します。
図:「新規JUnitテスト・ケース」画面

次の画面は自動生成させたいテストメソッドを選択する画面です。
ツリーにはテスト対象のクラスが持つメソッド、そしてテスト対象クラスの親クラスが持つメソッドを選べます。
今回は親クラス(Objectクラス)のテストは不要なので、ValidatorUtility クラスだけチェックを入れます。
チェックが終わったら「完了」ボタンを押します。
図:「新規JUnitテスト・ケース」2画面

すると test フォルダにテストクラスが作成されています。
コメントやメソッドも自動生成されていますね。
プロジェクトの下に JUnit3 ライブラリも追加されています。
図:基本画面

テストクラスの実装

では作成したテストクラスの中身を実装していきましょう。

自動生成されたメソッドはそれぞれ以下のような役割を持っています。
・ValidatorUtilityTestメソッド
  このクラスのコンストラクタです。
  クラスがインスタンス化された際に実行されるメソッドです。
・setUpメソッド
  各テストメソッドが呼び出される前に実行されるメソッドです。
・tearDownメソッド
  各テストメソッドが呼び出さた後に実行されるメソッドです。
・testIsBlankメソッド
  テスト対象クラスの isBlank メソッドに対するテストメソッドです。
・testIsIntメソッド
  テスト対象クラスの isInt メソッドに対するテストメソッドです。

まずはそれぞれのメソッドがどのような順番で呼び出されるかを確認するために
以下のようなソースにしてみます。

ValidatorUtilityTest.java
package jp.co.junit3.sample;

import junit.framework.TestCase;

/**
 * @author みっちー
 *
 */
public class ValidatorUtilityTest extends TestCase {

	/**
	 * @param name
	 */
	public ValidatorUtilityTest(String name) {
		super(name);
		System.out.println("ValidatorUtilityTest");
	}

	/* (非 Javadoc)
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
		System.out.println("setUp");
	}

	/* (非 Javadoc)
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
		System.out.println("tearDown");
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isBlank(java.lang.String)} のためのテスト・メソッド。
	 */
	public void testIsBlank() {
		System.out.println("testIsBlank");
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)} のためのテスト・メソッド。
	 */
	public void testIsInt() {
		System.out.println("testIsInt");
	}
}

では早速実行してみましょう。
画面左側の「プロジェクト・エクスプローラー」で ValidatorUtilityTest を右クリックしてメニューから「実行」>「JUnitテスト」を選択します。
図:メニュー「実行」「JUnitテスト」

「JUnit」ビュー、「コンソール」ビューが追加されて実行結果が表示されると思います。
図:「コンソール」ビュー

「コンソール」ビューの実行結果を見ると以下のような順番でメッセージが表示されていると思います。

1.ValidatorUtilityTest
2.ValidatorUtilityTest
3.setUp
4.testIsBlank
5.tearDown
6.setUp
7.testIsInt
8.tearDown

以下、解説です。
「特徴」でも挙げた通り、JUnit3ではテストメソッドの数だけインスタンスが生成されます。
今回はテストメソッドが2つあるためインスタンスが2つ生成されます。
そのため、1番目と2番目に ValidatorUtilityTest メソッドが実行されます。
次にテストメソッドの前後で setUp、tearDown メソッドが実行されるので
testIsBlank メソッドのセットとして setUp→testIsBlank→tearDown メソッド、
testIsInt メソッドのセットとして setUp→testIsInt→tearDown メソッドと実行されます。

次に「JUnit」ビューを確認してみましょう。
ツリーが緑色のチェックが付いていて、エラー0、失敗0となっていると思います。
テストメソッドにメッセージ表示のコードしか記述していないので成功したからです。
図:「JUnit」ビュー

さらに testIsBlank、testIsInt メソッドを以下のように変更してみましょう。
ValidatorUtilityTest.java(一部抜粋)
	public void testIsBlank() {
		assertTrue(ValidatorUtility.isBlank(null));
	}

	public void testIsInt() {
		assertTrue(ValidatorUtility.isInt(null));
	}

急に assertTrue というメソッドが出てきたと思います。
このメソッドはテストクラスの親クラスである TestCase クラスが持つ検証メソッドです。
TestCase クラスが持つ検証メソッドは以下の通りです。
検証メソッド概要
assertEquals 期待値と実績値が等しい場合は正常終了。等しくない場合は失敗終了する。
assertFalse 実績値が false の場合は正常終了。true の場合は失敗終了する。
assertNotNull 実績値が null でない場合は正常終了。null の場合は失敗終了する。
assertNotSame 期待値と実績値が同じ参照をしていない場合は正常終了。同じ参照をしている場合は失敗終了する。
assertNull 実績値が null の場合は正常終了。null でない場合は失敗終了する。
assertSame 期待値と実績値が同じ参照をしている場合は正常終了。同じ参照をしていない場合は失敗終了する。
assertTrue 実績値が true の場合は正常終了。false の場合は失敗終了する。
fail このメソッドが実行されると失敗終了する。

と、いうことで上記で修正したコードは
・testIsBlank では ValidatorUtility.isBlank メソッドに null を渡して実行したら true が返されて正常終了するはず。
・testIsInt では ValidatorUtility.isInt メソッドに null を渡して実行したら true が返されて正常終了するはず。
というコードになっています。
が、しかし実際には ValidatorUtility.isInt メソッドに null を渡したら false が返されるので失敗終了します。
では ValidatorUtilityTest クラスを実行してみましょう。

先ほどと同様の手順で実行してみて下さい。
実行完了後、「JUnit」ビューを確認すると失敗1になっていると思います。
「JUnit」ビューの左側のツリーで失敗となったメソッドは赤色のチェックが付いています。
失敗となった isInt メソッドを選択すると、「JUnit」ビューの右側に失敗となった原因の詳細が表示されます。
さらに、詳細の at jp.co.junit3.sample.ValidatorUtilityTest.testIsInt(ValidatorUtilityTest.java:49) をダブルクリックすると
Javaコード・エディターでテストクラスの該当箇所に遷移できます。
図:「JUnit」ビュー2

さて、おおよその使い方も分かったと思うのでテストクラスを完成させましょう。
今のままでは isBlank メソッドのテストも不十分、isInt メソッドはそもそも失敗ですからね。

以下、テストクラスの完成形サンプルです。
ValidatorUtilityTest.java
package jp.co.junit3.sample;

import junit.framework.TestCase;

/**
 * @author みっちー
 * 
 */
public class ValidatorUtilityTest extends TestCase {

	/**
	 * @param name
	 */
	public ValidatorUtilityTest(String name) {
		super(name);
		System.out.println("ValidatorUtilityTest");
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
		System.out.println("setUp");
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
		System.out.println("tearDown");
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isBlank(java.lang.String)}
	 * のためのテスト・メソッド。(null)
	 */
	public void testIsBlank_01() {
		System.out.println("testIsBlank_01");
		assertTrue(ValidatorUtility.isBlank(null));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isBlank(java.lang.String)}
	 * のためのテスト・メソッド。(空白)
	 */
	public void testIsBlank_02() {
		System.out.println("testIsBlank_02");
		assertTrue(ValidatorUtility.isBlank(""));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isBlank(java.lang.String)}
	 * のためのテスト・メソッド。(正常)
	 */
	public void testIsBlank_03() {
		System.out.println("testIsBlank_03");
		assertFalse(ValidatorUtility.isBlank("xxxxx"));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(null)
	 */
	public void testIsInt_01() {
		System.out.println("testIsInt_01");
		assertFalse(ValidatorUtility.isInt(null));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(空白)
	 */
	public void testIsInt_02() {
		System.out.println("testIsInt_02");
		assertFalse(ValidatorUtility.isInt(""));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(数値以外)
	 */
	public void testIsInt_03() {
		System.out.println("testIsInt_03");
		assertFalse(ValidatorUtility.isInt("x"));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(正常)
	 */
	public void testIsInt_04() {
		System.out.println("testIsInt_04");
		assertTrue(ValidatorUtility.isInt("123456"));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(正常マイナス値)
	 */
	public void testIsInt_05() {
		System.out.println("testIsInt_05");
		assertTrue(ValidatorUtility.isInt("-123456"));
	}

	/**
	 * {@link jp.co.junit3.sample.ValidatorUtility#isInt(java.lang.String)}
	 * のためのテスト・メソッド。(int桁あふれ)
	 */
	public void testIsInt_06() {
		System.out.println("testIsInt_06");
		assertFalse(ValidatorUtility.isInt("12345678901234567890"));
	}
}


isBlank メソッドに対するテストメソッドを3つ、isInt メソッドに対するテストメソッドを6つ作成しました。
「特徴」でも挙げた通り、JUnit3ではテストメソッドの名称が固定になります。
テストメソッドの名前は test で始まる名称にしないといけません。
そのため、今回は test + テスト対象メソッド名 + _ + 連番 にしました。

実行してみると全て成功し、「JUnit」ビューは以下の図のようになると思います。
図:「JUnit」ビュー3

テスト・スイートの作成

さて、ここまでくれば「あなたも立派なJUnit使い」と言いたいところですが、
まだ完璧ではありません。

たくさんのクラスを作り、それに対するたくさんのテストクラスを作った場合、
いちいち1つ1つ「右クリック」>「実行」>「JUnitテスト」なんて操作はやってられません。
まだ自分が作成したものだけならいいですが、開発リーダが各メンバーのテスト状況を見たくて
全部実行しなきゃいけないなんてなったら大変です。

そこで、テスト・スイートというものを作成します。
テスト・スイートとは簡単に言うと複数のテストを一括で実行できるものです。

クラスが1つだと寂しいし作る意味がないので、サンプルとしてもう1クラス追加しましょう。

テスト対象クラス
ConvertorUtility.java
package jp.co.junit3.sample;

/**
 * 変換ユーティリティクラス
 */
public class ConvertorUtility {

	/**
	 * nullをブランク文字列に変換する
	 * 
	 * @param value
	 *            文字列
	 * @return nullをブランク文字列に変換した結果文字列
	 */
	static public String nullToBlank(String value) {
		if (value == null) {
			return "";
		}

		return value;
	}

	/**
	 * 2つの文字列をハイフン区切りで結合
	 * 
	 * @param value1
	 *            文字列1
	 * @param value2
	 *            文字列2
	 * @return ハイフン区切りで結合した文字列
	 */
	static public String concatHyphen(String value1, String value2) {
		if (value1 == null) {
			value1 = "";
		}
		if (value2 == null) {
			value2 = "";
		}

		return value1 + "-" + value2;
	}
}

テストクラス
ConvertorUtilityTest.java
package jp.co.junit3.sample;

import junit.framework.TestCase;

/**
 * @author みっち
 * 
 */
public class ConvertorUtilityTest extends TestCase {

	/**
	 * @param name
	 */
	public ConvertorUtilityTest(String name) {
		super(name);
		System.out.println("ConvertorUtilityTest");
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();
		System.out.println("setUp");
	}

	/*
	 * (非 Javadoc)
	 * 
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
		System.out.println("tearDown");
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#nullToBlank(java.lang.String)}
	 * のためのテスト・メソッド。(nullをブランクに)
	 */
	public void testNullToBlank_01() {
		System.out.println("testNullToBlank_01");
		assertEquals("", ConvertorUtility.nullToBlank(null));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#nullToBlank(java.lang.String)}
	 * のためのテスト・メソッド。(ブランクをブランクに)
	 */
	public void testNullToBlank_02() {
		System.out.println("testNullToBlank_02");
		assertEquals("", ConvertorUtility.nullToBlank(""));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#nullToBlank(java.lang.String)}
	 * のためのテスト・メソッド。(文字列はそのまま)
	 */
	public void testNullToBlank_03() {
		System.out.println("testNullToBlank_03");
		assertEquals("xyz", ConvertorUtility.nullToBlank("xyz"));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#concatHyphen(java.lang.String, java.lang.String)}
	 * のためのテスト・メソッド。(null+null)
	 */
	public void testConcatHyphen_01() {
		System.out.println("testConcatHyphen_01");
		assertEquals("-", ConvertorUtility.concatHyphen(null, null));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#concatHyphen(java.lang.String, java.lang.String)}
	 * のためのテスト・メソッド。(null+文字列)
	 */
	public void testConcatHyphen_02() {
		System.out.println("testConcatHyphen_02");
		assertEquals("-xyz", ConvertorUtility.concatHyphen(null, "xyz"));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#concatHyphen(java.lang.String, java.lang.String)}
	 * のためのテスト・メソッド。(文字列+null)
	 */
	public void testConcatHyphen_03() {
		System.out.println("testConcatHyphen_03");
		assertEquals("abc-", ConvertorUtility.concatHyphen("abc", null));
	}

	/**
	 * {@link jp.co.junit3.sample.ConvertorUtility#concatHyphen(java.lang.String, java.lang.String)}
	 * のためのテスト・メソッド。(文字列+文字列)
	 */
	public void testConcatHyphen_04() {
		System.out.println("testConcatHyphen_04");
		assertEquals("abc-xyz", ConvertorUtility.concatHyphen("abc", "xyz"));
	}
}

上記2つのクラスが完成したら「プロジェクト・エクスプローラー」は以下の図のようになっていると思います。
図:プロジェクト・エクスプローラー

「プロジェクト・エクスプローラー」で test の jp.co.junit3.sample パッケージを右クリックしてしてメニューから「新規」>「その他」を選択します。

「新規」画面が表示されたらツリーから「Java」>「JUnit」>「JUnitテスト・スイート」を選択して「次へ」ボタンを押します。

「新規JUnitテスト・スイート」画面が表示されたら各種項目を入力・選択して「完了」ボタンを押します。
各種項目の内容は以下の通りです。今回はどれもデフォルトのままでOKです。
項目概要
ソース・フォルダー テスト・スイートを作成する先のフォルダの場所です。
パッケージ テスト・スイートを作成する先のパッケージです。
名前 テスト・スイートのクラス名です。
スイートに含まれるテスト・クラス テスト・スイートに含めたいテスト・クラスにチェックを入れます。

図:「新規ソース・スイート」画面

すると test フォルダにテスト・スイートクラス AllTests が作成されています。
図:「AllTests」クラス

では AllTests を実行してみましょう。
実行方法は通常のテスト・クラスと同様です。

実行が終了して「JUnit」ビューを開くと全てのテスト・クラスが実行されて全て成功となっているはずです。
以下の図は「JUnit」ビューのツリーを展開した状態です。
図:「JUnit」ビュー4

以上、ここまでできればあなたも「立派なJUnit使い」です。


と、テスト・スイートについて説明しましたが、実は eclipse からの実行だと
「プロジェクト・エクスプローラー」で test フォルダを右クリックして「実行」>「JUnit」だけでも
パッケージ以下のテストを一括実行できたりします。
ただし、この方法だとパッケージ以下の全てのテストを実行してしまうので、
まだ実行させたくないテスト・クラスがあったりする場合はテスト・スイートを作成して明示的に実行対象のテスト・クラスを記述したほうがいいです。

ダウンロード

解説で使ったクラスなどを含んだ eclipse 用プロジェクト一式

更新履歴

2011/01/23 少しだけ修正
2011/01/16 新規作成


TOPJavaテスト → This Page