「Jasmine」、「Node.js」、「jasmine-node」、「Jenkins」でJavaScriptをテストしてみた。

Javascriptのテストを「Jasmine」を使って実行して、Jenkinsで使ったみたメモです。
動きはしましたがあくまでNode.js用のjavascriptでないと動かないという結果になってしまっています。(方法はあると思いますが。。。)
それでも良い方は続きどうぞ。

また、Karmaを使用したテストではテスト対象のコードをそのまま実行する事ができました。
そのうちこちらもまとめますのでよかったらどうぞ。

目次

以下の順に時系列でダラダラ書いています。

  • Jasmineインストール
  • JavaScriptのコードをJasmineを使ってテスト
  • Node.jsのインストール
  • jasmine-nodeのインストール
  • jenkinsインストール
  • jenkinsでテスト

環境

OS Windows7 Professional 32bit
CPU Core2 Duo 2.93GHz
メモリ 4GB
Jasmine 2.0.0
Node.js v0.10.25
jasmine-node 1.14.3

概要

きっかけ

お仕事で作っているアプリケーションでjsファイルを追加することになったのでテストやってみようって思った。
追加するjsには1つの関数しかないので、スモールスタートとしてはいいかなと。
アプリケーションの規模、用途を考えるとjsファイルが肥大化する事なんて考えられないのでお試しで導入もいいかなと。

今の会社はやりたいと言えば何でもOKだからほんと嬉しいし、楽しい!

Jasmineの選択理由

凄い人に聞いたらJasmineを勧められたため。
(他のフレームワークとの違い、メリットなどはよくわかりません。)

Jasmineとは

JasmineはJavascriptコードをテストするための振舞い駆動開発フレームワークです。他のJavascriptフレームワークに依存しませんし、DOMも必要としません。簡単にテストを書くことができるように、きれいで分かりやすい構文を持っています。

Jasmine: Behavior-Driven JavaScript
種類

2種類あるらしい。

Standalone Release はシンプル、ブラウザページ、コンソールプロジェクト用です。
Jasmine Ruby Gem は、Rails, Ruby, or Rubyに慣れている開発者用です。
他の環境も同様にサポートされます。

Jasmine: Behavior-Driven JavaScript

私はRubyとは縁遠い上に、特に高機能である必要はないのでStandalone Releaseを使用しました。

準備

モジュール取得

さっきからリンクを張っている日本語訳のページだとダウンロードページのリンクがおかしいので、公式のここの一番下の「Downloads」からダウンロードページに飛びます。
で、どうせなら最新版ということで「jasmine-standalone-2.0.0.zip」を落としました。

解凍

取得したモジュールを解凍

JASMINE-STANDALONE-2.0.0
├MIT.LICENSE
├SpecRunner.html
├lib
│└jasmine-2.0.0
│  ├boot.js
│  ├console.js
│  ├jasmine-html.js
│  ├jasmine.css
│  ├jasmine.js
│  └jasmine_favicon.png
├spec
│├PlayerSpec.js
│└SpecHelper.js
└src
  ├Player.js
  └Song.js
  • SpecRunner.html : これを開いた時にテストが実行されて、結果が表示されます。
  • lib/jasmine-2.0.0配下 : Jasmine本体
  • spec配下 : テストファイル
  • src配下 : テスト対象のファイル

本体のみかと思ったらサンプル一式入ってました。

Jasmine実行

サンプル実行

↑でも書きましたが、SpecRunner.htmlを開いたら実行されて結果が表示されます。
5個のテストケースを実行して失敗は0件と表示されているはず。
当然テストは全部成功していますし、テストコードもテスト対象のコードも見てないので正直よくわからない。

実践

サンプルを見てみたらなんとなくわかったけど、サンプル内で文字列比較とかないので失敗のケース作るのがめんどくさい。
なので、いきなりコード書いて、試してみる。

  • テスト対象コード
function Hoge(a,b) {
  return a + b
}
  • テストコード
    • ファイル名に「spec.js」をつける必要あり。
describe("Hogeクラス", function() {
  it("数字足し算", function() {
    expect(Hoge(1,2)).toEqual(3);
  });
  it("文字列足し算", function() {
    expect(Hoge("a","b")).toEqual("ab");
  });
  it("テスト失敗", function() {
    expect(Hoge(1,2)).toEqual(5);
  });
});
  • SpecRunner.htmlをコピーしてテスト対象とテストコードを追加。
