SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

JUnitフレームワークによるJava ME単体テスト

J2MEUnit/JMUnitを利用した単体テストの方法

ダウンロード Conversion 1.0 (264.7 KB)
ダウンロード Conversion 1.1 (117.5 KB)

JMUnitでの作業

JMUnitのセットアップ

 JMUnitダウンロードを入手したら、Java MEコンパイラとランタイム環境またはIDEの両方について、2つのJMUnit .jarファイル(「JMUnit4CLDC10.jar」と「JMUnit4CLDC11.jar」)をクラスパス上に配置します。JMUnitの現在のリリースは1.0.2です。

JMUnitのテストケース

 JMUnitが提供するフレームワークには2つのバージョンがあり、別々のJARに収められています。1つはCLDC 1.0アプリケーション用で、もう1つは浮動小数点基本型をサポートするCLDC 1.1アプリケーション用です。JUnit流のしきたりでは、JMUnitを使用する適切な単体テストを作成するための最初のステップは、テストケースを作成することです。JMUnitのテストケースを作成するには、JMUnitのjmunit.framework.cldc10.TestCaseまたはjmunit.framework.cldc11.TestCaseを拡張した新しいテストケースクラスを作成しなければなりません。パッケージ名からわかるように、前者は1.0バージョンのサポートを提供し、後者は1.1バージョンのサポートを提供します。両者の違いは、cldc11.TestCaseで実装されているassertEquals()メソッドとassertNotEquals()メソッドがJava浮動小数点基本型をサポートすることだけです(下記を参照)。

 JUnitのしきたりでは、テストケースクラスの名前はテスト対象クラスの名前を含み、末尾が「Test」でなければなりません。したがって、先ほどの温度変換クラスのCLDC 1.1バージョンをテストするJMUnitテストケースなら、次のように定義されるでしょう。

public class TemperatureConversionTest
    extends jmunit.framework.cldc11.TestCase {}

 すべてのテストメソッドがテストケースクラスに含まれていなければなりません。JUnitのしきたりにより、テストメソッドの名前は「test」で始まり、その後ろにテスト対象クラス内のメソッドの名前が付きます。たとえば、fahrenheitToCelsiusメソッドをテストするためのテストケースメソッドなら、testfahrenheitToCelsiusとなります。各テストメソッドは期待される結果を「アサート(assert)」しなければなりません。JUnitテストに不慣れな方のために申し上げると、アサートとはメソッドの実行結果がプログラマの期待どおりか否かを検証するステートメントです。JMUnitは次のアサーションをサポートしています。

assertTrue(expression)
assertFalse(expression)
assertSame(expected, actual)
assertNotSame(expected, actual)
assertEquals(expected, actual)
assertNotEquals(expected, actual)
assertNull(object)
assertNotNull(object)

 JMUnitでは、これらのアサーション呼び出しのいずれかを使用するテストメソッドはAssertionFailedExceptionをスローしなければなりません。フレームワークは、この例外を使って失敗したテストを識別します。適切なテストメソッドを持つTemperatureConversionTestクラスは、次のようになるでしょう。

import jmunit.framework.cldc11.*;

public class TemperatureConversionTest extends TestCase {

    public void testfahrenheitToCelsius()
        throws AssertionFailedException {
        System.out.println("fahrenheitToCelsius");
        float result = TemperatureConversion.fahrenheitToCelsius(66F);
        assertEquals(18.88889F, result);
    }

    public void testcelsiusToFahrenheit()
        throws AssertionFailedException {
        System.out.println("celsiusToFahrenheit");
        float result = TemperatureConversion.celsiusToFahrenheit(20F);
        assertEquals(68F, result);
    }

    public void testisHotter() throws AssertionFailedException {
        System.out.println("isHotter");
        assertTrue(TemperatureConversion.isHotter(70F, 2F));
    }

    public void testisCooler() throws AssertionFailedException {
        System.out.println("isCooler");
        assertTrue(TemperatureConversion.isCooler(10F, 10F));
    }
}

 標準のJUnit実装により、JMUnitのテストケース抽象クラスにはsetup()tearDown()というメソッドも用意されています。これらをオーバーライドして、テストケースを通じたテストの実行の前後にオブジェクトやリソースを初期化したりクリーンアップしたりすることができます。たとえば、Java MEアプリケーションでは、setupでテスト前にレコードストアを開き、tearDownでテスト後にレコードストアを閉じることができます。これらに加え、fail()メソッドでは、アサートステートメントに関係なく、テストメソッドでテストの失敗を返すことができます。このメソッドはテストメソッド内のある種の条件でよく使われます。また、まだ作業が必要なことを示すための方法として、未開発の単体テストをスタブアウトするのにも使用できます。

 JMUnitのテストケースクラスにはコンストラクタも付属しています。JMUnitのテストケースクラスのいずれかを拡張したテストケースクラスのコンストラクタは、スーパーコンストラクタを呼び出し、テストケースのテスト数を表す整数とテストケースを識別する文字列を渡さなければなりません。

public TemperatureConversionTest() {
    super(4, "TemperatureConversionTest");
}

 テスト数を表す整数は、テストケースの実際のテスト数と一致していなければなりません。コンストラクタに渡すテスト数と、テストケースの実際のテスト数とを一致させることが大切です。テストケースのtest(int testNumber)メソッドを見ると、これが分かります。

 テストケースのtest(int testNumber)メソッドからテストメソッドが始まります。Java MEにはリフレクション機能がないので、JUnitのようにテストメソッドを見つけて自動的に実行することはできません。そのため、テストメソッド内のswitchステートメントに各テストメソッドを追加し、テスト番号に基づいて呼び出す必要があります。TemperatureConversionTestの場合、テストメソッドのコードは次のようになるでしょう。

