月別アーカイブ: 2015年7月

KarmaでDOM操作のテストをする

このページでは、KarmaでDOM操作のテストをする方法を紹介します。

テスト対象

例として、下記のコードをテストしたいとします。index.htmlを開くと、メッセージが表示されるものです。

<!-- index.html -->
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <p id="message"></p>
  <script src="js/jquery.js">
  <script src="js/app.js">
  <script>
    $(function() {
      app.showMessage('init');
    }());
  </script>
</body>
</html>
// app.js
(function(global) {
  'use strict';
  global.app = {
    showMessage: function(message) {
      $('#message').text(message);
    }
  };
}(this.self));

フォルダ構成は下記の通りです。appフォルダにテスト対象のコードを入れ、specフォルダにテストコードを書いていきます。

Project
  ├─ app
  │    ├─ index.html
  │    └─ js
  │       ├─ jquery.js
  │       └─ app.js
  └─ spec

テスト環境構築

karma-html2js-preprocessorのインストール

karma-html2js-preprocessorはKarmaのプラグインであり、HTMLファイルをjsから読み込むことができるようになります。

$ npm install karma-html2js-preprocessor --save-dev

karmaの設定ファイルを変更し、filesとpreprocessorsにHTMLファイルを追加します。

// karma.conf.js
module.exports = function(config) {
  config.set({
    ...
    files: [
      'app/js/jquery.js',
      'app/js/app.js',
      'app/*.html'
      'spec/**/*.js',
    ],
    preprocessors: {
      'app/*.html': ['html2js']
    },
    ...
  });
};

テストコードの記述

specフォルダにテストコードappSpec.jsを作成し、beforeEachでdocumentのbodyにindex.htmlを読み込みます。テスト対象のコードでjQueryを使用しているので、テストコードからも使用しています。

// appSpec.js
describe('app', function() {
  var text = 'text';
  beforeEach(function() {
    document.body.innerHTML = __html__['app/index.html'];
  });
  it('should show message', function() {
    app.showMessage(text);
    expect($('#message').text()).toEqual(text);
  });
});

画像読み込みエラー

index.htmlで画像ファイルを読み込んでいる場合、テスト実行時にWARNINGが表示されます。

<!-- index.html -->
<!DOCTYPE html>
<html>
  ...
  <img src="img/image.png">
  ...
</html>
$ npm test
...
WARN [web-server]: 404: /img/image.png
...

このエラーが表示されないようにするには、プロキシを介して画像ファイルを読めるようにします。画像ファイルはファイルの変更監視が必要ないのと、ブラウザ起動時にscriptタグで読み込まないので、watchとincludedをfalseにします。プロキシには、ベースとなるフォルダのパスを基点にするために’base’を付加したパスを設定します。

// karma.conf.js
module.exports = function(config) {
  ...
  files: [
    'app/js/jquery.js',
    'app/js/app.js',
    'app/*.html',
    {pattern: 'app/**/*.png', watched: false, included: false, served: true},
    'spec/**/*.js'
  ],
  proxies: {
    '/img/': '/base/img/'
  },
  ...
};

Karmaでカバレッジを取る

このページでは、Karmaのテスト実行時にカバレッジを取る方法を紹介します。

カバレッジ取得環境の構築

karma-coverageのインストール

karma-coverageはkarmaのプラグインであり、テストを実行するとカバレッジが取れます。karmaのテスト環境構築方法はこちらで紹介しています。

$ npm install karma-coverage --save-dev

karmaの設定ファイルを修正します。reportersに’coverage’を追加し、preprocessorsにカバレッジを取りたいファイルを指定します。

// karma.conf.js
module.exports = function(config) {
  config.set({
    ...
    files: [
      'app/js/jquery.js',
      'app/js/app.js',
      'test/**/*.js'
    ],
    reporters: ['progress', 'coverage'],
    preprocessors: {
      'app/js/app.js': ['coverage']
    }
    ...
  });
};

カバレッジ取得

Karmaのテストを実行すると、自動的にカバレッジが取得します。取得したカバレッジはcoverageフォルダにHTML形式で保存されます。

$ npm test
(karma startのことです)

coverage/index.html
karma-coverage
 

ちなみに

カバレッジデータはテストを実行すれば作成されるため、コミットする必要はありません。バージョン管理している場合はignoreに追加しておきましょう。

[.gitignore]
...
coverage

karma.conf.jsをwatchする

このページでは、Karmaの設定ファイルであるkarma.conf.jsの変更を検知して、テストを再実行する方法を紹介します。

はじめに

karma.conf.jsには、テスト対象やテストコードのファイルパスや記述します。autoWatchをtrueにすればファイルの変更を検知できますが、karma.conf.js自体の変更を検知できません。テスト実行中にファイルを増やすこともあるため、karma.conf.jsもwatchしたいと思います。
karmaのテスト環境構築方法はこちらで紹介しています。

