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
DATE : 2008/10/16 (Thu)
はじめに
Hudson では、Java 以外の言語で作られたプロジェクトの継続的インテグレーションを行うことができます。特に、テスト結果のログを JUnit 形式の XML で出力できる場合、テスト結果の管理もできるので便利です。本記事では、unittest モジュールを用いてユニットテストを行っている Python プロジェクトのテスト結果を Hudson で管理させる方法についてメモします。Python プロジェクトはすでに Hudson に登録できている状態だとします。Hudson でプロジェクトを管理する方法については、「Hudsonを使ったアジャイルな開発入門」(川口耕介、gihyo.jp)を参考にしてください。本記事で使用した Hudson のバージョンは 1.255、Python のバージョンは 2.6 です。
unittest モジュールの結果から、JUnit 形式のログファイルを出力
unittest モジュールは、標準では JUnit 形式のログを出力しません。そこで、Sebastian Rittau 氏が開発された XML Test Runner for PyUnit を使用します。「XML Test Runner」から xmlrunner.py をダウンロードし、プロジェクトのフォルダか <Python のインストールフォルダ>\Lib に配置します。次に、テストを実行するスクリプトを作成します。例えば、test_on_hudson.py というスクリプトに以下のように記述します(「<...>」の部分は、各自のテスト用スクリプトに応じて置き換えてください)。なお、以下のコードは「Hudson embraces Python」(Redsolo)のものを参考にしています。対象とする XML Test Runner for PyUnit は、2007-11-12 版のものです。
import sys import unittest import xmlrunner import <テスト対象モジュール> if __name__ == "__main__": suite = unittest.TestSuite([ unittest.TestLoader().loadTestsFromTestCase(<テストケース>), <その他テストケース> ]) runner = xmlrunner.XMLTestRunner(sys.stdout) runner.run(suite)
テストを実行するスクリプトが出来上がったら、Hudson に登録しておきます。
ビルド手順にユニットテストの起動を指定
プロジェクトページの「設定」→「ビルド手順の追加」から、ユニットテストを起動するスクリプトを実行します。例えば、「Windows バッチコマンドの実行」からユニットテストを起動する場合は、次のようになります。
python <ワークスペースからの test_on_hudson.py のパス> > testlog.xml
「Ant の呼び出し」の場合の Ant スクリプトは、次のようになります。各プロパティは各自のプロジェクトに応じて置き換えてください。hudson.WORKSPACE プロパティは、Hudson から提供される環境変数で、Hudson の上のプロジェクトのワークスペースフォルダを表します。以下の Ant スクリプトでは、ログファイルを <プロジェクトのワークスペース>/logs に「PYUNIT-<ビルドタグ>.xml」という名前で出力します。この Ant スクリプトは、「Ant の呼び出し」→「高度な設定」→「ビルドファイル」にこのファイルのパスを指定するだけで使えます。
<?xml version="1.0" encoding="utf-8"?> <project name="unittestOnHudson" default="test" basedir="."> <description> Python プロジェクトのユニットテストを Hudson 上で実行する。 </description> <property environment="hudson"/> <!-- テスト用コードのパス --> <property name="testCode" location="${hudson.WORKSPACE}/sample/test_on_hudson.py"/> <!-- ログを出力するディレクトリのパス --> <property name="logsDirectory" location="${hudson.WORKSPACE}/logs"/> <!-- ログファイルの名前 --> <property name="logName" value="PYUNIT-${hudson.BUILD_TAG}.xml"/> <target name="test"> <mkdir dir="${logsDirectory}"/> <delete includeemptydirs="true"> <fileset dir="${logsDirectory}" includes="**/*"/> </delete> <exec executable="python" output="${logsDirectory}/${logName}"> <arg path="${testCode}"/> </exec> </target> </project>
あとは、「ビルド後の処理」の「JUnitテスト結果の集計」にチェックを入れ、「テスト結果 XML」に出力されるログファイルのパターンを記述すれば完了です。上記の「Windows バッチコマンドの実行」の場合は、「テスト結果 XML」に「testlog.xml」を、「Ant の呼び出し」の場合は「logs/PYUNIT-*.xml」を指定してください。
参考文献
DATE : 2008/10/13 (Mon)
はじめに
JavaScript 向けテスティングフレームワーク JSUnit は、現在のバージョン(2.2alpha11)では Firefox 3 上で動作しない場合があります。Firefox 3 では、ローカルにあるファイルを Firefox に読み込んだ際に、そのファイルからアクセスできるディレクトリに制限が設けられています。標準では、読み込んだファイルと同じディレクトリかそのサブディレクトリしかアクセスすることができません。テストを起動する TestRunner とテスト用のページとが別の階層のディレクトリにあると、TestRunner からテスト用のページにアクセスできなくなってしまいます。
Firefox 3 の「security.fileuri.strict_origin_policy」設定を false に変える
その制限を解除するために「security.fileuri.strict_origin_policy」設定を変更します。この設定は読み込まれたローカルのファイルからアクセスできるディレクトリの制限を設定するもので、標準では同じディレクトリかそのサブディレクトリ(true)に設定されています。そこで、「about:config」を開き、「security.fileuri.strict_origin_policy」設定を false に設定します。こうすることで、ローカルのファイルからアクセスできるディレクトリに制限がなくなります。この結果、TestRunner とテスト用のページとが別の階層のディレクトリにあっても JSUnit を使用できるようになります。
ただし、この設定の変更は Firefox 3 のセキュリティ設定を緩めてしまうことになります。余裕があれば、開発作業用のプロファイルを作成することをおすすめします。
テスト対象ページを testPage パラメータで指定する
TestRunner にあるファイルを選択するボタンも、Firefox 3 上ではうまく動作しません。その場合、TestRunner の URL の後に、「?testPage=C:/abcd/efg.html」(「/」は「\」でもかまいません)という風に testPage パラメータを付けて、そこでテストページ、またはテストスイートのページを指定します。
注意
なお、JSUnit はテストメソッドの間違いがあれば指摘してくれますが、テストページの HTML の記述が間違えていた場合やテストの構成に失敗していた場合には何も警告を出しません。上記の操作を行った上でも何も変化がない場合は、テストコードを HTML 部分も含めてチェックしてください。
(;^ω^)始めの問題が解決した後に、テストコードの構成の間違いでまたしばらく時間を費やしてしまいました。
参考文献
DATE : 2008/09/19 (Fri)
Twitter を使用して早1ヶ月以上が経ちました。初めはインスタントメッセンジャー(以下、IM)経由で使用していたのですが、Twitter 側の障害により、Web のインタフェースを使わなければならない状況になってしまいました。
Web のインタフェースも使い心地は悪くないのですが、IM を使っていた頃と違って、フォロー数、被フォロー数が常に目に入るようになってしまいました。いくら気にしないように心がけていても、やはり数字の増減は気になってしまいます。
ということで、フォロー数、被フォロー数をウェブのインタフェースで非表示にする Firefox 3 用のユーザスタイルシートを書いてみました。IM が完全に復活するまでの暫定的なものなので、フォロー、被フォローへのリンクも丸ごと非表示にします。
なお、ユーザスタイルシート中の your_name の部分は、Twitter での自分のユーザ名に置き換えてください。
更新履歴
- 2008/09/19
- Twitter のデザイン変更で「設定」→「デザイン」の部分に表示されてしまう問題に対処。
- 2008/07/25
- 「ダイレクトメッセージ」ページでの非表示化が抜けていたのを修正。
- 2008/06/29
- 「お気に入り」ページでの非表示化が抜けていたのを修正。
- 2008/06/25
- 公開。
Firefox 3 用ユーザスタイルシート
/* Version : 2008/09/19 */ @-moz-document url-prefix(http://twitter.com/your_name), /* 自分のユーザ名を含むページ */ url-prefix(https://twitter.com/your_name), url-prefix(http://twitter.com/home), url-prefix(http://twitter.com/replies), url-prefix(http://twitter.com/account), url-prefix(http://twitter.com/public_timeline), url-prefix(http://twitter.com/favorites), url-prefix(http://twitter.com/direct_messages), url-prefix(https://twitter.com/home), url-prefix(https://twitter.com/replies), url-prefix(https://twitter.com/account), url-prefix(https://twitter.com/public_timeline), url-prefix(https://twitter.com/favorites), url-prefix(https://twitter.com/direct_messages) { a[href$="/followers"], a[href$="/friends"], #following_count, #followingcount, #follower_count, #followers_count { display : none; } }
DATE : 2008/09/02 (Tue)
高岡市美術館の企画展で「高岡開町400年記念プレイベント ピカソ展 -天才・もうひとつの顔-」が開催されていたので、見に行ってきました。また、万葉の杜にある「ドラえもんの散歩道」も見に行ってきました。
高岡駅の北に出て、そのまま北に商店街を進むと、徒歩約5分程度で万葉の杜が右手に見えてきました。小さく静かな公園で、正面から奥にかけてドラえもん、のび太、しずか、スネ夫、ジャイアンと、「ドラえもん」のキャラクターの像の乗った柱が続いています。また入口から少し入ったところにある左側の茂みには、「ドラえもん」作者、藤子・F・不二雄のメッセージが刻まれた銅板が置かれていました。平日の午前中ともあって、到着した当初は人もほとんどいません。けれど、万葉の杜を歩き回ったり、写真を撮っていたりするうち、私の他にも「ドラえもんの散歩道」の写真を撮って行かれる方が現れました。親子連れの方も万葉の杜にやってきて、ドラえもんの像に目を輝かせていたりと、とても和やかな雰囲気に包まれていました。
万葉の杜を出て大和高岡店の方へ道なりに歩いていくと、広大な森と堀に囲まれた高岡古城公園が見えてきました。その高岡古城公園を過ぎると、高岡市美術館にたどり着きます。高岡市美術館には、かつて一度、「THE ドラえもん展」を見に行ったことがありました。「THE ドラえもん展」は2004年7~9月だったため、4年ぶりに訪れたことになります。
平日のため人も少ないと思っていたのですが、意外にも来場者が多く、驚きました。まさに列を作って歩いていく状態で、なかなかじっくりとピカソを鑑賞できる雰囲気ではなかったものの、ときおり感嘆の声が上がったり、自分なりの解釈を話し合っている声が聞こえてきたりと、とても良い雰囲気でした。会場に展示されていたのは、ピカソの陶芸に始まり、版画、油彩といった顔ぶれでした。非常に単純な線描から描かれる迫力には心を揺さぶられました。ぱっと見ると子供の描いたような絵なのですが、無駄のない線や点の数々は、さすがの一言に尽きます。また、皿の表には簡単な模様だけ描いておいて、裏に細かく描かれた作品などもあり、遊び心が垣間見えて微笑ましくありました。作品とともに、ピカソの制作・生活風景を撮影した写真も飾られており、どのような雰囲気の中で作品作りに取り組んでいたのかも感じられ、非常に面白かったです。
ピカソを美術館で見るのは初めてでしたが、媒体や表現技法を様々に変えながらも亡くなる直前まで創作活動を行った点には頭が下がる思いでした。芸術作品を鑑賞する際、どうしても絵は絵として、陶芸は陶芸として、特定の表現技法は表現技法として見がちなのですが、ピカソにとって見れば表現したいものをただ追い求めた結果だったのかもしれません。