DATE : 2008/10/19 (Sun)
Hudson では、Java 以外の言語で作られたプロジェクトの継続的インテグレーションを行うことができます。特に、テスト結果のログを JUnit 形式の XML で出力できる場合、テスト結果の管理もできるので便利です。本記事では、JSUnit を用いてユニットテストを行っている JavaScript プロジェクトを Hudson で管理させる方法について記します。JavaScript プロジェクトは、すでに Hudson に登録できている状態だとします。本記事で使用した Hudson のバージョンは 1.255 で、使用したブラウザは Firefox 3.0.3、JSUnit は 2.2alpha11 です。標準の状態では、Firefox 3 で JSUnit は動きません。その場合は、「JSUnit を Firefox 3 で動作させるメモ」を参考にしてください。
本記事では、実行用のコードが main フォルダ、ユニットテスト用のコードが test フォルダに分けて配置されていることを前提にしています。また、JSUnit 本体は test フォルダに収められているとします。
常用している Firefox プロファイルでテストを行う場合
JSUnit の実行に開発専用のプロファイルを用いず、常用しているプロファイルを使用している場合は、JSUnit 付属の build.xml が使用できます。しかし、JSUnit から出力されるログの形式は JSUnit 独自の形式なので、Hudson でテスト結果を管理するには JUnit 形式のものに変換しなければなりません。そこで、Billy Reisinger 氏が作成されたXSLTを使用して、変換を行います。「JSUnit XML to JUnit XML」から「jsunit_to_junit.xsl」をダウンロードして、テスト用フォルダに配置します。
JSUnit Server から standalone_test を実行した後、JSUnit 形式のログファイルを JUnit 形式に変換する Ant スクリプトは次の通りです。なお、以下のスクリプトでテスト環境の設定を行うため、JSUnit 付属の build.xml の設定を行う必要はありません。また、複数のブラウザでユニットテストを行う場合は、JSUnit 付属の build.xml を呼び出す部分のスクリプトを修正してください。hudson.WORKSPACE プロパティは、Hudson から提供される環境変数で、Hudson の上のプロジェクトのワークスペースフォルダを表します。以下の Ant スクリプトでは、ログファイルを test/logs に名前で出力します。この Ant スクリプトは、「Ant の呼び出し」→「高度な設定」→「ビルドファイル」にそのファイルのパスを指定するだけで使えます。
<?xml version="1.0" encoding="utf-8"?>
<project name="JSUnitForHudson" default="test" basedir=".">
<description>
Hudson 上で JSUnit によるユニットテストを行う。
</description>
<property environment="hudson"/>
<!-- プロジェクトのホームディレクトリ -->
<property name="home"
location="${hudson.WORKSPACE}/sample"/>
<!-- テスト対象のページ -->
<property name="testPage"
location="${home}/test/testsuite.html"/>
<!-- JSUnit の動作するポート番号 -->
<property name="jsunitPort"
value="8090"/>
<!-- Firefox のパス -->
<property name="firefox"
location="C:\Program Files\Mozilla Firefox\firefox.exe"/>
<!-- JSUnit のホームディレクトリ -->
<property name="jsunitHome"
location="${home}/test/jsunit"/>
<!-- ログを出力するディレクトリ -->
<property name="logsDirectory"
location="${home}/test/logs"/>
<!-- JSUnit 形式のログファイルを JUnit 形式のログファイルに変換する XSLT -->
<property name="logTransrator"
location="${home}/test/jsunit_to_junit.xsl"/>
<!-- TestRunner -->
<property name="testRunner"
location="${jsunitHome}/testRunner.html"/>
<!-- JSUnit Server を起動する build.xml -->
<property name="buildScript"
location="${jsunitHome}/build.xml"/>
<target name="test">
<mkdir dir="${logsDirectory}"/>
<delete includeemptydirs="true">
<fileset dir="${logsDirectory}" includes="**/*"/>
</delete>
<makeurl file="${testRunner}" property="testRunnerURL"/>
<ant antfile="${buildScript}" dir="${jsunitHome}" target="standalone_test">
<property name="browserFileNames" value="${firefox}"/>
<property name="port" value="${jsunitPort}"/>
<property name="logsdirectory" location="${logsDirectory}"/>
<property name="url" value="${testRunnerURL}?testPage=${testPage}"/>
</ant>
<xslt basedir="${logsDirectory}" destdir="${logsDirectory}"
style="${logTransrator}">
<mapper type="glob" from="JSTEST-*.xml" to="JSTEST-*.junit.xml" />
</xslt>
</target>
</project>
あとは、「ビルド後の処理」の「JUnitテスト結果の集計」にチェックを入れ、「テスト結果 XML」に出力されるログファイルのパターンを記述すれば完了です。「<ログが出力されるフォルダ>/JSTEST-*.junit.xml」を指定してください。
専用のプロファイルを用いる場合(Windows 向け)
JSUnit 専用のプロファイルを作る
専用のプロファイルを用いる場合は、まず JSUnit 専用のプロファイルを作成することをおすすめします。Firefox 3 の場合、常用以外のプロファイルで起動する場合、プロファイル名以外に「-no-remote」オプションを付けて起動しなければなりません。しかし、すでにそのプロファイルで Firefox 3 が立ち上がっている場合、「-no-remote」オプションを付けると、すでに Firefox 3 が立ち上がっていることを示すメッセージが表示され、新たに起動できません。そのため、テスト実行時のみに起動し、テストが終われば終了できる JSUnit 専用のプロファイルが必要となります。ここでは、そのプロファイル名が「jsunit」であると仮定して話を進めます。
JSUnit でテスト終了時に Firefox を自動的に閉じる設定を行っている場合は、Firefox の再起動時に、前回終了時に読み込んでいたページを復元するか聞かれる場合があります。そのため、「about:config」から次の設定を全て false に設定します。
- browser.sessionstore.resume_from_crash
- browser.sessionstore.enabled
Ant スクリプトから専用のプロファイルの Firefox を起動
JSUnit 付属の build.xml では、コマンドラインオプションを付けて Firefox を起動できません。そこで、バッチファイルを用意し、オプションを付けて Firefox を起動する Ant スクリプトを呼び出すようにします。バッチファイル単体でも起動は可能ですが、起動するコマンドの前に他の文が含まれていると、うまく動作しない場合があるためです。
Ant スクリプトは次のようになります。JSUnit のログを JUnit 形式のログに変換するため、Billy Reisinger 氏が作成されたXSLTを「JSUnit XML to JUnit XML」からダウンロード(jsunit_to_junit.xsl)して、テスト用フォルダに配置しておいてください。
テスト終了時に Firefox を強制終了させている点に注意してください。通常では、ユニットテスト終了時に JSUnit Server が Firefox を終了させるのですが、バッチファイルやスクリプトなどから Firefox を起動した場合は JSUnit Server から終了できません。そこで Ant スクリプトから、テストに使用した Firefox を終了させています。Ant スクリプトからはテストに使用した Firefox のプロセス番号を入手できないので、Firefox のウィンドウのタイトルから、終了する Firefox を特定しています。そのため、テスト以外の用途の Firefox も巻き込まれて終了されてしまう場合があります。これを防ぐ場合は、closeFirefoxAfterTestRuns プロパティを false に設定してください。ただし、テストに使用した Firefox も手動で閉じる必要があります。
複数のブラウザでユニットテストを行う場合は、Ant スクリプト中の、JSUnit 付属の build.xml を呼び出す部分を修正してください。hudson.WORKSPACE プロパティは、Hudson から提供される環境変数で、Hudson の上のプロジェクトのワークスペースフォルダを表します。以下の Ant スクリプトでは、ログファイルを test/logs に名前で出力します。この Ant スクリプトは、「Ant の呼び出し」→「高度な設定」→「ビルドファイル」にそのファイルのパスを指定するだけで使えます。
<?xml version="1.0" encoding="utf-8"?>
<project name="JSUnitForHudson" default="test" basedir=".">
<description>
Hudson 上で JSUnit によるユニットテストを行う。
</description>
<property environment="hudson"/>
<!-- プロジェクトのホームディレクトリ -->
<property name="home"
location="${hudson.WORKSPACE}/trunk"/>
<!-- テスト対象のページ -->
<property name="testSuite"
location="${home}/test/TestSuite.html"/>
<!-- JSUnit の動作するポート番号 -->
<property name="jsunitPort"
value="9091"/>
<!-- Firefox を起動するバッチファイル -->
<property name="firefox"
location="${home}/test/hudson_firefox.bat"/>
<!-- JSUnit のホームディレクトリ -->
<property name="jsunitHome"
location="${home}/test/jsunit"/>
<!-- ログを出力するディレクトリ -->
<property name="logsDirectory"
location="${home}/test/logs"/>
<!-- JSUnit 形式のログファイルを JUnit 形式のログファイルに変換する XSLT -->
<property name="logTransrator"
location="${home}/test/jsunit_to_junit.xsl"/>
<!-- テスト終了後に Firefox を終了するかどうか。 -->
<!-- ウィンドウのタイトルが ${closingFirefoxTitle} のみのものを終了する -->
<property name="closeFirefoxAfterTestRuns"
value="true"/>
<!-- TestRunner -->
<property name="testRunner"
location="${jsunitHome}/testRunner.html"/>
<!-- JSUnit Server を起動する build.xml -->
<property name="buildScript"
location="${jsunitHome}/build.xml"/>
<!-- 終了させる Firefox の、ウィンドウのタイトル -->
<property name="closingFirefoxTitle"
value="Mozilla Firefox"/>
<target name="test">
<mkdir dir="${logsDirectory}"/>
<delete includeemptydirs="true">
<fileset dir="${logsDirectory}" includes="**/*"/>
</delete>
<makeurl file="${testRunner}" property="testRunnerURL"/>
<ant antfile="${buildScript}" dir="${jsunitHome}" target="standalone_test">
<property name="browserFileNames" value="${firefox}"/>
<property name="port" value="${jsunitPort}"/>
<property name="logsdirectory" location="${logsDirectory}"/>
<property name="url" value="${testRunnerURL}"/>
</ant>
<xslt basedir="${logsDirectory}" destdir="${logsDirectory}"
style="${logTransrator}">
<mapper type="glob" from="JSTEST-*.xml" to="JSTEST-*.junit.xml" />
</xslt>
<antcall target="_closeFirefox"/>
</target>
<target name="_closeFirefox" if="closeFirefoxAfterTestRuns">
<exec executable="TASKKILL" osfamily="Windows">
<arg value="/IM"/>
<arg value="firefox.exe"/>
<arg value="/FI"/>
<arg value="WINDOWTITLE eq ${closingFirefoxTitle}"/>
<arg value="/F"/>
</exec>
</target>
</project>
Firefox を起動する Ant スクリプトを、呼び出すバッチファイル(hudson_firefox.bat)は次の通りです。Firefox を起動する Ant スクリプトの名前は hudson_firefox.xml としています。
ant -f hudson_firefox.xml REM Firefox を起動するためのバッチファイル jsunit\build.xml から呼ばれる。 REM 他の文が含まれているとそこで動作が止まってしまうため、本バッチファイルでは REM ant スクリプトを起動する。 REM 本コメントが ant の実行より上にあると、ant が実行されない場合がある。
Firefox を起動する Ant スクリプト(hudson_firefox.xml)は、次の通りです。各プロパティは、各自の環境に合わせて設定してください。
TestRunner の URL を Ant スクリプト内で生成している点に注意してください。JUnit Server で TestRunner の URL が生成されて、Firefox を起動するバッチファイルにその URL に渡されるのが本来の流れなのですが、「&」や「=」はバッチファイルの引数として使用できません。そのため、Ant スクリプトで URL を生成しています。
<?xml version="1.0" encoding="utf-8"?>
<project name="launchFirefox" default="test" basedir=".">
<description>
Firefox を専用のプロファイルで起動してユニットテストを行う。
hudson_firefox.bat から呼び出される。
</description>
<import file="build.xml"/>
<!-- Firefox のパス -->
<property name="firefox_exe"
location="C:\Program Files\Mozilla Firefox\firefox.exe"/>
<!-- テストを実行する Firefox プロファイル -->
<property name="profileName"
value="jsunit"/>
<target name="test">
<makeurl file="${testRunner}" property="testRunnerURL"/>
<exec executable="${firefox_exe}">
<arg value="-no-remote"/>
<arg value="-P"/>
<arg value="${profileName}"/>
<arg value="${testRunnerURL}?testPage=${testSuite}&autoRun=true&submitResults=localhost:${jsunitPort}/jsunit/acceptor"/>
</exec>
</target>
</project>
あとは、「ビルド後の処理」の「JUnitテスト結果の集計」にチェックを入れ、「テスト結果 XML」に出力されるログファイルのパターンを記述すれば完了です。「<ログが出力されるフォルダ>/JSTEST-*.junit.xml」を指定してください。
参考文献
- Re: Automatically launch browsers in the background
- Fx起動時にでる「前回のセッションの復元」表示をなくす方法?
- "Not Recognized" Error Using PKZIP.EXE with Ampersand (&) Switch
- Equal-Sign Characters as Arguments in Batch Files
