Gem Rails 3.2.13 使用 Spork + Guard + RSpec + Capybara

juanito · 发布于 2012年04月30日 · 最后由 juanito 回复于 2016年06月07日 · 9300 次阅读
1510

读这篇比我的好

Ruby on Rails 教程第二版,3.6 高级技术

比较匆忙的同学请看

  1. rails new appname --skip-test-unit --skip-bundle
  2. 复制 Gemfile,替换掉项目下的 Gemfile:
  • OSX

  • Linux

  • Windows

    安装需要的 Gems,你有两个选择:

    • bundle install ,之后使用 bundle exec xxx
    • bundle install --binstubs ,之后使用 bin/xxx
  1. rails generate rspec:install
  2. 运行 bin/guard init rspec && bin/guard init spork
  3. 复制这个 Guardfile,覆盖掉项目下的 Guardfile。
  4. 添加 --drb 至项目的根目录下的 .rspec
  5. 复制这个 spec/spec_helper.rb,覆盖 spec/spec_helper.rb

  6. bundle exec spork --bootstrapbin/sprok --bootstrap

  7. bundle exec guardbin/guard

-- FINISH --

有10分钟的同学请看

为什么使用 Guard

  1. 要切回终端机敲 RSpec 命令
  2. 启动速度太慢(使用 Spork 来加速)

Guard 人如其名,自动侦测改动并运行测试。

配置

添加 guard-rspec gem:

Gemfile:

group :development, :test do  
  gem 'guard-rspec', '1.2.1'
end

:test group 加入一些相依的 Gems,OSX 可能需要安装 growl-notify

Growlnotify 效果圖:

*Growlnotify* 效果圖

MacOSX

gem 'rb-fsevent', '0.9.1', :require => false
gem 'growl', '1.0.3'

Linux

gem 'rb-inotify', '0.8.8'
gem 'libnotify', '0.5.9'

Windows

gem 'rb-fchange', '0.0.5'
gem 'rb-notifu', '0.0.4'
gem 'win32console', '1.3.0'

范例 Gemfile,放在 Gist:

MacOSX / Linux / Windows

Gemfile 配置好运行 bundle install ,初始化 Guard:

bundle exec guard init rspec

或是运行 bundle install --binstubs,初始化 Guard:

bin/guard init rspec

会产生一个 Guardfile,最上方加入此行:

require 'active_support/core_ext'

并改动此行 guard 'rspec', :version => 2 do

guard 'rspec', :version => 2, :all_after_pass => false do

确保 Guard 一个失败测试通过以后,不会运行所有的测试(加快 红绿重构 周期)

再添加:

guard 'rspec', :version => 2, :all_after_pass => false do
  .
  .
  .
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  do |m|
    ["spec/routing/#{m[1]}_routing_spec.rb",
     "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb",
     "spec/acceptance/#{m[1]}_spec.rb",
     (m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" :
                       "spec/requests/#{m[1].singularize}_pages_spec.rb")]
  end
  watch(%r{^app/views/(.+)/}) do |m|
    (m[1][/_pages/] ? "spec/requests/#{m[1]}_spec.rb" :
                       "spec/requests/#{m[1].singularize}_pages_spec.rb")
  end
  .
  .
  .
end

当 integration tests 及 views 有变动时,会自动运行测试。

这些都设置好了,启动 guard

bundle exec guard

bin/guard

更多信息请参考:Guard Github 页面

使用 Spork 来加速测试

运行 RSpec 很慢的原因是每次都得重加载整个 Rails 环境。Spork 测试服务器透过加载 Rails 环境,并维护一个进程池(pool of processes)给之后的测试使用。跟 Guard 搭配使用顺风顺水。

配置 Gemfile,将此行加入 :test group

gem 'guard-spork', '0.3.2'
gem 'spork', '0.9.0'

范例 Gemfile,放在 Gist:

运行 bundle install 并运行 spork :

bundle exec spork --bootstrap

运行 bundle install --binstubs 并运行 spork:

spork --bootstrap # or bin/spork --bootstrap

添加需加载的环境信息至 spec/spec_helper.rb 里的 Spork.prefork

require 'rubygems'
require 'spork'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.
  # This file is copied to spec/ when you run 'rails generate rspec:install'
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

  RSpec.configure do |config|
    # == Mock Framework
    #
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
    #
    # config.mock_with :mocha
    # config.mock_with :flexmock
    # config.mock_with :rr
    config.mock_with :rspec

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false
  end
end

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

end

启动 Spork 服务器:

之前使用 bundle install

bundle exec spark

之前使用 bundle install --binstubs

bin/spork

加入此行至 .rspec ,让 RSpec 缺省使用 spork:

--drb

提示

如果改动了 routes.rb 需重启 Spork 服务器,如果你觉得测试是对的,但是失败了,也可以重启 Spork 服务器试试看。

更多信息请参考 Spork Github 页面

Guard 搭配 Spork

有了 Guard 与 Spork 以后,让它们合体:

bundle exec guard init spork
bin/guard init spork

加入此段代码至 Guardfile:

guard 'spork', :rspec_env => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.+\.rb$})
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb')
  watch('test/test_helper.rb')
  watch('spec/support/')
end

guard 'rspec', :version => 2, :all_after_pass => false, :cli => '--drb' do
  .
  .
  .
end

现在全都设定好了,以后只要

bundle exec guardbin/guard

Guard 就会自动启动 Spork 服务器并侦测你的改动!

一个常见的错误

ERROR: Could not start Spork server for Test::Unit & RSpec after 30 seconds.

如果没有使用 Test::Unit ,把 test/ 目录移除或更名即可。

:D

共收到 20 条回复
535

不错。

96

不错,不过建议楼主可以用guard-spork,这样一个guard可以全包了

贴一个傻瓜型Gemfile 带了guard,livereload等等一体化自动测试

require 'rbconfig'
HOST_OS = RbConfig::CONFIG['host_os']
source 'http://rubygems.org'

gem 'rails', '3.2.3'

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'rspec-rails' ,:group => [:development,:test]

# jquery-ui
# gem 'jquery-ui-rails'

# bootstrap
# gem 'anjlab-bootstrap-rails', :require => 'bootstrap-rails',:git => 'git://github.com/anjlab/bootstrap-rails.git'

if HOST_OS =~ /linux/i
  gem 'therubyracer', '>= 0.8.2'
end
case HOST_OS
  when /darwin/i
    gem 'rb-fsevent', :group => :development
    gem 'growl', :group => :development
    gem 'guard-pow', :group => :development
  when /linux/i
    gem 'libnotify', :group => :development
    gem 'rb-inotify', :group => :development
  when /mswin|windows/i
    gem 'rb-fchange', :group => :development
    gem 'win32console', :group => :development
    gem 'rb-notifu', :group => :development
end


# Use unicorn as the web server
# gem 'unicorn'

# Deploy with Capistrano
# gem 'capistrano'

# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'

group :test do
  # Pretty printed test output
  gem 'turn', :require => false
  gem 'factory_girl_rails' , "~> 1.1.0" ,:require => false
  gem 'database_cleaner', ">= 0.6.7"
  gem 'mongoid-rspec', ">= 1.4.4"
  gem "capybara",">= 1.1.1"
  gem "launchy", ">= 2.0.5"
  gem 'guard-spork'
  gem 'spork', '~> 0.9.0'
  gem "guard-rspec"
  gem 'guard-livereload'
  gem 'guard-bundler'
end



执行guard init 然后按照需要调整Guardfile,确保spork在rspec的上面

# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'livereload' do
  watch(%r{app/.+\.(erb|haml)})
  watch(%r{app/helpers/.+\.rb})
  watch(%r{(public/|app/assets).+\.(css|js|html)})
  watch(%r{(app/assets/.+\.css)\.s[ac]ss}) { |m| m[1] }
  watch(%r{(app/assets/.+\.js)\.coffee}) { |m| m[1] }
  watch(%r{config/locales/.+\.yml})
end

guard 'pow' do
  watch('.powrc')
  watch('.powenv')
  watch('.rvmrc')
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.*\.rb$})
  watch(%r{^config/initializers/.*\.rb$})
  watch(%r{^config/settings(\.local)?\.yml$})
end

guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch(%r{^config/environments/.+\.rb$})
  watch(%r{^config/initializers/.+\.rb$})
  watch('spec/spec_helper.rb')
end

guard 'rspec', :version => 2 ,:cli => "--drb",:notification => true do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec/" }

  # Rails example
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^lib/(.+)\.rb$})                           { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec/" }
  watch('spec/spec_helper.rb')                        { "spec/" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }
  # Capybara request specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }
end

然后参照楼主的文章设置一下spec_helper.rb

执行guard即可开始自动测试,自动重启服务,自动bundle等等

1510

#3楼 @aNdReW_Qx 谢谢提醒,我也有用 guard-spork,好用!

304

guard挺好的,只是我每写几行代码就很习惯地保存一下,guard跑个不停...而且有时会出现一些灵异错误怎么跑都跑不过,最后重启guard才过了,可能没配置好。@Juanito 有没有出现过这种问题?

1510

#5楼 @Zernel 有些改动需要重启才能测试。。。比如改了个 route,要是觉得测试对了,但是跑不过,就重启 guard 吧。

304

#6楼 @Juanito 现在在做的项目没有选用guard,等下次用的时候参考下你的配置,谢谢分享XD

96

不错,很帅。

861

#3楼 @aNdReW_Qx 这个Gemfile非常适合经常在不同系统上写同一个项目的人。

96

#9楼 @AlphaLiu 嗯,你可以配合:platform => :jruby 这样的使用, 另外如果经常跨平台,注意再gemfile里限gem版本,然后不要让Gemfile.lock进入repo

861

#3楼 @aNdReW_Qx 有个问题,guard-livereload怎么连不上浏览器呢?我都已经装了浏览器扩展,但是当我修改一个view的时候,浏览器都没有自动刷新。我在ubuntu下,guardfile里面的pow段没用,被我删掉了。

1031

看了这篇文章, 才真正知道咱社区常说的Guard是个啥玩意儿.

之前一直以为是一个Mac下专用的,类似于autotest的玩意儿, 现在才明白, Guard原来是全方位的...

太谢谢@Juanito啦.

3672

archlinux+openbox通知测试结果失败?

3547

学习了。

16楼 已删除
96

bundle exec guard init spec ,新版本中应改为 bundle exec guard init rspec ,另外, 在windows xp,还需要 gem wdm ,否则出错。

96

另外,问下,怎么取消提示音。。

96

我这边windows7 用unit test 在opensuse下什么问题都没有 切windows下面提示,然后修改文件是没有反应的。也就是说没有监视到文件的变化

Please add the following to your Gemfile to avoid polling for changes:
  require 'rbconfig'
  if RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwin/i
    gem 'wdm', '>= 0.1.0'
  end

然后我加了wdm,再然后

11:21:07 - INFO - Guard is now watching at 'F:/src/guard'
Process finished with exit code -1073741819

rubymine中会有Process finished with exit code -1073741819 而cmd终端显示now watching之后就直接显示 F:\src\guard>

同样的代码,opensuse完全木有问题,求问是怎么回事

guardfile

guard 'spork', :test_unit => true, :test_unit_env => {'RAILS_ENV' => 'test'}, :wait => 60 do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb') { :rspec }
  watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard :test, :drb => true, :all_after_pass => false, :all_on_start => false do
  watch(%r{^test/.+_test\.rb$})
  watch('test/test_helper.rb')  { 'test' }

  # Non-rails
  watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
  watch(%r{^app/models/(.+)\.rb$})                   { |m| "test/unit/#{m[1]}_test.rb" }
  watch(%r{^app/controllers/(.+)\.rb$})              { |m| "test/functional/#{m[1]}_test.rb" }
  watch(%r{^app/views/(.+)/.+\.erb$})                { |m| "test/functional/#{m[1]}_controller_test.rb" }
  watch(%r{^app/views/.+$})                          { 'test/integration' }
  watch('app/controllers/application_controller.rb') { ['test/functional', 'test/integration'] }
end

gemfile

source 'https://ruby.taobao.org'
require 'rbconfig'
if RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwin/i
  gem 'wdm', '>= 0.1.0'
end
  ...
group :development, :test do
    gem "guard-rails"
    gem 'spork-testunit'
    gem 'guard-spork'
    gem 'guard-test', '~> 1.0.0'
    gem 'ruby-prof' 
    gem 'pry'
    gem 'pry-nav'
  gem 'childprocess'
end

group :test do
  gem "shoulda", "> 3.3.2"
  gem "mocha", "~> 0.13.3"
  gem 'capybara', '~> 2.0.0'
  gem 'nokogiri', '< 1.6.0'
  gem 'factory_girl'
  gem 'rb-fchange', '0.0.5'
  gem 'rb-notifu', '0.0.4'
  gem 'win32console', '~>1.3.0'
end
  ...
6829

经典好帖!

1510 juanito 1000 个小时学会 Rails - 004 神秘的 X 项目 中提及了此贴 06月07日 21:43
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册