nodemonのインストール

nodemonを使うと、ファイルの変更を検知してタスクを再実行できます。

$ npm install nodemon --save-dev

ファイルの監視とテストの実行

監視するファイルと実行するタスクを指定して、nodemonを実行します。karma.conf.jsを変更すると、テストが止まって再実行されます。

$ node_modules/.bin/nodemon --watch karma.conf.js --exec node_modules/.bin/karma test

コマンドの整理

毎回長いコマンドを書くのも大変なので、npm testでファイルの監視を含めたテストを実行できるようにします。

[package.json]
{
  ...
  "scripts": {
    "test": "nodemon --watch karma.conf.js --exec karma start"
  },
  ...
}

下記コマンドでテストが実行できます。

$ npm test

Karma+JasmineでJavaScriptをテストする

このページでは、KarmaというテストランナーとJasmineというテストフレームワークを使って、JavaScriptをテストする方法を紹介します。

関連記事

このページの続きとして、以下の関連記事があります。順番は関係ないので、必要なものを見てください。

テスト対象

例として、下記のコードをテストしたいとします。index.htmlを開くと数値の合計値が表示されるものです。

<!-- index.html -->
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <p id="message"></p>
  <script src="js/app.js">
  <script src="js/jquery.js">
  <script>
    $(function() {
      var num = app.sum(1, 2);
      app.showMessage(num);
    }());
   </script>
</body>
</html>
// app.js
(function(global) {
  'use strict';
  global.app = {
    sum: function(a, b) {
      return a + b;
    },
    showMessage: function(message) {
      $('#message').text(message);
    }
  };
}(this.self));

フォルダ構成は下記の通りです。appフォルダにテスト対象のコードを入れ、specフォルダにテストコードを書いていきます。

Project
  ├─ app
  │    ├─ index.html
  │    └─ js
  │       ├─ jquery.js
  │       └─ app.js
  └─ spec

テスト環境構築

事前準備

Node.jsはインストール済みとして、package.jsonがない場合は作ります。設定は自由に。

$ npm init

karmaのインストール

npmからkarmaをインストールします。

$ npm install karma --save-dev

karmaの設定ファイルを作成します。テストフレームワークとしてJasmine、ブラウザにChrome、テストコードのディレクトリをspecフォルダ以下のjsファイルに指定します。

$ node_modules/.bin/karma init
Which testing framework do you want to use ?
Press tab to list possible options. Enter to move to the next question.
> jasmine
Do you want to use Require.js ?
This will add Require.js plugin.
Press tab to list possible options. Enter to move to the next question.
> no
Do you want to capture any browsers automatically ?
Press tab to list possible options. Enter empty string to move to the next question.
> Chrome
>
What is the location of your source and test files ?
You can use glob patterns, eg. "js/*.js" or "test/**/*Spec.js".
Enter empty string to move to the next question.
> app/js/jquery.js
> app/js/app.js
> spec/**/*.js
WARN [init]: There is no file matching this pattern.
>
Should any of the files included by the previous patterns be excluded ?
You can use glob patterns, eg. "**/*.swp".
Enter empty string to move to the next question.
>
Do you want Karma to watch all the files and run the tests on change ?
Press tab to list possible options.
> yes
Config file generated at ".../Project/karma.conf.js".

テストコードを書く

app.jsのテストコードとして、specフォルダにappSpec.jsを作成します。appオブジェクトのsum関数をテストします。

// appSpec.js
describe('app', function() {
  it('should sum numbers', function() {
    expect(app.sum(1, 2)).toEqual(3);
  });
});

テストを開始します。するとブラウザが立ち上がりテストコードが実行されます。「SUCCESS」と表示されていて、テストが成功したことがわかります。テストにかかった時間も表示されるため、処理速度の目安にすることもできます。

$ node_modules/.bin/karma start
INFO [karma]: Karma v0.12.37 server started at https://localhost:9876/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 43.0.2357 (Mac OS X 10.10.4)]: Connected on socket IFN6So2x3Bv54q3o_ch4 with id 97782541
Chrome 43.0.2357 (Mac OS X 10.10.4): Executed 1 of 1 SUCCESS (0 secs / 0.002 secChrome 43.0.2357 (Mac OS X 10.10.4): Executed 1 of 1 SUCCESS (0.005 secs / 0.002 secs)

karma_chrome

コマンドの整理

上記では「node_modules/.bin/karma」を実行しており、binのパスまで指定する必要がありますが、npm経由でコマンドを実行すると、パスを指定しなくても実行できます。

[package.json]
{
  ...
  "scripts": {
    "test": "karma start"
  },
  ...
}

下記コマンドでテストが実行できます。

$ npm test

ちなみに

DOM操作を行っているappのshowMessage関数のテスト方法はこちらを紹介しています。