読者です 読者をやめる 読者になる 読者になる

Jenkins で Jasmine

JavaScript CI Jenkins Jasmine

大変久しぶりにエントリを書いてみます。

JasmineJenkins で動かそうとしたら少しはまりました。
はまったので、メモ代わりに書いておきます。

Jasmine を Jenkins で動かすにあたり、以下の構成で動かすことに落ち着きました。

以下のものを採用しなかった理由も書いておきます。

  • rake jasmine:ci
    • ブラウザが必要になるので、重い
    • reporter を自由に変えられなさそうだった*1
  • PhantomJS
    • JavaScript を読み込むのに、 http:// じゃないとだめそうだった(file:// 形式が読めなさそうだった)
      • あまりちゃんと調べなかったので、実はできるかも。

さて、準備方法です。

上に、4つ必要だと書きましたが、実は、 jasmine-reporters に必要なものが全部入ってます。

今回は、これのディレクトリ構成を変えてやってみることにしました。

  • jasmine-reporters v0.2.1 をダウンロードし、適当なディレクトリに展開します
  • 私は、以下のように構成を変えました
    • test/envjs.runner.sh -> bin/envjs.runner.sh
    • lib -> extlib
    • src -> lib
    • test/envjs.bootstrap.js -> lib/envjs.bootstrap.js
    • src/JUnitXmlReporterSpec.js -> spec/JUnitXmlReporterSpec.js
    • test/junit_xml_reporter.html -> ./junit_xml_reporter.html
    • PhantomJS 用ファイルなど、不要なものを削除
      • LICENSE, README.md, test/phantomjs*, test/*.html
  • bin/envjs.runner.sh を、カスタマイズ
--- a/bin/envjs.runner.sh	2012-03-09 14:00:12.000000000 +0900
+++ b/bin/envjs.runner.sh	2012-09-16 18:26:59.000000000 +0900
@@ -1,7 +1,53 @@
 #!/bin/bash
 
+MYDIR=$(dirname "$0")
+MYDIR_FULLPATH=$(cd ${MYDIR} && pwd)
+ROOTDIR_FULLPATH=$(cd ${MYDIR}/../ && pwd)
+EXTLIB_DIR="${ROOTDIR_FULLPATH}/extlib"
+LIB_DIR="${ROOTDIR_FULLPATH}/lib"
+BOOTSTRAP_JS="${LIB_DIR}/envjs.bootstrap.js"
+MAIN_CLASS=org.mozilla.javascript.tools.shell.Main 
+
+# If your path doesn't include java, or you wanna to specify the other one, 
+# please customize the following lines.
+
+### If you wanna to override JAVA_HOME, it's required to unset current JAVA_HOME
+
+# unset JAVA_HOME
+
+SYSTEM=$(uname -s)
+
+CYGWIN=0
+MAC=0
+LINUX=0
+
+if [[ "${SYSTEM}" =~ ^CYGWIN ]]; then
+    CYGWIN=1
+    MY_JAVA_HOME="C:\\Program Files (x86)\\Java\\jdk1.6.0_35"
+elif [[ "${SYSTEM}" =~ ^Darwin ]]; then
+    MAC=1 
+    MY_JAVA_HOME=/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
+else
+    # Assume the other is Linux, yes I know this is too rough.
+    LINUX=1
+    MY_JAVA_HOME=/usr/java/jdk1.6.0_35
+fi
+
+
+export JAVA_HOME=${JAVA_HOME:-${MY_JAVA_HOME}}
+
 # cleanup previous test runs
-rm -f *.xml
+rm -f TEST-*.xml
+
+if [ ${CYGWIN} -eq 1 ]; then
+    CLASSPATH=$(cygpath -w "${EXTLIB_DIR}/js.jar")
+    ROOTDIR_FULLPATH_WIN=$(cygpath -w "${ROOTDIR_FULLPATH}")
+    JAVA=$(cygpath "${JAVA_HOME}\\bin\\java")
+    BOOTSTRAP_JS=$(cygpath -w "${LIB_DIR}/envjs.bootstrap.js")
+    "${JAVA}" -cp "${CLASSPATH}" ${MAIN_CLASS} -opt -1 "${BOOTSTRAP_JS}" "${ROOTDIR_FULLPATH_WIN}" "$@"
+else
+    CLASSPATH=${EXTLIB_DIR}/js.jar
+    JAVA=${JAVA_HOME}/bin/java
+    ${JAVA} -cp "${CLASSPATH}" ${MAIN_CLASS} -opt -1 "${LIB_DIR}/envjs.bootstrap.js" "${ROOTDIR_FULLPATH}" "$@"
+fi
 
-# fire up the envjs environment
-java -cp ../ext/js.jar:../ext/jline.jar org.mozilla.javascript.tools.shell.Main -opt -1 envjs.bootstrap.js $@
  • envjs.bootstrap.js をカスタマイズ
--- a/lib/envjs.bootstrap.js	2012-03-09 14:00:12.000000000 +0900
+++ b/lib/envjs.bootstrap.js	2012-09-15 05:04:23.000000000 +0900
@@ -1,10 +1,11 @@
-load('../ext/env.rhino.1.2.js');
+var baseDir = arguments[0];
+load(baseDir + '/extlib/env.rhino.1.2.js');
 
 Envjs.scriptTypes['text/javascript'] = true;
 
 var specFile;
 
-for (i = 0; i < arguments.length; i++) {
+for (i = 1; i < arguments.length; i++) {
     specFile = arguments[i];
     
     console.log("Loading: " + specFile);
  • env.rhino.1.2.js に、 Windows 用 file:// 処理パッチを当てる(Windowsで使用する場合)
--- a/extlib/env.rhino.1.2.js	2012-03-09 14:00:12.000000000 +0900
+++ b/extlib/env.rhino.1.2.js	2012-09-15 05:04:22.000000000 +0900
@@ -1118,7 +1118,12 @@
     // if base is still empty, then we are in QA mode loading local
     // files.  Get current working directory
     if (!base) {
-        base = 'file://' +  Envjs.getcwd() + '/';
+        var prefix = 'file://';
+        var cwd = Envjs.getcwd();
+        if (cwd.match('^[a-zA-Z]:\\\\')) {
+            prefix = prefix + '/'
+        }
+        base = prefix + cwd + '/';
     }
     // handles all cases if path is abosulte or relative to base
     // 3rd arg is "false" --> remove fragments
  • envjs.runner.bat を作成 (Windows で使用する場合)
new file mode 100644
index 0000000..00ded11
--- /dev/null
+++ b/bin/envjs.runner.bat
@@ -0,0 +1,26 @@
+@echo off
+
+set MYDIR=%~dp0
+echo %MYDIR%
+set ROOT_DIR=%MYDIR%..
+set EXTLIB_DIR=%ROOT_DIR%\extlib
+set LIB_DIR=%ROOT_DIR%\lib
+set BOOTSTRAP_JS=%ROOT_DIR%\envjs.bootstrap.js
+set MAIN_CLASS=org.mozilla.javascript.tools.shell.Main
+
+REM Uncomment if you wanna to override JAVA_HOME
+REM set JAVA_HOME=
+
+REM Change the following to match your environment
+if "%JAVA_HOME%" == "" set JAVA_HOME=C:\Program Files (x86)\Java\jdk1.6.0_35
+
+del /q TEST-*.xml
+
+set CLASSPATH="%EXTLIB_DIR%\js.jar"
+set JAVA=%JAVA_HOME:"=%\bin\java
+set JAVA="%JAVA%"
+set BOOTSTRAP_JS="%LIB_DIR%\envjs.bootstrap.js"
+set ROOT_DIR="%ROOT_DIR%"
+
+echo %JAVA% -cp %CLASSPATH% %MAIN_CLASS% -opt -1 %BOOTSTRAP_JS% %ROOT_DIR% %*
+%JAVA% -cp %CLASSPATH% %MAIN_CLASS% -opt -1 %BOOTSTRAP_JS% %ROOT_DIR% %*
  • ここまでで、 bin/envjs.runner.sh junit_xml_reporter.html を実行し、カレントディレクトリに TEST-JUnitXmlReporter.xml が生成されれば成功です。
  • あとは、Jenkins を設定します
    • Freestyle Project を作成
    • リポジトリは適切に設定
    • Add build step にて、以下の内容で Execute shell ステップを追加
bin/envjs.runner.sh junit_xml_reporter.html
      • Windows の場合、 以下の内容で Execute windows batch command ステップを追加
bin\envjs.runner.bat junit_xml_reporter.html*2
    • Add post-build action で Publish JUnit test result report を追加し、「TEST-*.xml」を設定する
      • このとき、ファイルが見つからないとエラーを吐く場合(一度ビルドに失敗してる場合など)がありますが、無視します
    • Let's build, and enjoy!

自分の Github に上記状態のがおいてありますので、ご自由にお使いください。

実行結果

ビルド成功時の Jenkins の結果を張っておきます。
jasmine-reporters により、圧倒的に結果が分かりやすくなっています。

*1:ソースを hack すればいけそうでした。が、ブラウザ起動が必要なことにはかわりないので、そこまでしませんでした。

*2:htmlへのパスの区切りは / を使用してください。また、どうやら Envjs の内部挙動により、Windows においては、hoge/junit_xml_reporter1.html hoge/junit_xml_reporter2.html のように複数ファイルを指定した場合、2つめ以降が正常に Envjs に読み込まれません。その場合は、 envjs.runner.bat を起動する前に、 cd hoge して実行してください。