<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Jasmine Spec Runner v2.0.0</title>

  <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.0/jasmine_favicon.png">
  <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.0/jasmine.css">

  <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.0/jasmine-html.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.0/boot.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="src/Player.js"></script>
  <script type="text/javascript" src="src/Song.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/SpecHelper.js"></script>
  <script type="text/javascript" src="spec/PlayerSpec.js"></script>

  <!-- 追加メインコード -->
  <script type="text/javascript" src="src/Sample.js"></script>

  <!-- 追加テストコード -->
  <script type="text/javascript" src="spec/SampleSpec.js"></script>
</head>
<body>
</body>
</html>

で、適切な場所に保存してSpecRunner.htmlをコピーしたファイルを開くといい感じの結果。

結果画面

どうやらこんな感じらしい。

  • 一番上はバージョン。
  • 一番上の右に実行時間表示(テスト実行に時間がかかる場合には実行中とかは出ない。。。)
  • 緑の●は成功で赤の×は失敗。
    • 数を増やしたら単純に増えただけだった。。。
  • バーが赤くなっていたら失敗しているテストケースがある
  • Spec Listをクリックすると成功時と同じテストケース一覧を表示
  • 最下部はテスト失敗時のスタックトレースを表示

Jenkinsとの連携(前書)

ユニットテストはJenkinsで行っているため、htmlでテスト出来てもしょうがない。
ということで、JasmineをJenkinsで動かすための手順を調べてました。

  • JavaScriptなので、JavaScriptを動作させるエンジンが必要。
  • で、ブラウザ、Node.js、PhantomJSなどがある。
    • これらの環境で動作させるためにkarma、jasmine-nodeなどを使用する。(Node.jsの場合は直で動かすことができそうだけど、そう簡単にいかないのかしら?)
  • Jenkinsにプラグイン入れてPATH指定したらできるんじゃないか。とか簡単に考えてたけど結構大変っぽい。
  • 手間は手間だけど、こういうのは最初作っちゃえばなんとかなるさということで作る。
  • ブラウザは起動が遅い上にバージョンとかに依存しそう、という事でボツ。
  • Node.jsは少し触ったことがあって、他は全く知らないのでjasmine-nodeを使用してNode.js上で動作させる事に決定。

node.jsインストール

Node.js
私はWindowsなので、「Install」クリックしてインストーラでインストール。
「ダウンロード」からexeも落とせますが、インストーラの方がいいとどっかで見た気がするので大人しくインストーラ実行。
インストールできたらコマンドプロンプト開いてバージョン確認。

$ node -v
v0.10.25

jasmine-nodeインストール

JasmineのテストをNode.jsで動作させるために「jasmine-node」をインストール。

npm install -g jasmine-node

npmはNode.jsのパッケージ管理ツールで、「node.exe」と同じPATHにあるのでNode.jsのバージョン表示されていれば動作するはず。
インストールできたらコマンドプロンプト開いてバージョン確認。

$ jasmine-node  --version
1.14.3

jasmine-nodeでテスト実行

とりあえず実行

早速↑で作ったコードを動かしてみる。

$ jasmine-node ./spec/SampleSpec.js
FFF

Failures:

  1) Hogeクラス 数字足し算
   Message:
     ReferenceError: Hoge is not defined
   Stacktrace:
     ReferenceError: Hoge is not defined
    at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:5:12)

  2) Hogeクラス 文字列足し算
   Message:
     ReferenceError: Hoge is not defined
   Stacktrace:
     ReferenceError: Hoge is not defined
    at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:8:12)

  3) Hogeクラス テスト失敗
   Message:
     ReferenceError: Hoge is not defined
   Stacktrace:
     ReferenceError: Hoge is not defined
    at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:11:12)

Finished in 0.024 seconds
3 tests, 3 assertions, 3 failures, 0 skipped

っということでテストする関数がないよって事で失敗。(1行目に出力されている「FFF」はHTMLでいう●らしい。)
そりゃ、テスト対象のjsを指定してないので当たり前。
Node.jsの機能?でexports、requireがあるので、これを行うことで紐付けます。

  • テスト対象クラス
function Hoge(a,b) {
  return a + b
}

exports.Hoge = Hoge;
  • テストクラス
    • requireで指定するファイルPATHはテストクラスからの相対PATHです。(ここで設定するとわかるけど、jenkinsに設定後だとworkspaceからと勘違いしてしまったので一応。)
var Hoge = require('../src/Sample.js').Hoge;

describe("Hogeクラス", function() {
  it("数字足し算", function() {
    expect(Hoge(1,2)).toEqual(3);
  });
  it("文字列足し算", function() {
    expect(Hoge("a","b")).toEqual("ab");
  });
  it("テスト失敗", function() {
    expect(Hoge(1,2)).toEqual(5);
  });
});
再実行

上記の設定後に再実行。

$ jasmine-node ./spec/SampleSpec.js
..F

