想有一下RSPec来做BDD开发,地发现中文资料太少了,无耐只能自己去主页上看资料,做为爱国者,俺的英文真烂得不成,不过翻完了,发出来大家乐一乐吧。
Spec::rails
---------------------------
一个将RSpec引入Rails的Rails插件
特点:
1. 可以使用RSpec独立的测试models,views,controllers和heplers
2. 整合了具夹(fixture)的载入
3. 为models和controllers特别制作的生成器,可以生成指定的测试RSpec文件来代替原来rails默认生成的tests文件。
4. 增加了很多易读的匹配器
愿景:
对那些刚认识TDD这个概念的人来说,rails的测试支持是一个大的飞跃。弄好这些测试就相当的棒了,因为这样的rails程序通常会比没有测试支持的rails程序要容易维护的多。
对于我们这些经历了TDD到现在的BDD的人来说,还必须考虑在现有支持上那些spec之间依赖性的问题。为此,RSpec支持4种规范。这主要启发于Test::Rails,这个zenTest内置rails框架。
我们还建立良好的mocking和stubbing的支持,以助于打破那些不同关联间的依赖关系。
不同类型的Example Groups:
-------------------------------------------
对如下示例的spec类型,Spec::Rails有各自不同的ExampleGroups子类来支持:
Model Examples
这个和rails内置的单元测试工具相同。讽剌的是(对那些传统的TDD'er),我们认为这些只是与数据库相关的(言下之意,rails内置的test只是提供了数据库相关的测试)。
详细示例
Controller Examples
除了不能真的给你转向views外,这和你在rails里做功能测试差不多。而且如果你喜欢,你也可以强制它转向一个view。你可以设置预期的模板,以代替设置预期转向的页面。
详细示例
view Examples
这是rails功能测试的别一部分。View spec可以让你建立设置指定(感谢ZenTest)
详细示例
Helper示例
你可以直接测试你heplers里的指定方法。
详细示例
Fixtures
--------------------------------
你可以在你任何的specs中使用fixture,如model,view,controller或helper,都可以。如果你想在全局中使用fixture,你可以在spec/spec_helper.rb设置。看下面的例子:
命名约定:
为了明确和一致,RSpec在目录和rake任务上使用和Rails内置测试模块稍微不同的命名约定
project
|
+--app
|
+--...
|
+--spec
|
+-- spec_helper.rb
|
+-- controllers
|
+-- helpers
|
+-- models
|
+-- views
Rake任务也对应的命名
Models
---------------------
Model的spec在SRAILS_ROOT/spec/models/目录中,并提供对fixtures的支持
Expectations
---------------------
Model样板支持如下的自定义Expectations
详见:Spec::Rails::Expectations
Records
Model.should have(:no).records
Model.should have(1).record
Model.should have(3).records
这个比Model.find(:all).length.should == 3.要简略一些
Error
model.should have(:no).errors_on(:attribute)
model.should have(1).error_on(:attribute)
model.should have(3).errors_on(:attribute)
Controllers
-----------------------------
Controllers的spec在$RAILS_ROOT/spec/controllers/下
相对Test::Unit,Spec::Rails不需要在setup方法中初始化controller。取而代之的是把controller类传给describe方法。Spec::Rails会自动给你实例化一个controller,在Examples中你可以直接访问该controller的方法
与views独立开来
-----------------------------
默认情况下,Spec::Rails将你的Controller actions与相关的views独立开来。这就让你可以在还没有views的时候测试你的controllers,并在当views出错的时候保持这些(controller的)spec结果。
整合views
------------------------------
如果你要整合views的测试功能(在很多的功能测试中),你可以在代码中加入“integrate_views”
describe ArticlesController do
integrate_views
...
end
整合后,你可以使用views中使用才能使用的Expectations。详见views Examples
与数据库分离
-----------------------------
我们强烈建议您使用RSpec的mocking/stubbing框架来拦截类级的调用,如:find、:create甚至:new,从而引入mock实例来代替事实的active_record实例 。
这容许你的specs专注于controller所处理的事而不用担心那些复杂的验证和关联,这些验证和关联spec
会在Model Examples中去处理。
account = mock_model(Account)
Account.should_receive(:find).with("37").and_return(account)
或
account = mock_model(Account)
Account.stub!(:find).and_return(account)
Mocks和Stubs框架详细信息详见其文档。
Response Expectations
----------------------------
这个Expectations在分离模式或整合模式中都能使用。详见Spec::Rails::Expectations。
Response.should be_success
当返回200状态,测试才能通过。注:分离模式下,这也返回真,所以它的用处不大,但起码你的specs不会终止。
response.should be_success
response.should be_redirect
返回300-399状态时通过。
response.should be_redirect
response.should render_template
get 'some_action'
response.should render_template("path/to/template/for/action")
response.should have_text
get 'some_action'
response.should have_text("expected text")
response.should redirect_to
get 'some_action'
response.should redirect_to(:action => 'other_action')
还支持如下的格式:
response.should redirect_to(:action => 'other_action')
response.should redirect_to('path/to/local/redirect')
response.should redirect_to('http://test.host/some_controller/some_action')
response.should redirect_to('http://some.other.domain.com')
assigns, flash and session
使用如下方法访问 assigns, flash 和session.
assigns[:key]
flash[:key]
session[:key]
Routing Expectations(路由Expectations)
--------------------------------
验证通过路由来获得的地址
route_for(:controller => "hello", :action => "world").should == "/hello/world"
验证路由发送过来的参数
params_from(:get, "/hello/world").should == {:controller => "hello", :action => "world"}
Views
-----------------------------
View Examples位于$RAILS_ROOT/spec/views/。
Spec::Rails支持完全从他们controllers分离出的views测试。
这让你可以在没有controllers或是相关acitons被开发之前的时候测试和写你的views。这也意味着controllers中引入的bugs并不会使views的测试用例失败。
正如介绍中说有,这是一个很大的好处,但是他们将controllers和他们的views关互产生的Bugs给隐藏起来了。我们强烈建议将这些独立的views测试与高层次的集成测试结合起来,最好使用Cucumber。
注:Cucumber是一个BDD(BehaviourDrivenDevelopment)工具。
Spec::Rails::Expectations中还提供了几个可用的函数。
Conveniences
-------------------------------
assigns
使用assigns[:key]来给view中的实例变量赋值。我们推荐您这里使用mock框架,而不是使用真实的model对象,这样可以使view的spec从models的变更中独立开来。
# example
article = mock_model(Article)
article.should_receive(:author).and_return("Joe")
article.should_receive(:text).and_return("this is the text of the article")
assigns[:article] = article
assigns[:articles] = [article]
# template
<% for article in @articles -%>
<!-- etc -->
flash,params和session
使用flash[:key],params[:key] 和session[:key]来给view example中的值赋值。
# example
flash[:notice] = "Message in flash"
params[:account_id] = "1234"
session[:user_id] = "5678"
# template
<%= flash[:notice] %>
<%= params[:account_id] %>
<%= session[:user_id] %>
Examples支持下面的自定义expectations
----------------------
Spec::Rails的view Examples支持下面的自定义expectations
response.shoud have_tag
这个覆盖了assert_select,并可以在集成模式下的所有view examples和controller Examples都可以使用。
response.should have_tag('div') #如果有div标记则通过
response.should have_tag('div#interesting_div')
response.should have_tag('div', 'expected content')
response.should have_tag('div', /regexp matching expected content/)
response.should have_tag('form[action=?]', things_path)
response.should have_tag("input[type=?][checked=?]", 'checkbox', 'checked')
response.should have_tag('ul') do
with_tag('li', 'list item 1')
with_tag('li', 'list item 2')
with_tag('li', 'list item 3')
end
注:任何的hash值都可以是Strings或regexps,并得到相应的评价。
response[:capture].should have_tag
这个方法可以访问那些被content_for捕获的内容。
1.example
response[:sidebar].should have_tag(‘div’)
2.template
<% content_for :sidebar do %>
Sidebar content here
<% end %>
Mocking与stubbing helpers
如果你希望使用mock或stub的helper方法,这些可以在template对象中完成:
template.should_receive(:current_user).and_return(mock("user"))
Helpers
----------------------------------------
Helper Examples在$RAILS_ROOT/spec/helpers/中
写helpers的specs很容易,只要告诉ExampleGrouphelper的名字就可以了
describe RegistrationHelper do
...
end
这将会在ExampleGroup中得到一个包含了这个helper的对象
Conveniences
---------------------
assigns
使用assigns[:key]来在包含了这个helper的view中给实例变量赋值。详见上面的鸽子。
writing
---------------------------
使用Spec::Rails写Examples介绍
Spec::Rails支持4种不同类型的可招执examples
1.Models Examples
2.View Examples
3.Controllor Examples
4.Helper Examples
使用这些各专门ExampleGroup子类可以让你访问适当的服务和方法。他们被放在各自相应的目录中,并以*_spec.rb的明显方法标注出来:
spec/controllers/**/*_spec.rb
spec/helpers/**/*_spec.rb
spec/models/**/*_spec.rb
spec/views/**/*_spec.rb
警告:如果你没有遵守这些约定,那可以得不到正确的ExampleGroup子类。如果你更喜欢不管这些约定,那你也可以通过传递一个hash值给describe方法来获得正确的ExampleGroup子类:
describe "some model", :type => :model do
...
end
在:model,:view,:controller和:helper都生效。
Generators(生成器)
---------------------------------
Spec::Rails包含了一个生成器,你可以用来生成models和RESTfulControllers,它和Rails内置的生成器基本一样。 唯一不同的是,他多帮你会在spec目录下生成一个specs来代替test,还有一个fixtures用来提供测试数据。如下例:
ruby script/generate rspec_scaffold purchase order_id:integer created_at:datetime amount:decimal
ruby script/generate rspec_model person
ruby script/generate rspec_controller person
详细的用法,可以以上命令不加参数获得其帮助 。
运行
---------------------
标准的spec命令:
script/spec path/to/directory/with/specs
script/spec path/to/individual_spec.rb
快速运行模式--drb(推荐)
------------------------
每次运行 都输入所有的Rails环境变量,spec运行起来就很慢了。为了加速测试速度,Spec::Rails安装一个守护进程脚本,用于加载本地Rails应用,并用DRb侦听传入的连接。
打开一个shell来运行spec服务:
script/spec_server
现在你可以使用--drb参数来使用这个功能了。
如果你使用Rake来运行,应该把--drb加给spec/spec.opts文件。
注意到默认情况下,有的类和modules不要rails重新载入,在spec中也是一样的。你也可以修改rails的环境文件中的策略变量来让rails每次都重新载入他们。详细rails的文档。
使用Rake来运行 specs
注意到rake任务不能使用快速Rails_spec命令--就是说只能使用标准的spec。同时我们注意到它预设的都是以_spec结尾的文件,所以你必须遵从如下的约定。
注意到你可以通过编辑sepc/spec.opts文档来配置传给RSpec的选项。
那运行所有的spec(包括plugins)的代码是:
rake spec
rake spec:app
包括plugins在内的specs:
rake spec:all
你也可单独运行 models、controller,view,helper或是plugin的specs:
rake spec:models
rake spec:controllers
rake spec:views
rake spec:helpers
rake spec:plugins
查看rake中所有的RSpec任务:
rake --tasks spec
来源:oschina
链接:https://my.oschina.net/u/4355/blog/10544