広告

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2010年11月03日

    Java総合講座 - 初心者から達人へのパスポート
                  vol.207

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:vol.xxx(xxxは番号)が振られています。
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:xxx号(xxxは番号)が振られています。
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


========================================================
◆ 01.Strutsのアプリケーション開発(プロジェクト:StrutsShop)
========================================================

では、ItemListActionTestクラスのソース・コード

--------------------------------------------------------
package jp.co.flsi.lecture.struts;

import java.io.File;
import java.util.Vector;

import jp.co.flsi.lecture.struts.db.Item;
import jp.co.flsi.lecture.struts.db.ItemDbManager;
import jp.co.flsi.lecture.struts.db.StruShopDbException;

import servletunit.struts.MockStrutsTestCase;

public class ItemListActionTest extends MockStrutsTestCase {

   public void setUp() throws Exception {
         super.setUp();
         File contextDir = new File("C:\\JavaWorkSpace\\StrutsShop\\WebContent");
         setContextDirectory(contextDir);
   }

   public void tearDown() throws Exception {
         super.tearDown();
   }

   public void testExecuteActionMappingActionFormHttpServletRequestHttpServletResponse() throws StruShopDbException {
      setRequestPathInfo("/itemlist");
      addRequestParameter("keyword", "製品001");
      addRequestParameter("categoryNum", "00001");
      actionPerform();
      verifyForward("success");
      verifyForwardPath("/itemList.jsp");
      ItemDbManager itemDbManager = new ItemDbManager();
      itemDbManager.connect();
      Vector<Item> itemList = itemDbManager.getDataByItemNameAndCatNum("製品001", "00001");
      Vector<Item> itemList2 = (Vector<Item>) getRequest().getAttribute("itemList");
      assertEquals(itemList.get(0).getNum(), itemList2.get(0).getNum());
      itemDbManager.disconnect();
      verifyNoActionErrors();
   }

}
--------------------------------------------------------

を簡単に解説しておきましょう。


まずsetUp()メソッドですが、これはvol.161でお話したJUnitのsetUp()メソッド
と同様で、テストの前準備を行うためのメソッドです。
詳しくはvol.161等を復習して下さい。


この中で使っているsetContextDirectory()というメソッドはStrutsTestCase特有の
メソッドで、Strutsのコンテキスト・ディレクトリー(= コンテキスト・ルートのディ
レクトリー、つまり、Webアプリケーションが置かれているディレクトリー。この
ディレクトリーにはWEB-INFディレクトリーが入っている)を指定するものです。
         File contextDir = new File("C:\\JavaWorkSpace\\StrutsShop\\WebContent");
         setContextDirectory(contextDir);
のようにコンテキスト・ディレクトリーをFileオブジェクトとして表現し、
setContextDirectory()メソッドの引数として指定します。

StrutsTestCaseはStrutsアプリケーションの構成情報(struts-config.xml)を
このコンテキスト・ディレクトリーのWEB-INFディレクトリーから読み出して
アプリケーションの実行を行います。
そのため、このディレクトリーの指定が正しくないと正常にテストを実行でき
ません。


なお、setUp()メソッドの中では、テストの前提になるデータベースのデータ
を設定しておく(いったん各テーブルのデータを空っぽにしておいてから、
テストの前提になるデータをINSERTしておく)のが普通ですが、上のソース・
コードでは省略してあります(上記のソース・コードでは、これまでの記事で
データベースにINSERTしてきたデータでテストできるようになっています)。
setUp()メソッドの中にデータベースのデータを設定するコードを書くこと
は読者への課題としておきますので、自分でコードを追加してみて下さい
(詳しくはvol.162等を復習して下さい)。



tearDown()メソッドも、やはりvol.161でお話したJUnitのtearDown()メソッド
と同様で、テストの後始末を行うためのメソッドです。
詳しくはvol.161等を復習して下さい。


上記のtestExecuteActionMappingActionFormHttpServletRequestHttpServletResponse()
のようにtestで始まるメソッド名のメソッドが実際にテストを行うメソッドです。
これはvol.161でお話したtestXXXX()メソッドと同様ですね。
このメソッド名のXXXXのところには、自分で自由に名前を付けられますが、今回は
Eclipseで自動的に生成されたtestExecuteActionMappingActionFormHttpServletRequestHttpServletResponse
という名前をそのまま使っています。

複数テストをしたいときは、例えばtestNantoka1()、testNantoka2()、testNantoka3()
というようにそれぞれ異なる名前の複数のメソッドを用意します。
すると、テストの実行時には

(1) setUp()メソッド
(2) testNantoka1()メソッド
(3) tearDown()メソッド
(4) setUp()メソッド
(5) testNantoka2()メソッド
(6) tearDown()メソッド
(7) setUp()メソッド
(8) testNantoka3()メソッド
(9) tearDown()メソッド

という順番で実行されることになります。これもvol.161でお話しましたね。


上のソース・コードの場合は、testExecuteActionMappingActionFormHttpServletRequestHttpServletResponse()
というテスト・メソッドしか用意していませんから、

(1) setUp()メソッド
(2) testExecuteActionMappingActionFormHttpServletRequestHttpServletResponse()メソッド
(3) tearDown()メソッド

という順番で実行されることになります。



次に、このテスト・メソッドの中の

      setRequestPathInfo("/itemlist");

というコードですが、これは、Strutsアプリケーションの構成情報(struts-config.xml)
の中の<action-mappings>において、どのpathを使用するかを指定します。
つまり、この"/itemlist"というのは、struts-config.xmlファイルの中に指定
した

    <action path="/itemlist" name="itemSelectForm" type="jp.co.flsi.lecture.struts.ItemListAction" scope="request" input="/itemSelect.jsp">
      <forward name="success" path="/itemList.jsp"/>
    </action>

という行のaction pathの"/itemlist"という値を指しています。


次に、

      addRequestParameter("keyword", "製品001");
      addRequestParameter("categoryNum", "00001");

という行は、Webページから入力されるパラメーターのうち、"keyword"という
パラメーターには"製品001"という値を、また、"categoryNum"というパラメーター
には"00001"という値を設定するものです。

StrutsTestCaseでは実際にはWebページを開かずに、擬似的にWebページからデータ
が入力されたかのように見せかけますので、そのために上記のようにaddRequestParameter()
というメソッドを使って、入力するデータを指定することになっているのです。


続いて、

      actionPerform();

というメソッドは、実際にActionクラスを呼び出して実行を行うためのメソッド
ですが、先ほどの構成情報の

    <action path="/itemlist" name="itemSelectForm" type="jp.co.flsi.lecture.struts.ItemListAction" scope="request" input="/itemSelect.jsp">
      <forward name="success" path="/itemList.jsp"/>
    </action>

の部分から取り出した情報を元に、Actionクラスの実行に必要なオブジェクトを
予め自動的に生成しておいてからActionクラスのexecute()メソッドを自動的に
呼び出すことになります。
たとえば、上の"itemSelectForm"に対応するActionFormオブジェクトを生成し、
そのオブジェクトに先ほどのパラメーターの値("keyword"の値は"製品001"、
"categoryNum"の値は"00001")を設定したものをexecute()メソッドの引数
に渡すといった作業が自動的に行われます。


次に、

      verifyForward("success");

というメソッドは、Actionクラスを実行した後、forwardの値が"success"に
なったかどうかを検証するものです。forwardの値が"success"以外の値になる
ことを確認したい場合は"success"以外の該当する値をこの引数に指定します。

