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

はてブロ@ama-ch

https://twitter.com/ama_ch

KarmaでTDD + Travis CI + Coverallsなイケてるワークフロー

巷でAngularJSが盛り上がっているのを横目に、最近は黙々とKarmaを触っていました。Karmaはかなりよくできていて素晴らしいと思うんですが、具体的な使い方はあまり見ないので紹介したいと思います。

Karmaについて

http://karma-runner.github.io/

Karmaはいわゆるリモートテストランナーです。リモートテストランナーというと、色んなブラウザでテストを走らせることが目的のように思えますが、そうではありません。Karmaは ワークフローの問題を解決すること に主眼が置かれています。なので、コマンドラインでテストを実行するほかに

  • ファイルの変更監視
  • CIサーバとの連携
  • デバッグのサポート
  • プラグインによる機能拡張

といった機能を持っています。実際に使ってみると、単にテストを実行してくれるだけでなく、ワークフローが劇的に変わることを実感できると思います。

Karmaの特徴

個人的にいいなと思うKarmaの特徴について。

ドキュメントが豊富

公式ページのドキュメントが充実しています。とりあえずドキュメントをざっと眺めれば使い始めることができますし、CIサーバとの連携方法など使い始めたら気になる所も網羅されていて好感が持てます。

あとリポジトリのルートに置いてあるthesis.pdfにはKarmaの設計思想やアーキテクチャがコンパクトにまとまっていて、全体を把握するのに役立ちました。

プラグインで拡張できる

Karmaはテストフレームワークのサポートやレポーター・プリプロセッサなど機能の多くがプラグインになっています。代表的なものは公式プラグインとして提供されていて、ほかにもユーザーが作成したプラグインが数多く公開されています。おかげで、テストに関する様々な要求に柔軟に対応できます。

たとえば、

なんていう場合にもプラグインの設定をちょいちょい変えるだけでOKです。

実績がある

実際に現場に投入するとなると、ちゃんと動くかどうかが気がかりです。とくに大規模なプロジェクトはJSファイルが数千になったりするので、安易に乗り換えた結果まともに動かないという事態は絶対に避けないといけません。
Karmaはその点GoogleYoutubeで実際に使われているという実績があり、その安心感はデカイです。

Karmaのサンプルプロジェクト

そんなKarmaを使うと、「TDDしてCIしてカバレッジを見て...」というワークフローがかなりイケてる感じになります。試しにそのワークフローが体感できるリポジトリを作ってみました。

ama-ch/karma-intro
https://github.com/ama-ch/karma-intro

Karmaのセットアップ方法や基本的な使い方は割愛します。公式ドキュメントや入門エントリを参照してください。

概要

f:id:ama-ch:20131215234201p:plain

基本コマンド

grunt karma:devでTDD用の設定でKarmaが起動します。起動した状態でコードを変更すると自動でテストが走って、Growlでポコポコ通知してくれます。Ctrl+Cで終了します。
grunt karma:ciでCI用の設定でKarmaが起動します。PhantomJSだけでテストが実行されて、実行後は即終了します。
grunt coverageでCoverall用のカバレッジレポートを作成して、Coverallにポストします。手元で直接叩くことはないです。

CI設定

.travis.ymlはこんなかんじ。

language: node_js
node_js:
  - 0.10

before_script:
  - npm install -g grunt-cli

script:
  - grunt karma:ci

after_success:
  - grunt coverage

grunt karma:ciしてgrunt coverageするだけです。簡単ですね。

機能追加ワークフロー

では、このリポジトリで何か機能を追加するワークフローを考えてみます。

1.フィーチャーブランチを切る

まず実装用のブランチを切ります。

2. grunt karma:devでTDDを開始する

Karmaが起動してコードの変更を監視します。

3. 実装する

コードを変更すると自動でテストが走って結果がGrowlで通知されます。

f:id:ama-ch:20131215231419p:plain

4. デバッグする

テストが意図せず失敗したときは、デバッグをします。
コンソールを開くとスタックトレースが表示されているので、参考にしましょう。

f:id:ama-ch:20131215231445p:plain

