SHOEISHA iD

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

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

特集記事

CactusでWebアプリケーションをテストする

サーバーサイドのJavaコードの単体テストを行う


  • X ポスト
  • このエントリーをはてなブックマークに追加

Cactusによるテストコードの記述方法

 まずはテストしたいサーバーサイドコードに応じて、Cactusのテストケースを拡張した対応するテストクラスを作成します。拡張されるテストケースには次の3種類があります。

Cactusが用意している基底テストケースクラス
クラス名 対象となるテストケース
ServletTestCase Servlet
JspTestCase JSP、カスタムタグ
FilterTestCase フィルタ

 上の表のテストケースクラスを継承させる形でテストケースを作成していきますが、CactusはJUnitを拡張しているだけあって、テストコードの書き方はJUnitとほとんど同じです。ただ、requestresponseなどのHTTP特有の機能もテストできるように拡張してある点が異なります。テストはbeginXXX()(前処理)→testXXX(テスト)→endXXX()(後処理)のメソッド順で行われますが、beginXXXにはリクエスト情報を設定するためのorg.apache.cactus.WebRequestクラスが、endXXXには、レスポンス情報を取得するためのorg.apache.cactus.WebResponseクラスが第1引数で唯一の引数として渡されます。なお、WebRequestオブジェクトにはrequestを設定するための次のようなメソッドが存在します。

WebRequestオブジェクトの主要なメソッド
メンバ名 概要
addCookie(java.lang.String theName, java.lang.String theValue) クッキーの追加
addHeader(java.lang.String theName, java.lang.String theValue) ヘッダーの追加
addParameter(java.lang.String theName, java.lang.String theValue, java.lang.String theMethod) (GET or POST)パラメータの追加
setContentType(java.lang.String theContentType) content-typeの追加

 さらにWebResponseでは、responseから情報を取得するために次のようなメソッドが存在します。

WebResponseオブジェクトの主要なメソッド
メンバ名 概要
getStatusCode() HTTPステータスコードを取得
getCookie(java.lang.String theName) クッキーの取得
getInputStream() responseをストリームで取得

 また、Cactusでは本来サーブレットコンテナが生成するさまざまなオブジェクトをRedirector Proxyによって暗黙オブジェクトとして生成し、テストコードで設定/取得/実行ができるようにしています。主によく使われる暗黙オブジェクトには次のようなものがあります。

主な暗黙オブジェクト
対象となるテストケース インスタンス名 暗黙オブジェクトクラス 継承クラス
すべて request org.apache.cactus.server
.HttpServletRequestWrapper
javax.servlet.http
.HttpServletRequest
すべて response javax.servlet.http
.HttpServletResponse -
Servlet,JSP config org.apache.cactus.server
.ServletConfigWrapper
javax.servlet.ServletConfig
Servlet,JSP session javax.servlet.http.HttpSession -
JSP pageContext org.apache.cactus
.server.PageContextWrapper
javax.servlet.jsp.PageContext
Filter config org.apache.cactus.server
.FilterConfigWrapper
javax.servlet.FilterConfig

 次に、それぞれの基底クラスを拡張した実際のテストクラスを解説します。

Servletのテストコード記述方法

 Servletのテストコードの記述について解説します。具体的には一つのテストを記述した場合、以下のコードのようになります。

TestHelloServlet.java
package to.msn.wings.cactussample;

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.cactus.ServletTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.WebResponse;

/**
 * Tests of the <code>HelloServlet</code> servlet class.
 *
 * @version $Id: TestHelloServlet.java 238816 2004-02-29 16:36:46Z vmassol $
 */
public class TestHelloServlet extends ServletTestCase
{


    public TestHelloServlet(String theName)
    {
        super(theName);
    }

    public void beginHello(WebRequest request){
        request.addParameter("name", "ken");
    }

    public void testHello() throws IOException,ServletException
    {
        HelloServlet servlet = new HelloServlet();
        servlet.service(request, response);
        assertEquals("ken", request.getAttribute("name"));
    }

    public void endHello(WebResponse theResponse)
    throws IOException
    {
        //HTTPステータスコード-正常
        assertEquals(200, theResponse.getStatusCode());
    }

}

 1つのテストコードは、beginXXXtestXXXendXXXの3つのメソッドから構成されます。XXXにはテストの名称を入れます。基本的にはbeginXXXメソッドでリクエストパラメータの設定をし、testXXXメソッドでサーブレットオブジェクトを生成して実行し、endXXXメソッドで実行結果を確認するという流れになります。

 テスト対象のServletでは、request.getParameterで受け取った値を、request.setAttributeで設定するという処理を行っているため、beginXXXメソッドで設定した値をendXXXメソッドで正しく受け取れているかというテストを行っています。

 なおCactusの各テストケースクラスは、JUnitのクラスを継承しているため、assertXXXメソッドは同一のものが使用できます。以下に簡単に表にまとめました。