JUnitでは、テスト結果がOKかどうかを判定するためにassertで始まるメソッ
ド名のメソッドがたくさん用意されています(忘れた人はvol.161を復習のこと)
が、それと同様に、StrutsTestCaseではテスト結果を判定するためのメソッド
としてverifyで始まるメソッド名のメソッドがたくさん用意されています。
このverifyForward()および下記のverifyForwardPath()というメソッドが
その例となります。
もちろんJUnitのassertで始まるメソッド名のメソッドも同様に使用することが
できます。(StrutsTestCaseはJUnitを拡張したものですから、JUnitのAPIも
使用できます。)


続いて

      verifyForwardPath("/itemList.jsp");

は、Actionクラスを実行した後、forwardのpathとして"/itemList.jsp"が使われた
かどうかを検証するものです。
上記のstruts-config.xmlファイルの中では
      <forward name="success" path="/itemList.jsp"/>
というように指定していましたから、このActionクラスの実行結果のforwardの
値が"success"であればforwardのpathとして"/itemList.jsp"が使われるはず
ですので、それを検証しているものです。


あと、

      Vector<Item> itemList2 = (Vector<Item>) getRequest().getAttribute("itemList");

の中のgetRequest()というメソッドは、HttpServletRequestオブジェクトを取り
出すためのメソッドです。StrutsTestCaseは、Actionクラスのexecute()メソッド
を実行する前にHttpServletRequestオブジェクトを擬似的に生成してくれてい
ます(それがexecute()メソッドに引数(request)として渡されている)が、
そのrequestオブジェクトをgetRequest()メソッドで取り出すことができます。

ItemListActionのexecute()メソッドの中ではrequestオブジェクトに対して、

request.setAttribute("itemList", itemList);

というコードを実行していますね。これに対して、getRequest().getAttribute("itemList")
というコードでそのitemList(これはVector<Item>型のオブジェクト)を取り出して
いるのです。そして、このitemListを次の行

      assertEquals(itemList.get(0).getNum(), itemList2.get(0).getNum());

で検証しようという訳です。

このassertEquals()というメソッドは、JUnitのメソッドですね。
忘れた人はvol.161を復習して下さい。
なお、この行が何を検証しているのかについては、自力で解読してみて下さい。


最後の

      verifyNoActionErrors();

は、Actionクラスの実行で一切エラー・メッセージが出なかったことを検証する
メソッドです。逆にエラー・メッセージが出ることを確認したいテストの場合は
代わりにverifyActionErrors()というメソッドを使うことになります。



他にもverifyで始まるメソッドはたくさんありますが、こういったStrutsTestCase
のAPIの詳細については、

http://strutstestcase.sourceforge.net/api/index.html

などを参照して下さい。

また、StrutsTestCaseの概要については

http://strutstestcase.sourceforge.net/

などを参照して下さい。



この程度説明しておけば、あとは自力でソース・コードを読解できることと
思います。



では、単体テストを行ってみましょう。

プロジェクト・エクスプローラーの中の「StrutsShop」(プロジェクト)配下の
「Javaリソース: src」配下のjp.co.flsi.lecture.struts(パッケージ)配下の
ItemListActionTest.javaを右クリックし、「実行」→「JUnitテスト」を
選択します。

すると、「コンソール」タブ配下にログが出力され、「JUnit」タブ配下に
テスト結果が出力されますね。

このテスト結果の見方はJUnitの使い方で説明した通りですので、忘れた人は
vol.161を復習して下さい。


テスト結果はOK(緑色)になりましたでしょうか。


では、他の入力データを指定した場合のテスト・メソッドも追加
(例えば"keyword"にありえない製品名を指定した場合のテスト・メソッドを
testExecuteActionMappingActionFormHttpServletRequestHttpServletResponse2
というメソッド名で作成する。この場合、itemListは空っぽになるはずなので、
itemListのsize()が0になることを検証する)してテストしてみて下さい。
これは読者への自由課題としておきます。


こういったStrutsTestCaseによるテストを行うことによって、ActionFormと
Actionクラスとstruts-config.xmlの動作確認を行うことができます。



◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆ ◆


(次回に続く)



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2010 Future Lifestyle Inc. 不許無断複製