vagrant上でguardのファイル検知する

Railsvagrant上にrspec+guard+sporkな環境作ってたのだけど、guardの検知ってvagrant側からできなくね?っと思って調べたメモ。
rspec+guard+sporkの組み合わせは基本的にRailsチュートリアルと同じ構成だけど、現時点での最新版使ってるので設定方法に若干バージョン差分あった。
試してるのはRailsは4.2でrspecは3.2です。あとvagrantは1.7.2でguardは2.12.1です。

まずGemfileに以下の行を追加する。

group :development, :test do
(略)
  # for test
  gem 'rspec-rails', '~> 3.2.0'
  gem 'guard', '~> 2.12.1'
  gem 'guard-rspec', '~> 4.5.0'
  gem 'spork-rails', '~> 4.0.0'
  gem 'guard-spork', '~> 2.1.0'
  gem 'childprocess', '~> 0.5.5'
end

group :test do
  gem 'selenium-webdriver', '~> 2.44.0'
  gem 'capybara', '~> 2.4.4'
  gem 'terminal-notifier-guard', '~> 1.6.4'
  gem 'factory_girl_rails', '~> 4.5.0'
end

bundle installする。

$ bundle install

次にrspecの初期化する。

$ bundle exec rails generate rspec:install

specディレクトリ以下にいろいろファイルができる。
元々あったtestディレクトリはrspec用ではなくmini_test用のディレクトリなのでまぎらわしいので削除。

結合テストのファイル生成する。

$ bundle exec rails generate integration_test (コントローラ名)

spec/requests/(コントローラ名)_spec.rbファイルができるので、とりあえず稼働確認のためにトップページ/にアクセスして文字列取ってくる。

require 'rails_helper'

RSpec.describe "(コントローラ名)", type: :request do
  describe "Index Page" do
    it "should have the content 文字列" do
      visit '/'
      expect(page).to have_content('文字列')
    end
  end
end

あとカピバラさんのinclude書いておく。Railsチュートリアルはspec/spec_helper.rbに書いてたけど、仕様が変わったっぽくてこんなかんじのエラー出て見えない。

$ bundle exec rspec spec/requests/commits_spec.rb
/vagrant/spec/spec_helper.rb:87:in `block in <top (required)>': uninitialized constant Capybara (NameError)

ググったところ、spec/rails_helper.rbに書いておけばよいっぽい。
RailsTutorialのテスト駆動開発が上手くいかない時の対処 - Qiita

RSpec.configure do |config|
(略)
  # for test
  config.include Capybara::DSL
end

ここらで一旦稼働確認。

$ bundle exec rspec spec/requests/commits_spec.rb
(略)
1 example, 0 failures

rspecは機能してる。次にgurad。gurad初期化する。

$ bundle exec guard init rspec
09:36:21 - INFO - Writing new Guardfile to /vagrant/Guardfile
09:36:22 - INFO - rspec guard added to Guardfile, feel free to edit it

Guardfileができるので以下の行を

guard :rspec, cmd: "bundle exec rspec" do

こんなかんじでall_after_pass: falseを追加してテストがコケたら止めるようにする。

guard :rspec, cmd: "bundle exec rspec", all_after_pass: false do

guardを実行してみる。

$ bundle exec guard

適当にspecファイル更新してみたが、あれっ?検知しない。。。

ん?あーーーーー、ファイル更新してるのは手元のMacrailsとguardはvagrant上で起動しててファイル共有で見せてるのでイベント拾える訳ないやん。。。そりゃそうだ。

なんかよい方法ないかと、ググってみたら解決策発見。
http://dev.akinaka.net/2014/01/16/vagrant-nfs-guard
guradに-p付けたらguard側からポーリングさせられるっぽい。

$ bundle exec guard -p
10:10:11 - INFO - Guard::RSpec is running
10:10:43 - INFO - Guard is now watching at '/vagrant'

これでMac側でファイル変更しても検知するようになった。

あとはsporkであらかじめrails環境読み込んで高速化する。

$ bundle exec spork --bootstrap
Using RSpec, Rails
Bootstrapping /vagrant/spec/spec_helper.rb.
Done. Edit /vagrant/spec/spec_helper.rb now with your favorite text editor and follow the instructions.

spec/spec_helper.rbにsporkのコードが追加されてしまったようなので、手動でspec/rail_helper.rb側に記載するようにこんなかんじで修正。

require 'rubygems'
require 'spork'

Spork.prefork do
  ENV['RAILS_ENV'] ||= 'test'
  require 'spec_helper'
  require File.expand_path('../../config/environment', __FILE__)
  require 'rspec/rails'
(略)
  RSpec.configure do |config|
(略)
    # for test
    config.include Capybara::DSL
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.

end

spork起動する

$ bundle exec spork &
Using RSpec, Rails
/vagrant/spec/spec_helper.rb has not been bootstrapped.  Run spork --bootstrap to do so.
Preloading Rails environment
Spork is ready and listening on 8989!

この状態でguard起動すればOK。

$ bundle exec guard