Murayama blog.

プログラミングと、その次の話

Rails4.1でSpring、Rspec、Guardを使う

はじめに

Rails4.1でテスト環境を構築する方法を調べてました。以下のブログ(英語、、)が参考になったので紹介します。
Setup Rails 4.1, Spring, Rspec, and Guard - Girders

Setup Rails 4.1, Spring, Rspec, and Guard

Rails4.1では、Springを使うことでrailsコマンドやrakeコマンドの起動を素早く実行することができます。Springはアプリケーションのバックグラウンドで動作し、アプリケーション起動時のもろもろの動作をサポートします。Springに関連する情報を見つけるのに苦労してので、ここにまとめておきます。

私はテストフレームワークRSpec、テストランナーのイベントウォッチャーにGuardを使っています。Springを使えば、エディタで編集したファイルを速やかにテストしてくれるようになります。

はじめに検証用のアプリケーションを作るところから始めましょう。もちろん、既存のアプリケーションでもこれから紹介する方法で上手くいくと思います。Rails 4.1.0.beta1 on Ruby 2.1.0p0で動作検証済みです。

% rails new myapp -T
% cd myapp
% vim Gemfile

Gemfileを編集し次のgemを追記します。

  • rspec-rails - Rails用のRSpecテスティングフレームワーク
  • spring-commands-rspec - springにrspecコマンドを追加する。Railsアプリケーションのプレローダ機能も含む
  • guard-rspec - rspecを実行するためにGuardファイルウォッチャ
  • rb-fsevent - OS/Xでのみ必要。Mac OS/X FSEvents APIを通じでファイルの変更を監視する

Gemfileには次のように記述するとよいでしょう。(もちろんgemのバージョンも記述してもかまいません)

group :development, :test do
  gem 'spring-commands-rspec'
  gem 'rspec-rails'
  gem 'guard-rspec'
  gem 'rb-fsevent' if `uname` =~ /Darwin/
end

"Bundle"をもう一度実行して、依存関係のあるgemをインストールします。

% bundle install

Setup Spring

springコマンドは、springアプリケーションランナーを介してコマンドを実行します。デフォルトでは、railsコマンドrakeコマンドのみ設定されています。ここにプラグイン(gem)を追加すれば、rspecコマンドを実行することができるようになります。

springにはbinstubというサブコマンドがあります。このサブコマンドを使えばmyapp/binのスクリプトを更新できます。

springでrspecコマンドを利用できるようにするために、次のコマンドを実行します。

% spring binstub --all
* bin/rake: spring already present
* bin/rspec: generated with spring
* bin/rails: spring already present

springがバックグラウンドで起動しているかどうかはstatusサブコマンドで確認できます。springが有効となっているコマンドを使ってサーバを起動してみましょう。

springの初回起動時はRailsのイニシャライザを実行するので時間がかかります。springはアプリケーションサーバを起動したら、結果を速く返すためにプロセスをフォークしています。

% spring status
Spring is not running.
% rails g
...
% spring status
Spring is running:

89168 spring server | myapp | started 5 secs ago
89170 spring app    | myapp | started 5 secs ago | development mode

springサーバはshellのセッションが終了するときに自動的にシャットダウンされます。明示的にシャットダウンしたい場合は、次のようにコマンドを入力します。

% spring stop
Spring stopped.

springを利用するのに必須となる知識はこれだけです。

Setting up Rspec and Guard

このプロセスも通常のやり方と同じです。

% rails g rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
% guard init
11:32:14 - INFO - Writing new Guardfile to /Users/allen/src/myapp/Guardfile
11:32:14 - INFO - rspec guard added to Guardfile, feel free to edit it
% vim Guardfile

上記のコマンドでrspecとguardに必要なファイルをセットアップします。次に、guardに対してrspecを使うときにspring runnerを使用することを伝えなければなりません。Guardfileを編集して、rspecコマンドをspring rspecコマンドに変更します。

guard :rspec do

上記の部分を次のように変更します。

guard :rspec, cmd:"spring rspec" do

Running

(ここで紹介する実行方法は、binstubs、shell、aliasなど、コマンドの実行方法はあなたの環境に依存します。bundle execやbin/railsのように環境に合わせて解釈してください)

springを使用するとrspecがどの程度速くなるのかチェックしてみましょう。ここではtimeコマンドを使います。

% time spring rspec
...
spring rspec  0.12s user 0.07s system 6% cpu 3.126 total

% time spring rspec
...
spring rspec  0.12s user 0.06s system 30% cpu 0.600 total

上記の実行結果は一つのscaffoldリソースをもつシンプルなアプリケーションで試したものです。アプリケーションが大きくなるに連れて、初回起動に必要な時間は長くなります。つまり、節約できる時間も増えていくことでしょう。

TDDを始めるなら、ターミナルセッションでguardを起動しましょう。

% guard
11:48:02 - INFO - Guard is using TerminalTitle to send notifications.
11:48:02 - INFO - Guard::RSpec is running
11:48:02 - INFO - Guard is now watching at '/Users/allen/src/myapp'
[1] guard(main)>

アプリケーションのファイルがguardによって監視され、specやsuiteが変更されるたびに、spring rspecコマンドが実行されるようになります。

gemファイルの追加など、キャッシュされているローカルの依存関係を更新したい場合は、guardとspringを再起動する必要があります(guardは"ctrl-D"、springはspring stopを実行するなど)。guardを再起動すればspringも再起動されるので、依存関係がリロードすることができるでしょう。