Failures:

  1) Hogeクラス テスト失敗
   Message:
     Expected 3 to equal 5.
   Stacktrace:
     Error: Expected 3 to equal 5.
    at null.<anonymous> (c:\work\20140424\gomi\spec\SampleSpec.js:11:23)

Finished in 0.076 seconds
3 tests, 3 assertions, 1 failure, 0 skipped

正しく実行されて、1件のテスト失敗がわかります。

Jenkinsインストール & 起動

いきなり動いているJenkinsでやるのもどうかと思うのでローカルにJenkins導入。

Jenkins設定

Job作成
  • 新規ジョブ作成
  • ジョブ名適当に入力
  • 「フリースタイル・プロジェクトのビルド」選択
  • OK
設定といきたいけどファイル配置

本来はバージョン管理システムから取得する所だけど、この段階ではそんなものないので手動でworkspaceに配置。

  • 私の環境だと↓
    • 「C:\Users\${ユーザ名}\.jenkins\jobs\${ジョブ名}\workspace\」
  • 私は以下のように配置しました。
C:\Users\${ユーザ名}\.jenkins\jobs\${ジョブ名}\workspace
└test
  ├lib
  │└jasmine-2.0.0
  │  ├boot.js
  │  ├console.js
  │  ├jasmine-html.js
  │  ├jasmine.css
  │  ├jasmine.js
  │  └jasmine_favicon.png
  ├spec
  │└SampleSpec.js
  └src
    └Sample.js
ジョブの設定 & 実行
  • ビルド部の「ビルド手順の追加」
  • Windowsバッチコマンドの実行」を追加
  • コマンド
jasmine-node test\spec\SampleSpec.js
  • 保存
  • ビルド実行
  • 以下の感じで出力されればOK(日本語が化けているのは気にしない。。。)
ユーザーanonymousが実行
ビルドします。 ワークスペース: C:\Users\yamap\.jenkins\jobs\Sample\workspace
[workspace] $ cmd /c call C:\Users\YAMAP\AppData\Local\Temp\hudson5171352823916894994.bat

C:\Users\yamap\.jenkins\jobs\Sample\workspace>jasmine-node test\spec\SampleSpec.js 
..F

Failures:

  1) Hoge繧ッ繝ゥ繧ケ 繝&#65533;繧ケ繝亥、ア謨&#65533;
   Message:
     Expected 3 to equal 5.
   Stacktrace:
     Error: Expected 3 to equal 5.
    at null.<anonymous> (C:\Users\yamap\.jenkins\jobs\Sample\workspace\test\spec\SampleSpec.js:15:23)

Finished in 0.022 seconds
3 tests, 3 assertions, 1 failure, 0 skipped


Build step 'Windowsバッチコマンドの実行' marked build as failure
Finished: FAILURE
レポート出力

コンソールに出力されてもどうしようもないのでJUnit形式でレポート出力を行う。

  • 設定変更
    • コマンド
jasmine-node test\spec\SampleSpec.js --junitreport --output "reports"
    • ビルド後の処理に「JUnitテスト結果の集計」を追加
reports\*
  • 保存
  • ジョブ実行(相変わらずコンソール上では日本語が化ける。。。)
ユーザーanonymousが実行
ビルドします。 ワークスペース: C:\Users\yamap\.jenkins\jobs\Sample\workspace
[workspace] $ cmd /c call C:\Users\YAMASH~1\AppData\Local\Temp\hudson941930116661068781.bat
C:\Users\yamap\.jenkins\jobs\Sample\workspace>jasmine-node test\spec\SampleSpec.js --junitreport --output "reports" 
..F

Failures:

  1) Hoge繧ッ繝ゥ繧ケ 繝&#65533;繧ケ繝亥、ア謨&#65533;
   Message:
     Expected 3 to equal 5.
   Stacktrace:
     Error: Expected 3 to equal 5.
    at null.<anonymous> (C:\Users\yamap\.jenkins\jobs\Sample\workspace\test\spec\SampleSpec.js:11:23)

Finished in 0.028 seconds
3 tests, 3 assertions, 1 failure, 0 skipped


Build step 'Windowsバッチコマンドの実行' marked build as failure
テスト結果を保存中
Finished: FAILURE
  • テスト結果が出力されていればOK

問題

  • Jenkinsのコンソール上で日本語を正しく表示させたい(レポートは化けてないので別に問題はないですが。)
    • 以前別のプラグインでハマったんだけど解決策は忘れたw
  • そもそもテスト対象コードに手を入れたくない。
    • Node.js以外の環境だとexportsメソッドが定義されていないので動かない。(jasmine付属のHTMLでの実行も同じ理由でNG。)
    • 色々試したけどNode.jsで動作させるのでexportは書く必要があるっぽい(別のファイルから指定できると思うけど方法がみつからず。)