public void test(int testNumber) throws Throwable {
    switch(testNumber) {
        case 0:testfahrenheitToCelsius();break;
        case 1:testcelsiusToFahrenheit();break;
        case 2:testisHotter();break;
        case 3:testisCooler();break;
        default: break;
    }
}

 これがテストケースコンストラクタにテスト数を渡さなければならない理由です。実行時、JMUnitフレームワークはテストケースクラスのインスタンスを作成します。フレームワークはループの中で、0から(テスト数-1)まで、テストケースインスタンスの各メソッドを呼び出します。このようにして、テストメソッドのswitchステートメントの各case(したがって各単体テスト)がフレームワークによって呼び出されます。テストケースにテストメソッドを追加するときにテストケースクラスコンストラクタを更新し忘れると、トリガされないテストケースが出てしまいます。

 JMUnitでは開発者自身がテストメソッドを書くので、テストメソッドの実行方法がJUnitとは異なってきますし、おそらくJMUnitの方が柔軟性に優れています。JMUnitではテストメソッドを制御できるため、パラメータを受け取るテストを書くことができます(JUnitではリフレクションを利用するのでこれができません)。たとえば、TemperatureConverstionTestのテストメソッドは次のようになるでしょう。

public void testcelsiusToFahrenheit(float c, float f) 
                                    throws AssertionFailedException {
    System.out.println("celsiusToFahrenheit(float c)");
    float result = TemperatureConversion.celsiusToFahrenheit(c);
    assertEquals(f, result);
}

 こうすると、テストメソッドはパラメータを使って、switchステートメントの中でこのテストメソッドを呼び出すことができます。

public void test(int testNumber) throws Throwable {
    switch(testNumber) {
        case 0:testfahrenheitToCelsius();break;
        case 1:testcelsiusToFahrenheit();break;
        case 2:testisHotter();break;
        case 3:testisCooler();break;
        case 4:testcelsiusToFahrenheit(20F, 68F);break;
        default: break;
    }
}

JMUnit TestSuite

 テストスイートは1つ以上のテストケースを管理します。JMUnitには2つのテストスイート抽象クラス(jmunit.framework.cldc10.TestSuiteとjmunit.framework.cldc11.TestSuite)が用意されているので、これらを拡張してテストスイートを作成します。テストケースの場合と同様に、拡張すべきテストスイートのタイプは、どちらのバージョンのCLDCを使用するかで決まります。CLDC 1.0のアプリケーションにはcldc10.TestSuiteを使用し、CLDC 1.1のアプリケーションにはcldc11.TestSuiteを使用してください。どちらのテストスイート抽象クラスにも、パラメータとして文字列を受け取るコンストラクタがあります。この文字列はテストスイートの説明となります。

 テストスイートの機能は、該当するすべてのテストケースのインスタンスを作成し、それらのテストケースのテストメソッドを呼び出すことだけです。テストスイートにテストケースを追加するには、テストスイートの構築時にadd(testCase)メソッドを使用します。変換テストケース用のテストスイートの例を次に示します。

import jmunit.framework.cldc11.TestSuite;

public class ConversionTestSuite extends TestSuite {
 
    public ConversionTestSuite() {
        super("All Conversion Tests");
        add(new DistanceConversionTest());
        add(new TemperatureConversionTest());
    }
}

JMUnitテストの実行

 JMUnitの抽象クラスであるTestCaseとTestSuiteは、MIDletのサブクラスです。これにより、個々のテストケースまたはテストスイートをエミュレータで(または、ありそうもないことですが、実際のデバイスで)実行することができます。シミュレータ上で実行すると、各テストケースまたはテストスイートは、exitとtestという2つのコマンドを提供します。図1は、上述のテストスイートの実行結果を示しています。図2は、失敗がどのように表示されるかを示しています。

図1 テストケースを実行する: JMUnitのテストスイートを実行すると、そのスイートを終了またはテストするオプションが与えられる。テストスイート結果はグラフィカルに示される
図1 テストケースを実行する: JMUnitのテストスイートを実行すると、そのスイートを終了またはテストするオプションが与えられる。テストスイート結果はグラフィカルに示される
図2 失敗したテストケース: テストケースが失敗すると、失敗が赤でグラフィカルに示される
図2 失敗したテストケース: テストケースが失敗すると、失敗が赤でグラフィカルに示される

 テストの実行時にはコンソールもチェックしたいものです(図3を参照)。とりわけ、失敗についてはコンソール出力を見るほうがよくわかります。失敗の出力には、スタックトレース情報と、テストでの実際の値と期待される値が含まれています。これは次に取り上げるJ2MEUnitと比べると、少し見劣りする機能の1つかもしれません。J2MEUnitでは、テストケースの失敗が、コンソール出力の代わりに、エミュレーションデバイス上に実際に表示されます。

図3 失敗したテストケースのコンソール出力: 失敗したケースのテキスト出力は、どのテストケースが失敗し、なぜ失敗したかを示し、スタックトレースを提供して、失敗した箇所を確認できるようにする
図3 失敗したテストケースのコンソール出力: 失敗したケースのテキスト出力は、どのテストケースが失敗し、なぜ失敗したかを示し、スタックトレースを提供して、失敗した箇所を確認できるようにする

次のページ
J2MEUnitでの作業

この記事は参考になりましたか?

japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Jim White(Jim White)

Intertech Trainingのインストラクタ。『Java 2 Micro Edition』(Manning刊)の共著者でもある。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/709 2008/08/26 14:07

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー