月別: 2011年7月

Unit Testing GWT Applications with JUnit

http://code.google.com/intl/ja/webtoolkit/doc/latest/tutorial/JUnit.html

  JUnitを使用したGWTアプリケーションのユニットテスト

この時点で、あなたはStockWatcherアプリケーションの最初の実装を作成済みで、それはかなり安定しているようです。
コードベースが進化した時、あなたはどうやってあなたが既存の機能を駄目にしていないと保証出来ますか?その解決法はユニットテストをすることです。 良いユニットテストケース群を作成することはアプリケーションのライフサイクル上でその品質を保証するのに重要な部分です。
あなたのテストしようとする試みを助けるために、GWTはオープンソース JUnit テスティングフレームを伴うインテグレーション(組込み)を提供します。開発モードとプロダクションモードの両方で走らせることが出来るユニットテストを作成することが出来ます。
このセクションでは、StockWatcherプロジェクトへJUnit ユニットテストを追加します。
  1. StockWatcher用のJUnitテストクラスとテスト実行用スクリプトの作成
  2. ユニットテストを走らせる
  3. ユニットテストを書く
  4. ユニットテストで識別された問題を解決する
Note: JUnitテストの幅広いガイドはJUnit Testingを見てください。

 始める前に

StockWatcher プロジェクト

このチュートリアルはGWTの概念とBuild a Sample GWT Application チュートリアルで作成した
StockWatcherアプリケーションを基にしています。 もしGWTアプリケーション作成チュートリアルを
終えておらずGWTの概念がある程度わかっているなら(慣れ親しんでいるなら)、
ここでStockWatcherプロジェクトをコードとしてインポートすることが出来ます。 
  1. StockWatcher projectをダウンロードします。
  2. ファイルを解凍します。
  3. エクリプスへプロジェクトをインポートします。
    1. ファイル メニューから、インポートメニューオプションを選択します。
    2. [一般]-[既存プロジェクトをワークスペースへ]を選択します。次へ(N)ボタンをクリックします。
    3. [ルート・ディレクトリーの選択(T)]でブラウズしStockWatcherのあるディレクトリ
      (ファイルを解凍した場所から)を選択します。完了(F) ボタンをクリックします。
antを使用している場合は、StockWatcher/build.xmlの何処にGWTを解凍したかを指す
 gwt.sdk プロパティを編集します。

antを使用している場合は、システム上のJUnitの場所を指し示すためにpath_to_the_junit_jarへの全ての参照を
置き換えてください。

Note: サンプルGWTアプリケーションの構築を完了していて、webAppCreatorで-junit オプションを指定していない場合は、作業を継続する前にStockWatcher/build.xml内のjavac.teststest.devtest.prod, test ターゲットをアンコメント化して、システム上のJUnitの場所を指し示すために path_to_the_junit_jar への全ての参照を置き換えてください。

 1. JUnitテストの作成

 -junit オプションを指定した時、webAppCreatorはJUnitテストの開発を開始するために必要な全てのファイルを作成しました。(※時制が過去?) webAppCreatorはスターターテストクラス、コマンドラインからテストを実行するantターゲットを生成し、Eclipse用の構成ファイルを起動します。
GWT2.0から、以前のコマンドラインツールjunitCreatorはwebAppCreatorに統合されました。
Eclipseで、test/ ディレクトリを展開することによってStockWatcherTestクラスまで移動します。
既存のアプリケーションへJUnitテストを追加する場合、あなたのEclipseプロジェクト内にソースフォルダとして test/ ディレクトリを追加し、既存のJUnitライブラリへの参照を含むためにビルドパスを更新する必要があります。
screenshot: JUnit tests in Package Explorer

テストクラスの試験する: StockWatcherTest.java

