ファイヤープロジェクト
Strutsアプリケーションのテスト自動化
2004-07-07T05:00+09:00   matsu
ServletTestCaseの拡張であるCactusStrutsTestCaseを使用して,Strutsを使用したWebアプリケーションのテストを自動化に挑戦してみた.
Cactusの基本的なテスト方法では,TestCase内にてServletをnewして,そのメソッドをテストした.ところがStrutsアプリケーションをテスト対象とすると,以下のような問題や要望が出てくる.
  • Servletをnewしたいが,その対象は(大抵)ActionServletで,newして初期化する方法がなんだか面倒臭そうな気がする.
  • 何らかの方法でActionServletが起動したとして,目的のアクションをテストするために,Strutsのstruts-config.xmlによる設定等の情報をTestCase内でも使用したい.
  • ActionErrorsの検証等,Strutsにある程度特有だが,Strutsアプリケーションのテストにおいてはパターン化できそうなAssertメソッドが欲しい.
これらの解決策として,servletunit.struts.CactusStrutsTestCaseがある.これはStrutsTestCase for JUnitというクラスライブラリ(?※)にある.StrutsTestCase for JUnitを使用すると,模擬環境におけるサーブレットのテストと,コンテナにデプロイした上でのサーブレットのテストが行え,その切替えはテストプログラムの基底クラスを切替えることで実現できるらしい.前者のための基底クラスがservletunit.struts.MockStrutsTestCaseで,後者のための基底クラスが本頁で試してみるCactusStrutsTestCaseである.
※ なんかよくわからんが,この辺が情報源か(ちょっと古いようだが日本語訳).
CactusStrutsTestCaseを拡張したテストプログラムを以下に示す.
これはFPのStrutsのコーナーにて作成したLookupDispathActionを使用したサンプルプログラムのためのテストプログラムである.テストプログラムには例によってtestで始まるメソッドを作成する.するとTestRunnerによって実行される.
    /**
     * command="plus"の場合のテスト
     */
    public void testPlus() {
テストメソッドではまずリクエストパラメータを設定する.
	// 設定
	addRequestParameter("param1", "100");
	addRequestParameter("param2", "200");
	addRequestParameter("command", "plus");
あとで裏でActionServletに処理が渡されるが,それによっていつものようにActionServletがActinFormを必要に応じてnewしたあと,リクエストパラメータを設定する.次にアクションを指定するために,リクエストパスを設定する.
	setRequestPathInfo("/SomeActions");
これで,/SomeActions.doを要求する./SomeActionsはもちろんstruts-config.xmlの要素actionに記述されていなければならない.より重要かつ基本的なことは,該当要素actionのアクションが,テストメソッド(ここではtestPlus)のテスト対象であるということである.ここまで準備ができれば,あとはActionServletに処理を依頼する.
	// executeの実行
	actionPerform();
このメソッドが終了して,テストメソッドに返ってきた時には,該当アクションが終了して,フォワード先,ActionForm,requestやsessionの状態が必要に応じて変更されている状態である.それらが正しく行われたかを以降で検証する.まずはフォワード先の検証である.
	// フォワード先の検証
	verifyForward("success");
	verifyForwardPath("/some_actions.jsp");
前者は該当Actionクラスのexecuteの返りのActionForwardのキーであり,後者はそのActionForwardのパスである.当然どちらもstruts-config.xmlと整合がとれているはずである.以下はテスト対象アクションのstruts-config.xmlの記述である.
    <action    path="/SomeActions"
               type="matsu.struts.sample.SomeActions"
	       scope="request"
	       name="MyActionForm"
	       parameter="command">
      <forward name="success" ← verifyForward("success");
                  path="/some_actions.jsp" ← verifyForwardPath("/some_actions.jsp");
      />
    </action>
ここではforwardが一つしかないので,例としてはあまり面白くないかもしれない.次にActionFormの状態を検証する.
	// ActionFormの検証
	MyActionForm form = (MyActionForm)getActionForm();
	assertEquals("100", form.getParam1());
	assertEquals("200", form.getParam2());
	assertEquals("300", form.getResult());
	assertEquals("plus", form.getCommand());
getActionFormで該当アクションのActionFormが取得できる.返り値ActionForm型なので,キャストする.あとはいつものassertメソッドでの検証である.最後にActionErrorsのチェックである.
	// ActionErrosの検証
	verifyNoActionErrors();
ここではエラーはないはずなので,verifyNoActionErrors()を使用した.エラーにキーがあるはずの場合には,以下のようにする.
	// ActionErrosの検証
	// キー"error.cmd.unknown"のエラーメッセージがあるハズ.
	verifyActionErrors(new String[]{"error.cmd.unknown"});
これでキー"error.cmd.unknown"でエラーが登録されていることを検証できる.以上のパターンで大体のStrutsアクションはテストできるのではないだろうか.また,ここではサンプルのテストプログラムの順番で説明を記述したが,設定,実行,検証の順番になっていれば,設定する順番や検証する順番は大体の場合任意に記述できる(念のため).
前節のサンプルから分かるように,Cactusによる基本パターンとは異なり,Strutsのテストの場合はテストプログラム内でServletをnewしない.StrutsのActionServletの起動(newと初期化)は(多分)それなりに面倒なので,普通に起動してリダイレクトする.したがってweb.xmlにはStrutsのための記述も必要である.今回のサンプルのためのweb.xmlを以下に示す.
このようにStrutsの基本的なweb.xmlとCactusの基本的なweb.xmlを合わせた内容となっている.
今回作成したサンプルを置いておく.これ.展開してlibの下にcactusのjarと StrutsTestCase for JUnitのjar(SourceForgeのstrutstest212-1.1_2.3.zip内にある)を置く.以下は動作確認時のjar一覧.
aspectjrt-1.1.1.jar         commons-lang.jar           servletapi-2.3.jar
cactus-1.6.1.jar            commons-logging-1.0.3.jar  some_actions.jar
cactus-ant-1.6.1.jar        commons-logging.jar        struts-legacy.jar
commons-beanutils.jar       commons-validator.jar      struts-sample.jar
commons-collections.jar     httpunit-1.5.4.jar         struts.jar
commons-digester.jar        jakarta-oro.jar            strutstest-2.1.2.jar
commons-fileupload.jar      junit-3.8.1.jar
commons-httpclient-2.0.jar  nekohtml-0.7.4.jar
以下でテスト用warファイル(※)が作成される.
ant buildwebtest
これをデプロイして,
ant webtest
で実行である.ただしcactus.properties.eucjpのcactus.contextURLは必要に応じて編集すること.
※ tldがないので普通にindex.jspにアクセスしようとするとJSPで怒られる.また,テスト用のsrc/webtest/ApplicationResources.properties.eucjpを使用する.テストプログラム記述を容易にするために,このファイルではbutton.cmd.*の値に日本語を使用していない.
私の環境(Debian GNU/Linux Woody,Tomcat4)ではサンプルを動かすためにセキュリティーポリシーを変更する必要があった.クリティカルな設定がよくわからなかったので,恥ずかしながら全開にした.以下を/etc/tomcat4/policy.d/01system.policyに追記した.
// For CactusStrutsTestCase
grant {
  permission java.security.AllPermission;
};
matsu(C)
Since 2002
Mail to matsu