rails3结合RSpec,Capybara,Guard和Spork进行BDD测试实践小结

阅读更多

Part 1一rails3结合RSpec和Capybara进行BDD测试

之前有听闻rspec结合cucumber进行BDD测试的一些东西,这次的项目使用rspec结合capybara进行BDD。以下为大致流程:

 

1.新建工程,修改gemfile,添加:

 

group :test do
  gem 'capybara', '1.1.2'
  gem 'rspec-rails', '2.10.0'
end
2.运行bundle进行gem的安

3.生成rspec,运行:
rails g rspec:install

4.生成为进行测试的静态页面
rails generate controller StaticPages home help --no-test-framework
5.生成集成测试的页面
rails generate integration_test static_pages

6.写测试代码

 

spec/requests/static_pages_spec.rb
require 'spec_helper'

describe "Static pages" do

  describe "Home page" do

    it "should have the content 'Sample App'" do
      visit '/static_pages/home'
      page.should have_content('Sample App')
    end
  end
end

基本上着一块会自动生成一些,结合自身项目的实际以及测试需要进行改动就可以了。

 

7.运行rspec

 

bundle exec rspec spec/requests/static_pages_spec.rb

8.根据提示进行适当的修改。这里我列出toturial中给出的一个模板:

 

require 'spec_helper'

describe "StaticPages" do
  describe "Home page" do
    it "should have the h1 'Sample App'" do
      visit '/static_pages/home'
      page.should have_selector('h1', :text => "Sample App")
    end
  	it "shoudl have the right title'Home'" do
  		visit "/static_pages/home"
  		      page.should have_selector('title',
                        :text => "Ruby on Rails Tutorial Sample App | Home")

  	end
  end

  describe "help page" do
  	it "should have the h1 'help'" do
  		visit'/static_pages/help'
  		page.should have_selector('h1', :text => "Help")
  	end
  	it "should have the right title" do
  		visit "/static_pages/help"
  		page.should have_selector('title',
  					:text => "Ruby on Rails Tutorial Sample App | Help")
  	end
  	it "should have the content 'help'" do
  		visit "/static_pages/help"
  		page.should have_content('help')
  	end
  end

  describe "about page" do
  	it "should have the  h1 'About Us'" do
  		visit'/static_pages/about'
  		page.should have_selector('h1', :text => "About Us")
  	end
  	it "should have the right title 'About Us'" do
  		visit "/static_pages/about"
  		page.should have_selector('title',
  					:text => "Ruby on Rails Tutorial Sample App | About Us")
  	end
  end

end

Part 2 - 加入Gurad 进行BDD测试

Guard能够实时地更新测试,对于使用之前的方法来说,有了很大的改进。具体步骤如下

1.修改gemfile文件,加入:

 

  gem 'guard-rspec', '0.5.5'

 

2.然后,我们需要替换掉test group中的评论,这需要一些依赖于系统的设置。(我自己的是Linux环境,配置如下)

 

# Test gems on Linux
group :test do
  gem 'capybara', '1.1.2'
  gem 'rb-inotify', '0.8.8'
  gem 'libnotify', '0.5.9'
end 

Mac平台配置如下:

 

# Test gems on Macintosh OS X
group :test do
  gem 'capybara', '1.1.2'
  gem 'rb-fsevent', '0.4.3.1', :require => false
  gem 'growl', '1.0.3'
end 

 

3.运行bundle install

 

4.初始化Guard:

 

$ bundle exec guard init rspec

 

5.编辑Guardfile,来让Guard在集成测试和view更新的情况下运行正确的测试(在默认文件内容上添加)

 

require 'active_support/core_ext'

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

 

其中guard 'rspec', :version => 2, :all_after_pass => false do确保在测试出现failing的时候,不再执行后面的测试。

 

6.运行guard

 

$ bundle exec guard

 

这样就可以看到在页面上的提醒

 

note:如果想要不使用bundle exec前缀需要按照前面介绍的方法,重新来过。

 

$ rvm get head && rvm reload
$ chmod +x $rvm_path/hooks/after_cd_bundler
$ cd ~/rails_projects/sample_app
$ bundle install --without production --binstubs=./bundler_stub

 

Part 3 用spork加速测试

当我们运行rspec的时候,你可能注意到,启动test的时候会花费好几秒钟,但是一旦启动,会很快完成测试。这是因为每一次RSpec运行测试的时候,会重新加载整个rails的环境,那使用Spork test server就是为了解决这个问题。Spork加载一次环境,并且维护着一个进程池给将来运行的test。Spork跟Guard结合起来使用,将会异常强大。

 

下面简单介绍其步骤:

1.还是老套路,先修改gemfile文件,如下:

 

source 'https://rubygems.org'

gem 'rails', '3.2.7'
.
.
.
group :test do
  .
  .
  .
  gem 'guard-spork', '0.3.2'
  gem 'spork', '0.9.0'
end

 

2.运行bundle install安装依赖的gem

 

3.接着,引导Spork配置,运行

 

$ bundle exec spork --bootstrap
4.我们需要编辑位于spec/spec_helper.rb下的RSpec配置文件。给Spork.perfork部分添加环境。

 

spec/spec_helper.rb
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

 

5.在运行Spork之前,我们可以通过衡量我们test suite的得到我们test的基准时间,如下

 

 

$ time bundle exec rspec spec/requests/static_pages_spec.rb
......

6 examples, 0 failures

real	0m8.633s
user	0m7.240s
sys	0m1.068s

 

6.这里,test suite花费了超过7秒的时间,尽管实际测试运行的时间,差不多1/10秒。为了加速,我们开一个专用的终端窗口,指向项目的根目录,然后运行Spork server

 

$ bundle exec spork
Using RSpec
Loading Spork.prefork block...
Spork is ready and listening on 8989!

7.现在,我们可以运行我们的test suite,使用--drb(“distributed Ruby”)选项,并且确保时间减少了。

 

$ time bundle exec rspec spec/requests/static_pages_spec.rb --drb
......

6 examples, 0 failures

real	0m2.649s
user	0m1.259s
sys	0m0.258s

效果相当明显

 

8.每次在运行rspec的时候,运行-drb 选项很不方便,因此,我们可以这样做:将它加到.rspec文件。

 

.rspec
--colour
--drb

9.使用Spork的建议:每次改变了相关的文件之后,需要重启Spork server,来加载新的rails环境。如果你认为测试该通过,但是没通过的时候,使用ctrl+c退出Spork server,并且重启。

 

$ bundle exec spork
Using RSpec
Loading Spork.prefork block...
Spork is ready and listening on 8989!
^C
$ bundle exec spork

10.Spork在使用Guard的时候,尤其管用,因此我们这样设置

 

$ bundle exec guard init spork

11.然后,我们需要改变guardfile的内容:

The Guardfile updated for Spork.

 

require 'active_support/core_ext'

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

12.有了上面的配置,我们就可以同时启动guard和Spork,使用guard命令

 

 

$ bundle exec guard

你可能感兴趣的:(测试)