StockWatcherTest.javaの内部を見てください。このテストクラスはStockWatcher/testディレクトリ以下のcom.google.gwt.sample.stockwatcher.clientパッケージ内に生成されます。(※was?) 
このクラスにStockWatcher用のユニットテストを書きます。現在、単一の簡単なテストが含まれています: testSimple メソッド
  1. StockWatcherTest.java ファイルを開きます。
    package com.google.gwt.sample.stockwatcher.client;

    import com.google.gwt.junit.client.GWTTestCase;

    /**
    * GWT JUnit tests must extend GWTTestCase.
    */
    public class StockWatcherTest extends GWTTestCase { // (1)

    /**
    * Must refer to a valid module that sources this class.
    */
    public String getModuleName() { // (2)
    return "com.google.gwt.sample.stockwatcher.StockWatcher";
    }

    /**
    * Add as many tests as you like.
    */
    public void testSimple() { // (3)
    assertTrue(true);
    }

    }

Notes

(1) 全てのGWT JUnitテストケースのように、 StockWatcherTest クラスはcom.google.gwt.junit.clientパッケージ内のGWTTestCase クラスをextendします。
このクラスをextendすることによって追加のテストケースを作成することが出来ます。
(2)StockWatcherTestクラスはGWTモジュールの名前を返さなければならない抽象メソッド(getModuleName)を持っています。
StockWatcherでは、それは”com.google.gwt.sample.stockwatcher.StockWatcher”です。
(3)StockWatcherTestクラスは簡単なテストケース(トートロジカルテスト testSimple)と共に生成されます。 このtestSimpleメソッドはGWTTestCaseクラスの祖先であるJUnitAssertクラスから継承した多くのassert〜 メソッドの一つを使用します。assertTrue(boolean)メソッドは渡されたブーリアン引数をtrueと評価するアサートをします? そうでなければ、JUnit内で実行した時にtestSimpleテスト失敗するでしょう。

※トートロジー… 変項の値のいかんにかかわらず、常に真であるような論理式。(トートロジー)
この場合だとassertTrue(true);の部分を指している?


アサートアサーション

 2. ユニットテストを実行する

あなた自身のStockWatcher用のユニットテストを書き始める前に、テスト環境のコンポーネントが適切であることを確認してください。スターターテスト testSimpleを実行するStockWatcherTest.javaを走らせることによってその確認は出来ます。
四つの方法でJUnitテストを走らせることが出来ます:
  • コマンドラインから—junitCreatorによって生成されたスクリプトを使用します。
  • Eclipseで—Google Plugin for Eclipseを使用します。
  • Eclipseで—webAppCreatorによって生成されたEclipseの起動構成ファイルを使用します。
  • 手動テストモードで

コマンドラインから

GWT webAppCreatorによって生成されたbuild.xmlファイルはテストのために使用される生成された三つのターゲットを含みます:
  • test.dev
    開発モードで全てのテストクラスを走らせます。
  • test.prod
    プロダクションモードで全てのテストクラスを走らせます。
  • test
    test.devとtest.prodの両方を走らせます。
Note: コマンドラインからテストを走らせるために、システムにJUnitがインストールされている必要があります。StockWatcherプロジェクトをダウンロードしている場合、あなたは最初にbuild.xmlを開き、 /path/to/junit-3.8.1.jar への全ての参照をシステム上のjunitへのパスに置き換えなければなりません。
  1. コマンドシェル上でStockWatcherディレクトリへ移動します。
  2. 開発モードでJUnitテストを走らせます。
    コマンドラインで、 ant test.dev と入力します。
  3. テストはJVM上でJavaバイトコードとして走ります。
    simpleTestはエラー無しで実行されます。
    [junit] Running com.google.gwt.sample.stockwatcher.client.StockWatcherTest
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 15.851 sec
  4. プロダクションモードでJUnitテストを走らせます。
    コマンドラインで、ant test.prod と入力します。 
  5. テストはコンパイル済みJavaScriptとして走ります。
    simpleTestはエラー無しで実行されます。
    [junit] Running com.google.gwt.sample.stockwatcher.client.StockWatcherTest
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 37.042 sec

