本文所使用的开发环境:
rvm 1.8.3
ruby 1.9.2p290
Rails 3.0.3
Rspec 2.11.0
DB sqlite3
Rspec是什么
Rspec是基于ruby的测试工具,产生于BDD思想。它的代码比Test::Unit更好阅读,开发人员更容易描述测试目的,类似于可执行的规则文件。
Rspec在Rails中的测试分为Model测试、Controller测试、View测试、Helper测试和Route测试。
准备
创建测试项目,因为是学习,强烈建议不要在现有商业项目中做学习。
$ rails new rspec_study
安装
在Gemfile文件中添加如下代码:
group :test, :development do
gem "rspec", "~> 2.0"
gem "rspec-rails", "~> 2.0"
end
安装gem文件:
$ bundle install
在项目中安装rspec:
$ rails generate rspec:install
如果打印如下结果,则安装成功:
create .rspec
create spec
create spec/spec_helper.rb
执行测试(执行前请确认config/database.yml中的test数据库与其它两个数据库不同):
$ bundle exec rake spec
注意:rake spec会先执行一次 rake db:test:prepare 以创建测试数据库,而创建测试数据库时需要db/schema.rb,所以对于新项目,一定要执行 rake db:migrate 以生成 schema.rb文件。否则,在执行测试命令时会有如下提示:
rspec_study/db/schema.rb doesn't exist yet. Run "rake db:migrate" to create it then try again.
基本语法
先上代码,如下:
require 'spec_helper' describe User do before(:all) do end
def happy_test # 这是一个帮助方法
end
it "should be very happy if you love your job" do end it "should be very happy if you don't love your job" do pending("bug 0001") do end end after(:each) do end end
describe方法
describe方法用于定义一组测试用例,其参数可以是测试的类对象(例如User),也可以是字符串。describe方法可以嵌套。
it方法
it方法用于定义一个具体的测试用例(在Rspec中,一个测试用例称为一个example)。
before和after方法
很多测试框架都支持这两个方法,它们的参数作如下说明:
before(:all) 每段describe之前只执行一次
before(:each) 每段it之前执行一次
after(:all) 每段describe之后只执行一次
after(:each) 每段it之后执行一次
帮助方法:
将多个测试用例所使用的共同方法抽取成为一个公用的方法,提高代码重用。如例子中的happy_test()方法。
Model测试
首先生成一个Model
$ rails generate model user name:string age:integer gender:boolean card_id:string mail:string
可以看到,自动生成一个测试文件“spec/models/user_spec.rb”:
invoke active_record
create db/migrate/20120708033206_create_users.rb
create app/models/user.rb
invoke rspec
create spec/models/user_spec.rb
执行Model测试
$ bundle exec rspec spec/models/user_spec.rb
测试执行结果如下:
*
Pending:
User add some examples to (or delete) rspec_study/spec/models/user_spec.rb
# No reason given
# ./spec/models/user_spec.rb:4
Finished in 0.00718 seconds
1 example, 0 failures, 1 pending
Randomized with seed 60625
一个完整的测试故事
# encoding: UTF-8 require 'spec_helper' describe Order do context "with validates" do it "should be false if name is null" do @order = Order.new @order.valid?.should be_false end pending "should be false if total is null or less than zero" end it "should discount 5 percent if no billing" do # 如果未开发票少付费5% @order = Order.new(:total => 100, :billing => true) @order.payables.should == 95 end it "should discount 20 percent if member" do # 如果是会员少付费20% @order = Order.new(:total => 100, :is_member => true) @order.payables.should == 80 end it "should discount 22 percent if member and no billing" do # 如果是会员且未开发票则少付费22% pending "bug #001 from redmine" end end
Controller测试
不再痛苦
以下提供一些可以提高测试开发效率的工具:
Watchr是一种Continuous Testing的工具。程序修改完成保存后,自动跑对应的测试。可以大大节省时间。
Shoulda提供了更多Rails专用的Matchers。
RCov用来统计测试覆盖率。有些团队会追求100%测试覆盖率,虽然很好,但是记得Coverage只是手段,不是测试的目的。
提示
本文的ruby环境是基于rvm的,所以编译安装的需要修改为ruby默认命令。
参考
https://github.com/rspec/rspec
《The Rspec Book》,目前貌似只有英文版的。