Strutsアプリケーションのテスト自動化
ServletTestCaseの拡張であるCactusStrutsTestCaseを使用して,Strutsを使用したWebアプリケーションのテストを自動化に挑戦してみた.
Cactusの基本的なテスト方法では,TestCase内にてServletをnewして,そのメソッドをテストした.ところがStrutsアプリケーションをテスト対象とすると,以下のような問題や要望が出てくる.
- Servletをnewしたいが,その対象は(大抵)ActionServletで,newして初期化する方法がなんだか面倒臭そうな気がする.
- 何らかの方法でActionServletが起動したとして,目的のアクションをテストするために,Strutsのstruts-config.xmlによる設定等の情報をTestCase内でも使用したい.
- ActionErrorsの検証等,Strutsにある程度特有だが,Strutsアプリケーションのテストにおいてはパターン化できそうなAssertメソッドが欲しい.
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;
};