Eclipseで (Google Plugin for Eclipseを使用)(※原文 Pluginプラグインのそういう表記があるのかもしれないが、この場合は不要と考え、gを削除)

Google Plugin for EclipseはEclipseでテストを走らせることを容易にします。
  1. 開発モードでJUnitテストを走らせます。
    パッケージエクスプローラから、走らせたいテストケースを右クリックし、
    実行(R) > GWT Junit を選択します。
  2. simpleTestはエラー無しで実行されます。
    screenshot: JUnit tests in Eclipse
  3. プロダクションモードでJUnitテストを走らせます。
    パッケージエクスプローラから、走らせたいテストケースを右クリックし、
    実行(R) > GWT Junit(production mode)を選択します。
  4. simpleTestはエラー無しで実行されます。

Eclipseで (生成された起動構成を使用)

webAppCreatorによって生成された、開発モード・プロダクションモード両用の起動構成を使用してEclipseでユニットテストを走らせることが出来ます。
  1. 開発モードでJUnitテストを走らせます。
    Eclipseメニューバーから、 実行(R) > 実行構成(N)を選択します。
  2. 「実行構成」ウィンドウで、StockWatcherTest-devを選択します。(※JUnit直下)
  3. Mac OSXを使用している場合は、Java仮想マシンを呼び出すために引数を追加します。
    「引数」タブを表示します。
    “VM引数(G)”に -XstartOnFirstThread -Xmx256M と入力します。
    引数の変更を保存するために”適用(Y)“ボタンを押下します。
    テストを実行するために”実行(R)“ボタンを押下します。
  4. simpleTestはエラー無しで実行されます。
    screenshot: JUnit tests in Eclipse
  5. プロダクションモードでJUnitテストを走らせます。
    Eclipseメニューバーから、 実行(R) > 実行構成(N)を選択します。
  6. 「実行構成」ウィンドウで、StockWatcherTest-prodを選択します。(※JUnit直下)
  7. Mac OSXを使用している場合は、Java仮想マシンを呼び出すために引数を追加します。
    「引数」タブを表示します。
    “VM引数(G)”に -XstartOnFirstThread -Xmx256M と入力します。
    引数の変更を保存するために”適用(Y)“ボタンを押下します。
    テストを実行するために”実行(R)“ボタンを押下します。

    At VM argument, enter -XstartOnFirstThread -Xmx256M

  8. simpleTestはエラー無しで実行されます。

 手動テストモード

ユニットテストを実行するブラウザを選択したい場合は、手動テストモードを使用します。手動テストモードでは、JUnitShellのmainクラスは通常通り指定したGWTモジュール上で走りますが、直ちにテストを走らせる代わりにURLを出力してブラウザが接続するのを待ちます。このURLをあなたの選択したブラウザへ手動でカット&ペーストして、ユニットテストをそのブラウザ内で走らせることが出来ます。
詳細: 手動モードでユニットテストを走らせる方法を学ぶには開発者ガイドのCreating a Test Caseを見てください。

 3. ユニットテストを書く