assertXXXメソッドの種類
メソッド名 概要
assertEquals 2つの変数が同一のオブジェクト(またはプリミティブ値)であるかどうかを判定
assertTrue boolean値がTrueであるかどうかを判定
assertSame 2つの変数が同一の参照オブジェクトであるかを判定

Filterのテストコード記述方法

 Filterのテストコード記述方法は基本的にServletと同じです。beginXXXtestXXXendXXXの3つのメソッドで構成され、リクエストの設定、実行、結果の確認を行います。また、次のサンプルプログラムのようにtestXXXメソッドにすべてを記述することもできます(Servletのテストコードでも同様にできます)。このテストコードでは、テスト対象のフィルタクラスを生成/実行し、characterEncodingをUTF-8に正しく設定しているかどうかをテストしています。

TestSetEncodingFilter.java
package to.msn.wings.cactussample;

import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.cactus.FilterTestCase;

public class TestSetEncodingFilter extends FilterTestCase
{
    
    public void testEncoding()throws ServletException,IOException{
        SetEncodingFilter filter = new SetEncodingFilter();
        filter.init(config);
        filter.doFilter(request, response, filterChain);
        assertEquals("UTF-8",request.getCharacterEncoding());
    }

}

JSP、カスタムタグのテストコード記述方法

 JSP、カスタムタグのテストコードについても、記述方法は基本的にServlet、Filterと同じです。JSPはrequest.setAttribute()した後に、暗黙オブジェクトpageContextincludeメソッドでJSPを読み込む処理を行います。読み込んだ結果はresponseに格納されるので、response.getTextで、指定されたHTMLタグが存在するかを検証しています。

TestHelloJSP.java
package to.msn.wings.cactussample;

import org.apache.cactus.JspTestCase;
import org.apache.cactus.WebResponse;

public class TestHelloJSP extends JspTestCase {


        public TestHelloJSP(String theName)
        {
            super(theName);
        }

    
        public void testHelloJSP() throws Exception
        {
            request.setAttribute("name","ken");
            this.pageContext.include("/hello.jsp");

        }

        public void endHelloJSP(WebResponse res) throws Exception
        {
            int index = res.getText().indexOf(
                "<div id=\"hello\">Hello ken</div>");
            assertEquals(false,index < 0);
        }


}

 また、以下のカスタムタグのテストコードでは、request.setAttribute()した後に、HelloタグのインスタンスのdoStartTag()を呼び出します。その後、その結果をresponse.getTextで受け取って正しい値を生成しているか検証しています。

TestHelloTag.java
package to.msn.wings.cactussample;

import javax.servlet.jsp.tagext.Tag;

import org.apache.cactus.JspTestCase;
import org.apache.cactus.WebResponse;

public class TestHelloTag extends JspTestCase
{


        public TestHelloTag(String theName)
        {
            super(theName);
        }


        private HelloTag tag;

        public void testHelloTag() throws Exception
        {
            this.tag = new HelloTag();
            this.tag.setPageContext(this.pageContext);
            this.request.setAttribute("name","ken");            
            int result = this.tag.doStartTag();
            assertEquals(Tag.SKIP_BODY, result);
        }

        public void endHelloTag(WebResponse theResponse)
        {
            assertEquals(theResponse.getText(), "Hello ken");
        }

}

テストの実行

 テストの実行にはいくつかの方法が存在します。EclipseにCactusのpluginであるCactusRunnerを入れてテストする方法や、antから実行する方法などです。今回はantでテストを実行し、テスト結果をコンソールから確認する方法と、ブラウザ上で確認する方法の2パターンを解説します。antでテストを実行するには「ant test」と実行してください。これで、次のようにテスト結果をコンソールに出力してくれます。

コンソール出力結果
コンソール出力結果

 また、テストを実行した際にXMLとしてテスト結果を出力するので、それをブラウザ上で確認することもできます。確認する画面は次のようなものになります。

ブラウザでのテスト結果確認
ブラウザでのテスト結果確認

 このテストの実行結果をXMLとして出力する処理は、「build.xml」の<junitreport>に記述されています。大量のテスト結果を見やすく確認したい場合には便利です。出力先を換えるには、<junitreport>todirを変更すればOKです。

まとめ

 本稿では、Cactusを利用したWebアプリケーションの自動テストについて解説しました。Junitを利用したことがあっても、Cactusまでは導入していない開発者の方は多いのではないでしょうか? 最初の設定がやや面倒ではありますが、基本的にはJUnitの拡張であり、JUnitに慣れてさえいれば、それほど学習コストもかかりません。最近では、ブラウザを介してJavaScriptでViewのテストをするSeleniumなど、さまざまなWebアプリケーションテストフレームワーク、ライブラリが出てきていますが、まずJUnitに慣れている方は、Cactusから導入してみてはいかがでしょうか? 本稿が導入のお役に立てれば幸いです。

参考資料

  1. Jakarta Cactus
  2. CactusRunner

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

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

WINGSプロジェクト 佐藤 真介(サトウ シンスケ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛...

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/494 2008/08/26 14:08

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング