連載
» 2008年09月11日 00時00分 公開

次世代テストフレームワークでテストを変える(1):JUnitより簡単なオープンソースの「TestNG」とは? (2/3)

[阪田浩一,株式会社クロノス]

TestNGのテストクラスを作ってみよう

 ここからは、TestNGを利用したテストを作成しましょう。まず、リスト1はテストの対象となるTargetクラスです。足し算をする単純なメソッドadd()と例外を発生させるメソッドthrowException()を定義します。

public class Target {
    public int add(int a, int b) {
        return a + b;
    }
    public void throwException() {
        throw new RuntimeException("例外が発生しました");
    }
}
リスト1 テスト対象とするクラス

 リスト2はTargetクラスを検証するテストクラスです。

import static org.testng.Assert.assertEquals;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class TestNGSample {
    private Target target;
    public TestNGSample() {
        System.out.println(
            "★TestNGSampleのコンストラクタを呼び出した★");
    }
    @Test
    public void verifyAdd1() {
        System.out.println("★★★verifyAdd1()を呼び出した★★★");
        int result = target.add(1, 2);
        assertEquals(result, 3);
    }
    @Test
    public void verifyAdd2() {
        System.out.println("★★★verifyAdd2()を呼び出した★★★");
        int result = target.add(3, 3);
        assertEquals(result, 6);
    }
    @BeforeMethod
    public void init() {
        System.out.println("★★init()を呼び出した★★");
        target = new Target();
    }
    @Test(expectedExceptions
        = { java.lang.RuntimeException.class })
    public void exceptionTest() {
        System.out.println(
            "★★★exceptionTest()を呼び出した★★★");
        target.throwException();
    }
}
リスト2 テストクラス

 このTestNGSampleがTestNGのテストクラスです。テストクラスは何らかのクラスを継承する必要はありません。テストクラスにはテストメソッドを3つ定義しました。verifyAdd1()とverifyAdd2()、exceptionTest()です。

 TestNGではテストメソッドに@Testアノテーションを付けます。メソッド名はtestで始める必要はなく、任意の名前を付けられます。

 注目はexceptionTest()メソッドです。テストとして例外が発生するかどうかを検証する場合、@Testの属性expectedExceptionsに発生する例外クラスを指定します。テストを実行したときに、指定した例外が発生すればテストは成功、発生しなければテストは失敗となります。JUnit 3の例外テストと比較しても、意図が明確でコード量も少なくなっています。

 もう1つ、@BeforeMethodアノテーションを付けたinit()メソッドを定義しました。これはテストメソッドではありません。BeforeMethodという英語の意味どおり、テストメソッドを実行する前に呼び出したいメソッドには@BeforeMethodを付けます。JUnit 3のsetUp()メソッドと同じ働きです。テストメソッドと同様、任意のメソッド名を付けられます。

 また、JUnit 3のtearDown()と同じことを実現する場合は@AfterMethodアノテーションを付けます。TestNGには@BeforeXXX、@AfterXXXというアノテーションがほかにもいくつかあります。それらについては、次回詳しく解説します。

 このテストを実行すると、以下のように出力されます。テストメソッドの前にinit()メソッドを呼び出していることが分かります。

★TestNGSampleのコンストラクタを呼び出した★
★★init()を呼び出した★★
★★★verifyAdd2()を呼び出した★★★
★★init()を呼び出した★★
★★★exceptionTest()を呼び出した★★★
★★init()を呼び出した★★
★★★verifyAdd1()を呼び出した★★★
実行結果

 なお、テストの実行については、この記事の最後でEclipseプラグインの導入と併せて解説します。

じゃあ、アノテーションを使うJUnit 4との違いは?

 では、同じアノテーションベースのテスティングフレームワークであるJUnit 4とTestNGのテストを比較してみましょう。先ほどのテストをJUnit 4で記述すると、以下のようになります。

import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
public class JUnit4Sample {
    public JUnit4Sample() {
        System.out.println(
            "★JUnit 4Sampleのコンストラクタを呼び出した★");
    }
    private Target target;
    @Test
    public void verifyAdd1() {
        System.out.println("★★★verifyAdd1()を呼び出した★★★");
        assertEquals(target.add(1, 2), 3);
    }
    @Test
    public void verifyAdd2() {
        System.out.println("★★★verifyAdd2()を呼び出した★★★");
        assertEquals(target.add(3, 3), 6);
    }
    @Before
    public void init() {
        System.out.println("★★init()メソッドを呼び出した★★");
        target = new Target();
    }
    @Test(expected = java.lang.RuntimeException.class)
    public void exceptionTest() {
        System.out.println(
            "★★exceptionTest()メソッドを呼び出した★★");
        target.throwException();
    }
}
リスト3 JUnit 4で書いたテストクラス

 TestNGのテストクラスと非常に似ています。@BeforeMethodが@Beforeに、@TestのexpectedExceptions属性がexpected属性に名前が変わっている以外に違いはありません。役割も同じです。

 ただし、同じ@TestでもJUnit 4とTestNGでは別のアノテーションクラスであることに注意してください(import文に注目してください)。

 JUnit 4とTestNGのアノテーションが似ている理由は、JUnit 4がTestNGより後に開発されたため、TestNGに影響を受けているからです。逆に考えると、エンジニアがJUnit 4からより機能の多いTestNGへ移行することも容易であるといえます。さて、このテストを実行すると、以下のように出力されます(※注:実行する場合、JUnit公式サイトから配布アーカイブをダウンロードしてクラスパスに追加してください)。

★JUnit 4Sampleのコンストラクタを呼び出した★
★★init()メソッドを呼び出した★★
★★★verifyAdd1()を呼び出した★★★
★JUnit 4Sampleのコンストラクタを呼び出した★
★★init()メソッドを呼び出した★★
★★★verifyAdd2()を呼び出した★★★
★JUnit 4Sampleのコンストラクタを呼び出した★
★★init()メソッドを呼び出した★★
★★exceptionTest()メソッドを呼び出した★★
実行結果

 TestNGの出力結果と見比べてください。大きな違いが1点あります。

 TestNGはコンストラクタを1回しか呼び出していませんが、JUnit 4では3回呼び出しています。JUnit 3の問題点でも説明したとおり、JUnitはテストメソッドに対してインスタンスを1つ生成します。これは、JUnit 4でもJUnit 3でも同様です。TestNGはインスタンスを1つしか作らず、テスト間で状態を共有します。

 次ページでは、TestNGのEclipseプラグインのインストールについて説明し、次回についてお話します。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。