実際のテストシナリオで出来るだけ多くのStockWatcherの挙動を確認したいでしょう。あなたは幾つものStockWatcherクラス用のユニットテストを追加することが出来ます。publicメソッドの形式で各テストを書くことが出来ます。
多数のテストケースを持っている場合、異なるテストクラスにグループ分けすることによってテストケースを編成することが出来ます。
しかしながら、GWTでのJUnitテストのセットアップの手順を学ぶために、このチュートリアルでは一つのテストを書き、それを走らせます。
  1. StockPriceクラスのコンストラクタが正しく新しいオブジェクトのインスタンスフィールドにセットされていることを確認するためのJUnitテストを書きます。
    StockWatcherTestクラスへ、以下に示すtestStockPriceCtorメソッドを追加します。
    /**
    * Verify that the instance fields in the StockPrice class are set correctly.
    */
    public void testStockPriceCtor() {
    String symbol = "XYZ";
    double price = 70.0;
    double change = 2.0;
    double changePercent = 100.0 * change / price;

    StockPrice sp = new StockPrice(symbol, price, change);
    assertNotNull(sp);
    assertEquals(symbol, sp.getSymbol());
    assertEquals(price, sp.getPrice(), 0.001);
    assertEquals(change, sp.getChange(), 0.001);
    assertEquals(changePercent, sp.getChangePercent(), 0.001);
    }
  2. 開発モードでStockWatcherTestを再び走らせます。
    どちらのテストもパスするはずです。
    [junit] Running com.google.gwt.sample.stockwatcher.client.StockWatcherTest
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 16.601 sec

 4. ユニットテストで識別された問題の解決

ユニットテストが失敗した場合に何が起こるかを見るために、Build a Sample GWT Applicationチュートリアルで修正した計算バグを再導入します。 当初、変動のパーセンテージはgetChangePercentメソッドで正しく計算されていませんでした。ユニットテストを失敗させるために、このコードを再び壊します。
  1. StockWatcherへバグを導入します。
    StockPrice.javaで以下でハイライトされている部分の変更を行います。
    public double getChangePercent() {
    return 10.0 * this.change / this.price;
    }
  2. 開発モードでStockWatcherTestを走らせます。 (Eclipseまたはコマンドラインのどちらかで)
    JUnitは失敗したテストケースを識別します。 (testStockPriceCtor).
    (Eclipseで走らせた場合の出力結果)
    screenshot: JUnit tests failed
    …そして結果である例外(AssertionFailedError)のフルスタックトレースを提供します。
    (コマンドラインから走らせた場合の出力結果)
    Testsuite: com.google.gwt.sample.stockwatcher.client.StockWatcherTest
    Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 16.443 sec

    Testcase: testSimple took 16.238 sec
    Testcase: testStockPriceCtor took 0.155 sec
    FAILED
    Remote test failed at 172.29.212.75 / Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
    expected=2.857142857142857 actual=0.2857142857142857 delta=0.0010
    junit.framework.AssertionFailedError: Remote test failed at 172.29.212.75 / Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
    expected=2.857142857142857 actual=0.2857142857142857 delta=0.0010
    at com.google.gwt.sample.stockwatcher.client.StockWatcherTest.testStockPriceCtor(StockWatcherTest.java:38)
    at com.google.gwt.sample.stockwatcher.client.__StockWatcherTest_unitTestImpl.doRunTest(__StockWatcherTest_unitTestImpl.java:7)
    ...
    Note: コマンドラインから走らせる場合、テスト完了レポート(スタックトレースを含む)は、開発モードテスト用はreports/htmlunit.dev/ディレクトリ、プロダクションモードテスト用は reports/htmlunit.prod/ディレクトリに置かれます。
  3. エラーを訂正します。
  4. テストを再び走らせます。
    両方のJUnitテストは再び成功裡に完了するはずです。
    [junit] Running com.google.gwt.sample.stockwatcher.client.StockWatcherTest
    [junit] Tests run: 2, Failures: 0, Errors: 0, Time elapsed: 16.114 sec
ベストプラクティス: JavaScriptへコンパイルした場合とJavaバイトコードとして走っている場合とで、GWTアプリケーションの動き方で微妙な違いが存在し得るので、アプリケーションを開発している時は開発モードとプロダクションモードの両方でユニットテストが走ることを確認してください。しかし、プロダクションモードで走らせた時にテストケースが失敗する場合、開発モードで見た完全なスタックトレースを取得しないことに気づいていてください。

 テストについて

この時点で、StockWathcer用のJUnitテストを作成し、簡単なテストケースを追加しています。 
GWTでのユニットテストの全種類についてより詳しく学びたいならば、開発者ガイドを見てください: