JUnitでは、テストメソッドに引数を定義できませんでした。しかし、TestNGでは定義できます。では引数を定義したとして、値はどのように渡すのでしょう。渡す値はXMLファイルに記述できます。リスト2は引数に渡す値を定義したtestng.xmlです。
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="samplesuite"> <test name="sampletest"> <parameter name="sei" value="sakata"></parameter> <parameter name="nenrei" value="29"></parameter> <classes> <class name="net.kronosjp.testng.ParameterSample"></class> </classes> </test> </suite>
<parameter>要素を使います。name属性にパラメータの名前、value属性に値を記述します。リスト3は引数を定義したテストメソッドです。testng.xmlに記述したパラメータを受け取ります。
package net.kronosjp.testng; import org.testng.annotations.Parameters; import org.testng.annotations.Test; public class ParameterSample { @Test @Parameters(value = { "sei", "nenrei" }) public void parameterTest(String name, int age) { System.out.println("★" + name + "★" + age); } }
testng.xmlに記述したパラメータを受け取るには、@Parametersアノテーションを使います。value属性には<parameter>のname属性の値を記述します。記述した順序に従ってテストメソッドの引数に値を渡します。今回であれば、テストメソッドの引数nameにはtestng.xmlに定義したパラメータ名seiの値、つまり「sakata」を、同様に引数ageにはnenreiの値である「29」を渡します。testng.xmlからテストを実行すると、次のような結果になります。
★sakata★29
引数の型はStringだけでなく、プリミティブ型とラッパークラスも使用できます。TestNGがパラメータの値を引数の型に合わせて変換します。変換できなかったときは例外が発生します。
しかし、この方法では以下のような2つの問題点があります。
テストメソッドに引数を渡せるのであれば、いろいろな値を渡してテストのパターンを増やしたいというのは自然な要求です。TestNGでは、もう1つパラメータを渡す方法があります。それが@DataProviderアノテーションです。
@DataProviderアノテーションを使ってみましょう。リスト4は@DataProviderを使ったテストです。
import static org.testng.Assert.assertEquals; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; public class DataProviderSample { @DataProvider(name = "add") public Object[][] data() { return new Object[][] { { 1, 2, 3 }, { 3, 3, 6 }, { 6, 4, 10 } }; } @Test(dataProvider = "add") public void verifyAdd(int a, int b, int expected) { Target target = new Target(); int actual = target.add(a, b); assertEquals(actual, expected); } }
2つのメソッドdata()とverifyAdd()があります。data()メソッドには@DataProviderアノテーションを付けています。verifyAdd()はテストメソッドです。注目は@DataProviderのname属性と@TestのdataProvider属性です。同じ「add」という値にしています。そのため、この2つのメソッドは「つながっている」とイメージしてください。
@DataProviderを付けたメソッドはObjectクラスの2次元配列を戻り値とする必要があります。この戻り値である配列の1つ1つの要素(Object配列)がテストメソッドへのパラメータとなります。
サンプルでは3つのObject配列を要素に持つ戻り値のため、verifyAdd()メソッドは引数の値を変えながら3回呼び出されます。verifyAdd()メソッドにどのようなパラメータが渡されるかを次に示します。
パターン | aの値 | bの値 | expectedの値 |
---|---|---|---|
1 | 1 | 2 | 3 |
2 | 3 | 3 | 6 |
3 | 6 | 4 | 10 |
表3 verifyAdd()メソッドへのパラメータ |
1つのObject配列が1回のテストのパラメータとなり、配列の要素が順番に引数の値となります。Eclipseでこのテストを実行すると、次のように表示します。
verifyAdd()を3回呼び出していることが分かります。引数の値もtoString()メソッドを呼び出した形で表示します。何を引数として渡したか非常に分かりやすいと思います。このように@DataProviderを使うと、テストのパターンを簡単に増やせます。
また、戻り値の型がObject配列であるため、Javaにおけるすべての型をパラメータとして渡せます。サンプルではパラメータの値はdata()メソッドに直接記述していますが、@DataProviderを付けたメソッドの中でファイルを読んだりデータベースと接続したりして、テストの実行時にパラメータの設定もできます。TestNGの「使える」機能であるといえます。
筆者はこうした機能を利用して、「テストも部品化が進んでいる」と感じます。TestNGでは、XMLファイルにテストの実行に関する設定を記述することでテストそのものとテストの実行を分離し、テストを組み合わせて1つの大きなテストスイートを作成できます。
データ駆動テストによりテストとデータを分離し、1つのテストにさまざまなデータを組み合わせてテストを実行します。これは「アプリケーション開発がXMLの設定ファイルを導入し、データとロジックを分けていることと同じである」と思います。
開発現場において、こうしたテストの部品化は「1つのテストからより大きな効果を引き出し、結果として開発効率を上げることにつながる」と筆者は考えます。
今回はTestNG独自の機能であるXMLファイルでのテストスイートの設定や前後処理のアノテーション、データ駆動テストについて解説しました。これらは「まったく新しい概念」というわけではなく、テストをより簡単に、より柔軟に作成するための機能です。TestNGが提供する機能は、テスト作成に常に付きまとう「面倒くささ」を軽減してくれるでしょう。
次回は、各種フレームワークとTestNGを統合する方法と、テスト結果のレポートを中心に解説し、実際のプロジェクトにおいてTestNGを利用できるよう実践的な内容にしたいと思います。
Copyright © ITmedia, Inc. All Rights Reserved.