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

lxyuma BLOG

開発関係のメモ

最近のjsテスト/ビルド環境

javascript gulp karma TDD

最近のテスト環境

最近、ブログ書かないうちに、また、

自分のjs周りのテストやビルド環境が変わってきた。

具体的には、karmaとかgulpとかに変わった。

今日は、

  • その環境にしてどうだったか?とか、

  • 設定ファイル(gulpfile)とか書いてみる。

去年と今年と

去年、勉強会等でyeomanとかgruntの話をしていて、このblogでもどこかに書いてた。

テストはmocha chaiが良いのかなーと思ってた。これもblog書いた。

所が、世の中どんどん変わっていく。

最近の環境

今はこんな感じ。

  • build tool
    • gulp
  • test
    • jasmine2
    • sinon
    • karma

gulp vs Grunt

gulpどうなんだろう?と思いながら色々試していくうちに、かなりしっくりきた。

stream baseで書き易いので、カスタマイズし易い。

gruntは、設定ファイルが何画面にも渡って長くなると、メンテが怠い。

何がどうなってるのか分からなくなって来る。

gulpは、小分けでタスク分けて依存関係も整理しながらstreamで書くので、非常にsmartで良い。

しかも、色々タスク積んでも並行実行はやっぱり早くて気持ちがよい。

Gruntも今後、色々gulpっぽくなりそうだけど、いつどうなるか、よくわかんない。

とりあえず、今日から始めるならgulpがいい。

yeoman

初め、yeomanとgulp組み合わせて使おうと思ってたけど、

なんか、最近、yeoman要らなくなってきた。

gulpだけでも、scaffoldingっぽい事も作れる。

yeoman色々事前に用意してくれてるんだけど、

実際の現場では、殆どの場合、使えない。(勿論、家で遊ぶなら、それでいいけど)

自分でカスタマイズしていかないといけない。

となるとカスタマイズし易いgulpだけで完結した方が扱い易い。という事でyeomanもう見てない。

jasmine vs mocha

mocha + chaiは、slideでも書いたんだけど、

language chainが気持ち悪くて結局、jasmineに戻った。

※should.jsもあるけど、もうrspecもshouldじゃなくてexpectなんだよな...shouldはobject破壊するので、いつか無理がでる

jasmineは2になって、非同期テストdoneが付いてて、

もう、mochaに大きなメリットが無くなってる。

jasmineは公式pageの1枚だけ調べれば何でも出来るAll in Oneのシンプルさが素晴らしい。

sinon

sinonはまだまだ使ってるなー。

最近は、要件上、htmlが大きく動く事が少ないので、そのままhtmlFixture使ってて、

TestDoubleそんなにしなくなったんだけど、

それでも、FakeTimerとかめっちゃ使う。

。。。これ書いてて思い出したけど、そういえば、

jasmine2にもtimerあったから、sinonのtimerでなくてもいいかも。明日から変えよう...

karma

昔は、それぞれのテスト環境の上にのっかったテストランナーを使ってた。

今、karma使うようになった。

こういう大きなeco systemに乗っかるメリットは、

困った時にググるとほぼ100%同じ事やってる人がいる事。

大体pluginとか助けてくれる。

HtmlFixtureもあるし、browser実行環境、report等、揃ってる。

勿論、他のtoolやtest FW単体でも出来るんだけど、

共通化されて整理されてるのは素晴らしい。

以前mocha固有の設定とかでイライラする事あったんだけど、karmaのおかげで大分助かってる。

gulpの設定等

今から使ってるgulp設定をおいておく

これは、今、componentっぽい物を幾つか作ってるのに使ってる設定で、

それぞれのprojectで使うには色々調整必要だと思う。

けど、なんかの参考迄に。

gulpのコマンド

  • 以下を準備してる
// all(buildして、testして、監視します)
gulp

// build(js/cssをbuildします)
gulp build

// test(jsをtestします)
gulp test

// 単にindex.htmlが見たい
gulp server

// 新たにコンポーネントを追加したい
gulp scaffold --name your_new_component_name

設定

  • gulpfileはこんな感じにしてる
    • $は、var $ = require('gulp-load-plugins')();の事。
gulp.task("hint", function() {
    return gulp.src(paths.scripts)
        .pipe($.jshint())
        .pipe($.jshint.reporter("default"))
});

gulp.task('scripts', ['hint'], function() {
    return gulp.src(paths.scripts)
        .pipe($.uglify())
        .pipe($.concat(dist.script))
        .pipe(gulp.dest(dist.dir))
        .pipe($.connect.reload());
});

gulp.task('styles', function() {
    return gulp.src(paths.styles)
        .pipe($.compass({
            project: path.join(__dirname, 'app/styles')
        }))
        .pipe($.csso())
        .pipe($.concatCss(dist.style))
        .pipe(gulp.dest(dist.dir))
        .pipe($.connect.reload());
})

gulp.task('connect', ['scripts', 'styles'], function() {
    $.connect.server({
        root: './',
        port: server_port,
        livereload: true
    });
});

gulp.task('html', function(){
    return gulp.src(paths.html)
        .pipe($.connect.reload());
});

gulp.task('watch', function(){
    gulp.watch(paths.scripts, ['scripts']);
    gulp.watch(paths.styles, ['styles']);
    gulp.watch(paths.html, ['html']);
    gulp.src(karma_filepaths)
        .pipe($.karma({
            configFile: karma_config,
            action: 'watch'
        }));
});

gulp.task('test', function(){
    return gulp.src(karma_filepaths)
        .pipe($.karma({
            configFile: karma_config,
            action: 'run'
        }))
        .on('error', function(err) {
            throw err;
        });
});

gulp.task('scaffold', function(){
    gulp.src(paths.templates.script)
        .pipe($.rename(argv.name + ".js"))
        .pipe($.template({name: argv.name}))
        .pipe(gulp.dest('app/scripts/'));
    gulp.src(paths.templates.style)
        .pipe($.rename(argv.name + ".scss"))
        .pipe($.template({name: argv.name}))
        .pipe(gulp.dest('app/styles/sass/'));
    gulp.src(paths.templates.test)
        .pipe($.rename(argv.name + "_spec.js"))
        .pipe($.template({name: argv.name}))
        .pipe(gulp.dest('tests/'));
    gulp.src(paths.templates.html)
        .pipe($.rename(argv.name + ".html"))
        .pipe($.template({name: argv.name}))
        .pipe(gulp.dest('tests/fixtures/'));
});

gulp.task('server', ['connect'], function(){
    gulp.src('./index.html')
        .pipe($.open('', {url: "http://localhost:" + server_port}));
});


gulp.task('default', ['server', 'watch']);
gulp.task('build', ['scripts', 'styles']);

gulpfileは現在進行形で編集中

  • 今現在もこのgulpfile色々追加したり直したりしながら、使ってる
    • 例えば、今日は、testからdocument生成用のtaskを書いてた。
    • scaffold系は、それ専用のpluginもググるといっぱいあるので、そっち使ってもいいかもしれない。
  • 無駄な所あったらごめんなさいね(concat周りとか)

gulpとjasmine2

まとめ

  • FrontendはRedOceanで次々に変化起きるので、どんどん乗っかって楽するのが良い