コンソールを見てもよく分からない場合は、Karmaのデバッグ画面(http://localhost:9876/debug.html)を開いてdevtoolsでデバッグします。

5. pushしてプルリクエストを作る

実装が一段落したら、ブランチをプッシュしてプルリクエストを作成します。

6. プルリクエストでビルド結果とカバレッジを確認する

pushと同時にTravis CIのビルドとCoverallsのカバレッジレポートが実行されます。これは快適ですね!

f:id:ama-ch:20131215234201p:plain

とまあこんな具合でTDDしつつCIしてカバレッジできてイケてるよねーとかそんな感じですが、これはNode.jsの開発を超速化するGitHub連携 三種の神器 - teppeis blogパクリです。 「それKarma使えばWebアプリでもできるよ!」って言いたかっただけです。

使ってるプラグインなど

grunt-karma

公式のGruntプラグインです。タスクごとにKarmaの設定を書き換えることができるので、これでCI用の設定などを書き分けています。

karma-spec-reporter

テスト結果をMochaのspecレポーター風に出力してくれるプラグインです。デフォルトのレポーターは通ったテストをほとんど表示してくれないんですよね。バババッと一覧で見たい人にはありがたいプラグインです。

grunt-karma-coveralls

これはKarmaのプラグインじゃなくてGruntプラグインです。Karmaで作成したカバレッジレポートをCoverallsにポストしてくれます。事前にカバレッジの計測をしておく必要がありますが、Karmaならkarma-coverageで一瞬でできちゃいます。

TestemかKarmaか

ちょっと違う話題になりますが、せっかくなので。
提供する機能が大体同じなのでどっちでもいいと思いますが、大規模プロジェクト*1ではKarmaをオススメします。

Karmaを触る前はTestemを調べていたんですが、大量のJSを読み込むとファイルディスクリプタの上限に引っかかって動かなかったりwatchでCPUリソースを食い潰して死亡するという現象が発生したため断念しました。

とはいえTestemはレポーターがかっちょいいですし、基本はやっぱり好みで決めて、問題が起きたら他のも検討してみるくらいでちょうど良いんじゃないかと思います。

まとめ

Karmaを使うとテストが自動で動かせるだけじゃなくて、CI連携やカバレッジ計測もできるようになります。まさにワークフローが変わります。AngularJSも良いけどKarmaもぜひ使ってみてください!

*1:読み込むJSのファイル数が数百を超えてくるイメージです。

Closure Linterが神アップデート!MAX_LINE_LENGTHが設定可能に!

久しぶりにClosure Linterのリポジトリを確認してみたらバージョンが2.3.10に上がっていて、色々と機能が追加されていました。

更新内容を確認していたら、なんと MAX_LINE_LENGTHが設定可能になっていて、さらにエラーが個別に制御できるようになっていますよ! 今まではこれができなくて、導入に二の足を踏んでしまう人も多かったんじゃないかと思います。

--max_line_lengthと--disableというコマンドラインオプションでそれぞれ指定可能です。以下はヘルプから抜粋。

closure_linter.errorrules:
  --disable: Disable specific error. Usage Ex.: gjslint --disable 1,0011 foo.js.
    (a comma separated list)
  --[no]jsdoc: Whether to report errors for missing JsDoc.
    (default: 'true')
  --max_line_length: Maximum line length allowed without warning.
    (default: '80')
    (a positive integer)

MAX_LINE_LENGTHが設定できない件はディスカッションでも何度か言及されていたんですが、かなりの強硬姿勢で頑として設定可能にはしないという雰囲気で完全に諦めてラッパースクリプトを書いたりしていました。それが一転して設定可能になるという僥倖に鼻息が抑えられません!

しかしなぜ急に設定可能になったんだろう?JSHintが歩み寄ってくれたのが関係あったりするんでしょうか。
理由はさておき、導入がしやすくなったのは素晴らしいです。JSHintと併用するのも簡単になったので、ますますLintが捗りそうです。Happy Lint!

https://developers.google.com/closure/utilities/

WEB+DB PRESS Vol.74でJavaScriptのメモリリークについて書きました!

WEB+DB PRESSで連載中の「JavaScript活用最前線」が2年目に突入しました!
第7回目となる今回は、JavaScriptメモリリークChrome Developer Toolsのヒーププロファイラを使った解析方法を書きました。

WEB+DB PRESS Vol.74

WEB+DB PRESS Vol.74

近ごろはJavaScriptでもメモリ管理を気にかける機会が増えていると感じます。少し前まではメモリリークというとIEのJSとDOMの間で循環参照がナントカみたいな話が多かったですが、最近はシングルページのリッチなWebが増えたことで、純粋にオブジェクトのライフサイクルをきちんと管理しないといけなくなりました。

連載の内容は、まずオブジェクトのライフサイクルとガベージコレクションの動きを解説して、実際にリークが発生するサンプルコードをヒーププロファイラで解析していくような構成になっています。実はconsole.log()がリークの原因になることや、Backbone.jsでよくハマるZombie Viewにも触れています。

Backbone.jsをはじめとするMVCフレームワークJavaScriptに新しいパラダイムを導入してくれましたが、それによってメモリリークが発生するというのは避けたいですね。このような罠にはまらないためにも、オブジェクトのライフサイクルをきちんと把握・管理することが重要です。

新人にドヤ顔で「それリークしてるよ」って言うためにも、このあたりはぜひ把握しておきたいですね。逆に新人さんは「それってメモリリークしませんか?」と強力なスタートダッシュを決めるチャンスです。

新人を応援するWEB+DB PRESS Vol.74 新人応援号は本日発売です!ぜひご覧ください!

JSHint+Closure Linter+Gruntで最強のLint環境を目指してみた

先日JSHint 1.1.0がリリースされ、そのリリースノートに気になる記述がありました。

Adds new option gcl to make JSHint style checks compatible with Google Closure Linter.

うそーまじでーなにそれヤバイ!

普段は仕事でClosureにどっぷりなせいもあってClosure Linterを使っているんですが、Closure LinterってJSDocとかお作法的なとこはチェックしてくれるけど、他のLintツールが当たり前にチェックしてくれるとこはやってくれないんですよね。たとえばvarの付け忘れとか。

Closure Compilerを使ってコンパイル時にチェックすることもできるけど、規模が大きくなってくるとその結果が出るまでに10分とか待たないといけなくっていやな感じー。Closure LinterとJSHintが一緒に使えたらいいんだけどなー。

でも今まではfunctionの後のスペース有無でClosure LinterとJSHintが喧嘩してしまい、同時に使うのが難しかったんです。

// Closure Linterのスタイル
var hoge = function() {};
// JSHintのスタイル
var hoge = function () {};

それがJSHint 1.1.0で解消したと。素晴らしいですね!
せっかくなのでGruntの練習もかねて、JSHintとClosure Linterが一括でかけられるGruntプロジェクトを作ってみました。

grunt-gjshint

https://github.com/ama-ch/grunt-gjshint

使い方

gjslintをインストールしたことがない場合は、たぶん事前に easy_install python-gflags が必要です。

  • JSHint
$ grunt jshint:all
  • Closure Linter
$ grunt gjslint:all
  • Closure Linter(fixjsstyle)
$ grunt fixjsstyle:all
  • ぜんぶLint
$ grunt

デフォルトタスクにjshint:allとgjslint:allが設定してあります。

  • watch
$ grunt watch

変更したファイルのみjshint+gjslintして、結果をGrowlで通知します。

解説など

以下、中身の解説です。

--flagfileを渡したい

gjslintを実行するGruntタスクとしてはgrunt-closure-linterがありますが、gjslintコマンドに任意の引数が渡せないっぽかったので練習もかねてタスクを自作しました。gjslintの設定はファイルにして--flagfileオプションで渡せるようにしておくと、.jshintrcと似た設定が書けて後述のエディタ連携でも使えます。

Closure Linterの80文字制限が邪魔

Closure Linterを使ってて一番キツイのが一行80文字制限だと思います。なぜかこれはハードコーディングされていて、設定ができないという。。JSHintならmaxlenで設定できるので、Closure Linterの80文字制限は不要です。この記事を参考にして、ラッパースクリプトを追加して80文字制限を除外しました。
あとはこのラッパースクリプトをGruntfile.jsにgjslint.cmdというパラメータで記述して、それを実行するようにしています。

watchして変更したファイルだけlint

Gruntのサンプルを見ていると大体watchで全部のファイルがlintやminifyの対象になっていて、そこそこの規模のプロジェクトで使うのは厳しいです。watchの時は変更したファイルだけタスクの対象にしたいですよね。

Gruntが出てきた時にそれができなくて手を出すのをやめて、継続的にウォッチだけしていました。少し前にgrunt-contrib-watchnospawnというオプションが入って、これを使うと変更ファイルが取得できるらしい。これで勝つる!と意気込んだものの、ちょっと調べてみたらgrunt-regardeっていうやつの方が良いらしいので結局そっちを使いました。

具体的な書き方を一部抜き出すとこんな感じ。

grunt.initConfig({
  jshint: {
    all: {
      src: '<%= target %>'
    },
    watch: {
      src: '<%= grunt.regarde.changed %>'
    }
  },
  regarde: {
    js: {
      files: '<%= target %>',
      tasks: ['jshint:watch']
    }
  },
  target: ['Gruntfile.js', 'js/**/*.js']
});

jshintにwatchというターゲットを追加して、srcにgrunt.regarde.changedと指定すると、変更されたファイルだけを対象にしてタスクが実行できます。イマイチ筋の良いやり方かどうかは分かりませんが。。

ところでregardeって全然覚えられなくて困っていたら

grunt.renameTask('regarde', 'watch');

と書けることを知ってgrunt watchでregardeが動くようになりました。やったね!Gruntfile.jsもwatchで書けるようになります。

watchしてるときにエラーが出ても落ちないようにする

watchタスクの実行中にlintエラーが出るとタスク自体が終了してしまって、全然watchできない。。。オプションにforceをつけるとか何種類か回避方法はあるみたいですが。ここのやりとりを参考にして以下のようにしました。

grunt.registerTask('eatwarnings', function() {
  process.exit = function() {};
});

watchの結果をGrowl通知

Growl通知はgrunt-notifyのnotify_hooksを使うだけでできました。ただgjslintはstdoutに改行が含まれるせいか、Ubuntuのnotify-sendがうまく通知してくれませんでした。Growlでは問題ないので、ひとまず後回し。通知内容の精査もしたいけど、ひとまずwatch & notifyはできたのでここまで!

f:id:ama-ch:20130421151951p:plain

エディタ連携

最近WebStormからIntelliJ IDEAに乗り換えました。明日まで50%オフなので今のうちに買いましょう!
IntelliJ IDEA (WebStorm) はJSLint, JSHint, Closure Linterに対応していて、設定ファイルを指定するだけでエディタと連携できます。

JSHint

f:id:ama-ch:20130421153019p:plain

Closure Linter

f:id:ama-ch:20130421153024p:plain

エディタ

f:id:ama-ch:20130421155914p:plain

JSHintはちょっとバンドルされているバージョンが古いようで誤判定される部分もありますが、概ね快適に使えています。
繰り返しますが、IntelliJ IDEAはじめJetBrains製品は明日22日まで50%オフなので買うなら今がチャンスですよ!

その他

  • JSHintのindent: 2とgjslintの--jslint_error=indentationは同時に設定するとswitch文で喧嘩する。Closure野郎ならClosure Linter、そうでなければJSHintだけ有効にするのが良さそう
  • Gruntのデバッグ中は grunt --verbose --stackで動かすと色々出力される
  • node-inspectorでデバッグしたい時はnode --debug-brk $(which grunt)

おわり

JSHint+Closure Linterおすすめです。2方向から締め上げられる感覚がたまりません!

WEB+DB PRESS Vol.72のJavaScript連載でChrome Developer Toolsの解説を書きました

連載「JavaScript活用最前線」第5回目でChrome Developer Toolsの解説を書きました。

WEB+DB PRESS Vol.72

WEB+DB PRESS Vol.72

  • 作者: 近藤宇智朗,生井智司,久保達彦,道井俊介,飯田祐基,中村知成,規世やよい,後藤秀宣,天野祐介,奥野幹也,Dr.Kein,tokuhirom,森田創,中島聡,堤智代,A-Listers,はまちや2,竹原,川添貴生,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2012/12/22
  • メディア: 大型本
  • クリック: 3回
  • この商品を含むブログ (1件) を見る

console.log()や簡単なJSのデバッグ、レイアウト調整くらいはやったことがあるけど、それ以上の使い方はよく分からないという方のために、次の一歩を進んでもらいたいと思って書きました。実践的なJSのデバッグ方法を中心に解説し、Timelineパネルを使ったメモリリーク検出方法といった比較的新しい機能も扱いました。

Chrome Developer Toolsは本当に進化が早くて、執筆中でもお構いなしにバージョンが上がったりUIが変わったりするのが大変でした。でもこの開発スピードのおかげで、僕たちはいち早く便利な機能が使える訳です。このスピードは本当に凄いと思います。

個人的に気に入ってる機能は、キーボードショートカットです!特にCtrl+oで「ソースを開く」、SourcesパネルでCtrl+Shift+oで「シンボルを開く」はよく使います。

WEB+DB PRESS Vol.72は本日発売です。クリスマス年末年始の読書の一冊に、ぜひご覧いただければと思います!

oh-my-zshとhomesickを使ってdotfilesをGitHubで管理するようにした

今までdotfilesは会社で使ってるものがメインで、家やノートPCで使うものはそこからコピペしたりして使ってました。たまにDropboxで同期させてシンボリックリンクを作ったりもしていたけど、結局面倒であまりメンテしていませんでした。

そんな感じでなんとなくお茶を濁していたんですが、最近チームの開発環境がSubversionからgitに引っ越しました。大量の.gitconfigの設定とエイリアスができあがり、今も頻繁に更新しています。そうなると当然家のマシンでも同じコマンドを使いたくなり、そろそろ今の管理方法に限界を感じるようになりました。

そこで、いい加減やる気を出して、dotfilesをGitHubでうまいこと管理できないかと挑戦してみました。

前提条件

まずはzshの設定を見直し

今までは.zshrcにべたーっと設定を書いていて、会社と家の環境で微妙に追記したり削ったりして使ってました。この.zshrcがかなり長くなっていて手を焼いてたんですが、最近oh-my-zshの存在を知りました。

テーマ(PROMPT)は今使ってるのと結構変わるけど、必要な設定は普通に揃ってる感じ。oh-my-zshのプラグインの仕組みを使えば、今までの長い.zshrcを分割して管理できそう!というわけで、zshまわりはoh-my-zshに乗り換えることにしました。

homesick + GitHubでドットファイル管理

最近GitHub does dotfilesを見ていたら、homesickというよさげなプロジェクトが紹介されていることに気付きました。gemとして提供されていて、簡単にGitHubでドットファイルが管理できるらしいです。

さらっと紹介すると、

$ homesick clone リポジトリ

でGitHubのリポジトリをcloneして、

$ homesick symlink リポジトリ

リポジトリのhomeディレクトリ以下にあるドットファイルシンボリックリンクをローカルに作ってくれるものです。

更新するときはこれでいけます。

$ homesick pull リポジトリ

oh-my-zshとhomesickを使ったらよさそうだ!と思って、早速やってみました。

できあがったリポジトリ

ama-ch/dotfiles

インストール方法

README.mdに書いてあることそのまんまですが。事前にインストールしとくものを除けば、使い始めるまでの手順はこれだけです。

1. dotfilesをGitHubから取得してsymlinkを作成する

$ homesick clone ama-ch/dotfiles
$ homesick symlink ama-ch/dotfiles

2. oh-my-zshをインストールする

$ git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh

以上で、dotfilesのインストールは完了です。

設定の書き方で注意したポイントも書いときます。

oh-my-zshの設定

oh-my-zshはホームディレクトリに.oh-my-zshというディレクトリを作成します。この中に各種プラグインやテーマを追加していきます。自分のカスタマイズ内容はデフォルトだと~/.oh-my-zsh/custom以下に追加します。

普通にリポジトリにカスタム内容である .oh-my-zsh/custom を追加すると、oh-my-zshのインストールが失敗するようになってしまいます。.oh-my-zsh以下を全部pushしてしまえばいいのかも知れないけど、お行儀が良くない。そこで、.zshrcの3行目に以下の行を追加しています。

ZSH_CUSTOM=$HOME/.oh-my-zsh-custom

ZSH_CUSTOMという変数をセットすると、~/.oh-my-zsh/customの代わりにその値が使われるようになります。これで、.oh-my-zsh自体のディレクトリとカスタム設定のディレクトリを分離できます。

環境依存設定の切り出し

Ubuntuでだけ使う設定はubuntuプラグインを作ってそこに切り出しました。Macだけの設定は今のところありません。

dotfilesを書き換えたい場合

普通に書き換えてOK。例えば~/.gitconfigを書き換えると、~/.homesick/repos/ama-ch/dotfiles/home/.gitconfigを書き換えることになります。ここは普通にcloneされたgitリポジトリなので、書き換えても問題ありません。

コンフリクトさえしなければ、

$ homesick pull ama-ch/dotfiles

で普通に更新できます。コンフリクトしてしまう場合でも、普通に解消するか別ブランチを切ったりして対応すれば問題ありません。

おわり

とりあえずこんな感じです。まだ.emacsとか整理するのが面倒でpushできてない設定もありますが、GitHubで管理すると紛失したりする心配がなくて嬉しいです。

ついでにMacPortsをやめてHomebrewにしたりして色々スッキリしました。作業環境を見直すと、人生を見直す良い機会になりますね。おしまい。

はてなブログはじめました

Markdownに対応したと聞いて!

  • とりあえず使ってみます
  • よさげなら乗り換えようかなー

てすと

// コードスニペット
var hoge = 'abc';
console.log(hoge);
// ハイライトはできない?
html直書き