1 对象.should(_not) be_方法 :应该(不应该)怎么样,方法的返回值为true/false
describe User do
it "should be in any roles assigned to it" do
user = User.new
user.assign_role("assigned role")
user.should be_in_role("assigned role")
end
it "should not be in any roles unassigned to it" do
user = User.new
user.assign_role("assigned role")
user.should_not be_in_role("unassigned role")
end
end
2 before/after(:each/:all) do end
before(:all) do
# 会在所有example运行前被调用一次
end
before do
# 与before(:each)相同,会在每个example运行前被调用一次
end
after(:each) do
# 会在每个example运行完后被调用一次
@post.destroy unless @post.new_record?
end
after(:all) do
# 会在所有examples运行完之后被调用一次
Post.destroy_all
end
实例:
describe Post do
before(:each) do
@post = Post.new(valid_post_hash) # grabs the hash below
end
it "should be valid" do
@post.should be_valid
end
it "should not be valid without a title" do
@post.title = ''
@post.should_not be_valid
end
it "should not be valid without a body" do
@post.body = ''
@post.should_not be_valid
end
def valid_post_hash
{:title => 'test', :body => 'test body'}
end
end
3 走验证should be_valid
实例:
post.should be_valid
4 基本语法
Strings:
'foo'.should == 'foo'
'foo'.should === 'foo'
'foo'.should_not equal('foo')
''.should be_empty
'foo with bar'.should include('with')
'http://fr.ivolo.us'.should match(/http:\/\/.+/i)
nil.should be_nil
Numbers:
100.should < 200
200.should >= 100
(200 - 100).should == 100
# (100 - 80) is less than 21
100.should be_close(80,21)
Arrays:
[1,2,3].should have(3).items
[].should be_empty
[1,2,3].should include(2)
Hashes:
{}.should be_empty
{:post => {:title => 'test'}}.should have_key(:post)
{:post => {:title => 'test'}}.should_not have_key(:title)
false.should be_false
true.should be_true
Records:
# assuming @post = Post.new(:title => 'test')
@post.should be_instance_of(Post)
@post.should respond_to(:title)
5 有关数据库的操作
实例:
def comment
@post = Post.find(params[:id])
@comment = Comment.new(params[:comment])
respond_to do |format|
if @comment.save && @post.comments.concat(@comment)
flash[:notice] = 'Comment was successfully updated.'
format.html { redirect_to post_path(@blogger, @post) }
format.xml { head :o k }
else
flash[:notice] = 'Error saving comment.'
format.html { redirect_to post_path(@blogger, @post) }
format.xml { render :x ml => @comment.errors.to_xml }
end
end
end
我需要确保我能够对帖子发布评论:
it "should add comments to the post" do
post = posts(:one)
comment_count = post.comments.size
post :comment, :id => 1, :comment => {:title => 'test', :body => 'very nice!'}
post.reload
post.comments.size.should == comment_count + 1
flash[:notice].should match(/success/i)
response.should redirect_to(posts_path(@blogger, @post))
end
看起来不错?但这个测试例实际测试了许多不该它来测试的东西,它应该只测试action,但是它却连同model也一并测试了,并且它还依赖于fixtures。
我们可以使用一个mock object来代替真是的post对象:
post = mock_model(Post)
现在我们需要关注comment的第一行:
@post = Post.find(params[:id])
我希望这一行在测试时得到执行,但是不用测试,我也知道这行代码肯定是工作正常的,因此,我现在要做的就是让这行代码返回我在上面创建的那个mock object:
Post.should_receive(:find).and_return(post)
或者这样:
Post.stub!(:find).and_return(post)
但 是请注意,should_receive和stub!虽然都可以让Post.find返回我的mock object,但是他们的区别却是巨大的,如果我调用了stub!,但是却没有调用Post.find,stub!不会抱怨什么,因为它是个老实人,但是 should_receive就不用,如果我告诉should_receive我会调用Post.find,但却没调用,那问题就来了,它会抱怨为何我不 守信用,并抛出一个异常来警告我。
但是跟在他们后面的and_return的作用却是完全相同的,它让你mock或者stub的方法返回你传递给它的任何参数。
接下来,我需要对comment做同样的事情:
comment = mock_model(Comment)
Comment.should_receive(:new).with({:title => 'comment title', :body => 'comment body'}).and_return(comment)
接下来我需要关注这条语句:
if @comment.save && @post.comments.concat(@comment)
同上面一样:
comment.should_receive(:save).and_return(true)
post.comments.should_receive(:concat).and_return(comment)
下面我需要测试flash及redirect:
flash[:notice].should match(/success/i)
response.should redirect_to(posts_path(blogger, post))
现在,还剩下最后一件事情:这个action必须使用blogger变量来进行重定向,这里我使用instance_variable_set来完成这个工作:
blogger = mock_model(User)
@controller.instance_variable_set(:@blogger, blogger)
基本就是这样,下面是将部分代码放入before中的完整代码:
describe PostsController, "comment", :behaviour_type => :controller, do
before do
@post = mock_model(Post)
Post.should_receive(:find).and_return(@post)
@comment = mock_model(Comment)
Comment.should_receive(:new).with.({:title => 'comment title', :body => 'comment body'}).and_return(@comment)
@blogger = mock_model(User)
@controller.instance_variable_set(:@blogger, @blogger)
end
it "should add comments to the post" do
@comment.should_receive(:save).and_return(true)
@post.comments.should_receive(:concat).and_return(@comment)
post :comment, :id => @post.id, :comment => {:title => 'comment title', :body => 'comment body'}
flash[:notice].should match(/success/i)
response.should redirect_to(posts_path(@blogger, @post))
end
end
分享到:
相关推荐
请查看以下文章,了解新的RSpec语法和RSpec 3中的更改:如果要在升级到RSpec 3的过程中使用Transpec,请阅读RSpec官方指南:例子这是一个示例规范: describe Account do subject ( :account ) { Account ....
原版The RSpec Book并附有源码
rspec出入门者学习理解,介绍的非常的详细、清楚; 欢迎下载学习~
rspec 下载请注意:英文文档
rspec_api_documentation, 从RSpec自动生成API文档 RSpec Doc为你的Rails API生成漂亮的。查看一个示例文件。更改请查看维基以了解最新的更改。安装将rspec_api_documentation添加到你的文件gem 'rspec_a
RSpec :: Wait允许您使用已经知道和喜欢的RSpec语法糖来等待声明通过。 RSpec :: Wait将继续尝试,直到您的断言通过或超时为止。 例子 RSpec :: Wait的wait_for断言几乎替代了RSpec的expect断言。 主要区别在于...
jruby-1.5.5+OperaWatir+RSpec
使用RSpec 测试Rails 程序.pdf
rspec-api-blueprint-formatter, 从RSpec测试自动生成API文档 ! RSpec APIBlueprint格式化程序从RSpec测试自动生成API文档 !像这样it 'retrievs the patients medications' do retrieve_medications
使用RSpec测试Rails程序。本书基于Rails 4.1,使用完整应用 来演示TDD的流程。
rspec-collection_matchers, 集合基数匹配器,从rspec期望中提取 RSpec::CollectionMatchers RSpec::CollectionMatchers 让你在一个例子中表达一个对象集合的预期结果。expect(account.shopping_cart).to have_
RSpec.Essentials 英文
rspec 是目前bdd測試的使用工具,很適合描述測試的內容
ruby(rails)单元测试相关的gem,rspec、cucumeber。BDD
rspec_junit_formatter, RSpec结果格式化为你的CI可以读取的JUnit RSpec JUnit格式化程序 RSpec 2 & 3结果, Jenkins可以读取。 可能还有其他的CI服务。灵感来自于的工作,在的RSpec格式化程序在对 Reporter的失望...
RSpec和Minitest匹配器来预防N 1查询问题
Api-rspec_api_documentation.zip,从rspecrspec api doc generator自动生成api文档,一个api可以被认为是多个软件设备之间通信的指导手册。例如,api可用于web应用程序之间的数据库通信。通过提取实现并将数据放弃到...
rspec_demo Rspec演示
db-query-matchers, 用于数据库查询的RSpec匹配器 db-query-matchers 用于数据库查询的RSpec匹配器。安装在你的应用程序中添加这一行,最好在你的test 组中:gem 'db-query-matchers'然后执行:bundle