この記事はGoodpatchのエンジニアがお送りするGoodpatch Advent Calendar 2015の1日目の記事です!
1日目は最近Prottチームでおこなったテスト推進施策について書いてみようと思います!
私はProttというプロトタイピングツールの開発を担当しているのですが、Prottには今までサーバーサイドのコードにしか自動テストがありませんでした。
変化のサイクルが速く長期的な運用になる自社サービスは常にコードの形を変えていく必要がありますが、自動テストがないと気軽なリファクタリングをしていくことが難しくなってしまいます。
今回はテスト推進施策ということで、フロントエンド側のテスト環境構築とテストに関連する取り組みを行ったので、その内容をまとめたいと思います。
ポイントは以下の3点です!
- フロントエンドのテスト環境を作る
- → Karma + mocha + power-assert + babel でのテスト環境構築
- masterにマージされるコードは必ずテストが通っていることを保証する
- → Protected branchesの導入
- テストの実行コストを減らす
- → キャッシュの設定でCIを高速化
フロントエンドテスト環境構築
構成
- テストランナー:Karma
- テストフレームワーク:mocha
- アサーションライブラリ:power-assert
- テストコード言語:ES2015(babel使用)
- テスト対象コード言語:CoffeeScript
ProttのコードはCoffeeScriptで書かれていますが、テストコードはES2015で書こう!ということになりました!
テストコードからでも新しい記法に少しずつ慣れていけるのは嬉しいですね。
テスト環境のセットアップ
$ npm install --save-dev karma karma-browserify babelify power-assert babel-plugin-espower babel-preset-es2015 karma-coffee-preprocessor coffee-script # Karma設定ファイル生成(今回はCoffeeScriptを使用) $ ./node_modules/.bin/karma init karma.conf.coffee # 対話式でconfigファイルを生成できるので、テストフレームワークでmocha, ブラウザでPhantomJSを選択 # → 該当パッケージ(karma-mocha karma-phantomjs-launcher)がインストールされる
生成されたkarma.conf.coffeeを開いて少し編集します。
module.exports = (config) -> config.set basePath: '' frameworks: ['mocha', 'browserify'] # browserify追加 files: [ # 追加 'node_modules/power-assert/build/power-assert.js' # 忘れずに 'app/bower_components/angular/angular.js' # テスト対象コードに必要なライブラリ類 'app/bower_components/angular-mocks/angular-mocks.js' # ...省略... 'app/scripts/**/*.coffee' # テスト対象コード 'test/spec/**/*.js' # テストコード ] exclude: [] preprocessors: # 追加 'app/scripts/**/*.coffee': 'coffee' 'test/spec/**/*.js': 'browserify' # 追加 browserify: debug: true transform: [ ["babelify", plugins: ["babel-plugin-espower"]] ] reporters: ['progress'] port: 9876 colors: true logLevel: config.LOG_INFO autoWatch: true browsers: ['PhantomJS'] singleRun: false concurrency: Infinity
これでkarmaの設定ができました。
続いてbabelです。ES2015を今すぐ使えるJSに変換してくれるbabelは、バージョン6から変換機能がプラグイン形式になりました。
ES2015を変換したい場合は、babel-preset-es2015
をインストールした上でプロジェクトルートの.babelrc
に使用するプラグインを記述する必要があります。
{ "presets": ["es2015"] }
最後に test/spec/
以下にES2015で簡単なサンプルテストを作成します。
describe('sample test', () => { it('1 + 1', () => { assert(1 + 1 === 3); }); });
これで ./node_modules/.bin/karma start
(グローバルにkarma-cliを入れている場合はkarma start
)でテストが実行されます!
見やすい表示でエラーが表示されました。
ちなみに、私が開発に使用しているRubyMineではバージョン7だとES2015のシンタックスがエラー表示になってしまいました。
8にバージョンアップの上、Preferences
→Languages & Frameworks
→JavaScript
で JavaScript language version
を ECMAScript 6
にするとエラーが表示されなくなります!
Protected branchesの導入
2015年9月4日からGitHubに「Protected branches」という機能が追加され、任意のブランチを保護することができるようになりました。
Protected branchに指定されたブランチには以下の操作が禁止されます。
- ブランチの削除
- force push(コミット履歴を上書きできる強制プッシュ。
push -f
) - テストが通る前のコードのマージ(オプション)
- テストステータスを確認できないため、ローカルからの直接プッシュも禁止される → 大事なブランチへのうっかりプッシュを防げて嬉しい!
設定方法
設定したいリポジトリのSettingsタブ
Branchesを選択
Protected branchesから対象にしたいブランチを選択
テスト周りのオプションを選んで確定
注意点
たとえばmasterに対してPull Request AとBがあった場合、今まではそのまま両方をぽちぽちとmasterにマージすることができましたが、masterがProtected branchである場合にはマージ後のコードがテストに通過することを保証しなければならないため、Aをmasterへマージしたあとに逆に一度Bに対してmaster(Aの差分)をマージしてBのテストを通過させる必要があります。
少しテスト待ちの時間がかかってしまいますが、AとBそれぞれ単体ではテストに通っていたのに両方をmasterにマージしたらmasterでテストが落ちた、というような事態を防ぐことができます。
キャッシュの設定でCIを高速化
.travis.ymlに以下の指定を追加します。
sudo: false cache: directories: - node_modules - vendor/bundle
cacheのdirectoriesにnpm installとbundle install先のディレクトリを指定することでキャッシュが効き、インストール時間を大幅に短縮できます。
(bundle installのディレクトリ指定は、bundler_args
の値もしくはbefore_script
内のbundle install
に --path vendor/bundle
を追加してください)
加えて、sudo: false
を指定することでコンテナベースの環境を使用することができ、テストの開始が速くなります。
これで1回に7~9分ぐらいかかっていた実行時間が2分40秒程度に短縮されました。
参考:いまどきの.travis.yml - teppeis blog
以上3つ、最近Prottチームに取り入れたテスト推進施策をご紹介しました。
フロントエンドのテストは実行環境を構築したばかりなのでまだ数がありませんが、ES2015で書けるということもテストを書くモチベーションに加担してくれています。
コストとのバランスをとりながら、積極的にテストコードを充実させていきたいと思います!
2日目はGoodpatchが誇るサーバーサイドエンジニア、itoさんのエントリです!おたのしみにー☆