JavaScript
Node.js
karma
gulp

gulp + karmaでテスト駆動開発

経緯

jsの開発をしていて、デグレが多くて辛いのでテスト駆動開発をしたいと思い
オレオレテスト駆動開発環境を作りました。

ローカル環境

  • mac(macOS 10.13.2)
  • Node.js(8.9.3)
  • gulp(3.9.1)
  • karma(2.0.0)

GitHub

  • TravisCI

ローカル環境を準備

1. Node.jsの導入

nvmでNode.jsは管理する

cd ~
git clone https://github.com/creationix/nvm.git ~/.nvm
source ~/.nvm/nvm.sh
nvm install v8.9.3
nvm alias default v8.9.3

macを起動した時に自動でNode.jsが起動するよう設定

vim ~/.bash_profile 

下記を追記

[[ -s ~/.nvm/nvm.sh ]] && . ~/.nvm/nvm.sh
nvm use default
npm_dir=${NVM_PATH}_modules
export NODE_PATH=$npm_dir

反映

source ~/.bash_profile

これでNode.jsの準備は完了。

2. gulp & karma

グローバルにgulpkarmaをインストール

npm install -g gulp karma

プロジェクトに必要なpackageをインストール

package 用途
gulp gulp本体
gulp-concat 複数のJSファイルを一個のJSにしてくれる
gulp-uglify 一個にまとめたJSをminfyする
karma karma本体
karma-coverage レポートを出すためのモジュール
karma-jasmine karmaでjasmineを使えるようにする
karma-phantomjs-launcher phantomjsで動かしたいので入れる
karma-spec-reporter コンソールを見やすくする
phantomjs phantomjs本体
jasmine jasmine本体
browser-sync Browsersync本体

インストール

npm install gulp gulp-concat gulp-uglify karma karma-coverage karma-jasmine karma-phantomjs-launcher karma-spec-reporter phantomjs jasmine browser-sync --save-dev

3. gulpfile.jsを設定

var gulp    = require("gulp");
var browser = require("browser-sync").create();
var concat  = require("gulp-concat");
var uglify  = require("gulp-uglify");
var Server  = require("karma").Server;

/**
 * server setting
 */
gulp.task("server", function ()
{
    browser.init({
        server: {
            baseDir: "./",
            index: "index.html"
        }
    });
});

/**
 * browser reload
 */
gulp.task("reload", function ()
{
    browser.reload();
});

/**
 * output swf2js
 */
gulp.task("output", function ()
{
    gulp.src([
            "src/**/*.js",
        ])
        .pipe(concat("output.js")) // 複数のJSを一個にまとめる
        .pipe(uglify()) // 圧縮
        .pipe(gulp.dest(".")); // 圧縮したファイルを出力
});

/**
 * default setting
 */
gulp.task("default", ["server"], function ()
{
    // JSに変更があればテストを起動
    gulp.watch(["src/**/*.js"], ["tdd"]);
    // テスト通過したファイルが出力されたらブラウザを再読み込み
    gulp.watch(["output.js"], ["reload"]);
});

/**
 * test-driven development
 */
gulp.task("tdd", function (done)
{
    new Server({
        configFile: __dirname + "/karma.conf.js",
        singleRun: false
    }, done)
        .on("run_complete", function (browsers, results)
        {
            // エラーがあれば出力
            if (results.failed) {
                throw new Error("failed");
            }
            // テストが終了したらjsを出力する
            gulp.start.apply(gulp, ["output"]);
        })
        .on("error", function (err) {
            done(err);
        })
        .start();
});

/**
 * Run test once and exit
 */
gulp.task("test", function (done)
{
    new Server({
        configFile: __dirname + "/karma.conf.js",
        singleRun: true
    }, done).start();
});

4. karma.conf.jsを設定

// Karma configuration
// Generated on Wed Sep 06 2017 20:07:29 GMT+0900 (JST)

module.exports = function(config)
{
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],


    // list of files / patterns to load in the browser
    files: [
      "src/**/*.js",
      "test/**/*.js"
    ],


    // list of files to exclude
    exclude: [
    ],


    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
        'src/**/*.js': ['coverage']
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['spec', 'coverage'],

    coverageReporter: {
      type: 'html',
      dir: 'coverage/'
    },

    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['PhantomJS'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity
  });
};

これで、ローカルの準備が整ったのでgulpを起動して動くか確認。

# gulp
[00:00:00] Using gulpfile ~/**/gulpfile.js
[00:00:00] Starting 'server'...
[00:00:00] Finished 'server' after 
[00:00:00] Finished 'server' after 11 ms
[00:00:00] Starting 'default'...
[00:00:00] Finished 'default' after 140 ms
[Browsersync] Access URLs:
 ---------------------------------------
       Local: http://localhost:3000
    External: http://172.17.100.100:3000
 ---------------------------------------
          UI: http://localhost:3001
 UI External: http://172.17.100.100:3001
 ---------------------------------------
[Browsersync] Serving files from: ./

こんな感じで動けばローカルの準備はOK。

GitHub側の設定

1. .travis.yml

.travis.ymlにテスト環境の設定を書く。

language: node_js
node_js:
  - "8.9.3"

cache:
  directories:
    - "node_modules"

before_install:
  - npm install -g gulp karma

install:
  - npm install

2. package.json

テストのディレクトリと実行スクリプトを追記

{
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "gulp test"
  },
}

これでコミットする度にTravisでテストできます。

それでは、楽しいテスト駆動ライフを〜