2011-08-25 49 views
0

,有4类用户:非登录,消费者,生产者和管理员。Rspec,在我的系统中有更好的方式来编写这个

我目前使用的是Cancan for ACL。

在写RSpec的,我看到以下内容:

describe DealsController do 

    describe "non-signed-in users" do 
    before(:each) do 
     @deal = Factory(:deal) 
    end 

    describe "should be able to" do 
     it "access index" do get :index end 
     it "show deal" do get :show, :id => @deal end 

     after(:each) do 
     response.should be_success 
     end 
    end 

    describe "should not be able to" do 
     it "redeem" do get :redeem end 
     it "new" do get :new end 
     it "edit" do get :edit, :id => @deal end 
     it "update" do get :update, :id => @deal end 
     it "destroy" do get :destroy, :id => @deal end 

     after(:each) do 
     response.should_not be_success 
     response.should redirect_to(root_path) 
     flash[:error].should == "Permission denied." 
     end 
    end 
    end 

    describe "consumers" do 
    before(:each) do 
     @user = test_sign_in(Factory(:user, :role => "consumer")) 
     @deal = Factory(:deal) 
    end 

    describe "should be able to" do 
     it "access index" do get :index end 
     it "show deal" do get :show, :id => @deal end 

     after(:each) do 
     response.should be_success 
     end 
    end 

    describe "should not be able to" do 
     it "redeem" do get :redeem end 
     it "new" do get :new end 
     ... 


     after(:each) do 
     response.should_not be_success 
     response.should redirect_to(root_path) 
     flash[:error].should == "Permission denied." 
     end 
    end 
end 

    describe "producer" do 
    before(:each) do 
     @user = test_sign_in(Factory(:user, :role => "producer")) 
     @business = Factory(:business, :user_id => @user.id) 
     @deal = Factory(:deal, :business_id => @business.id) 
    end 

    it "should be able to access index" do 
     get :index 
     response.should be_success 
    end 

    describe "in show deals" do 
     it "should be able to see merchant controls for his deal" do 
     get :show, :id => @deal 
     response.should have_selector('h3', :content => "Merchant Controls") 
     end 

     it "should not be able to see merchant controls for other's deal" do 
     @user2 = Factory(:user, :role => "producer") 
     @business2 = Factory(:business, :user_id => @user2.id) 
     @deal2 = Factory(:deal, :business_id => @business2.id) 
     get :show, :id => @deal2 

     response.should_not have_selector('h3', :content => "Merchant Controls") 
     end 
    end 

    describe "should not be able to" do 
     it "new" do get :new end 
     ... 

     after(:each) do 
     response.should_not be_success 
     response.should redirect_to(root_path) 
     flash[:error].should == "Permission denied." 
     end 
    end 
end 

end 

我还没有填写管理部分,但我非常有信心,这是不推荐的方式去这样做。

什么是更好的方法?

回答

0

老实说,如果它是一个你关心的应用程序 - 特别是涉及用户交互的时候 - 有很多验收测试是不错的。显然,不要被带走,并开始测试某些颜色是否可见等。但是如果你没有完全测试,你就不会成为你的程序员。

尽管您可能想要将测试分解为更易于管理的测试。也许为这四种用户类型分别创建一个单独的物理文件。我不记得了,但我不认为这会导致RSpec出现任何问题。我个人认为使用RSpec进行验收测试太可怕了。太坚韧。我更喜欢使用黄瓜(http://www.cukes.info)。它使验收测试更容易,尤其是如果你还想测试JavaScript。在我看来,他们写得更快,更干净。如果我是你看看它是否适合你,我会仔细考虑一下。

4

你应该考虑采用一种新的单线风格。例如。做这样的事情

describe "should be able to" do 
    it "access index" { get :index } 
    it "show deal" { get :show, :id => @deal } 
    after(:each)  { response.should be_success } 
end 

此外,你可能会考虑创建一个自定义的匹配器重复多行预期。例如,以下内容:

after(:each) do 
    response.should_not be_success 
    response.should redirect_to(root_path) 
    flash[:error].should == flash 
end 

可以用

after(:each) { response.should fail_redirect_and_flash(root_path, 'Permission denied.') } 

使用下面的自定义匹配代码

RSpec::Matchers.define :fail_redirect_and_flash do |path,flash| 
    match do |response| 
    response.should_not be_success 
    response.should redirect_to(path) 
    flash[:error].should == flash 
    end 
end 

也将进行更换,很多人甚至不打扰写控制器单元测试,因为设计良好的控制器通常只有很少的代码(他们通常只是使用模型上的方法设置一些变量并渲染/重定向,因此大多数测试实际上发生在我在模型中)。相反,他们将控制器和查看测试一起包装并使用黄瓜。你仍然会得到一堆同样难看的代码,但有些人觉得管理起来更容易。

在这个笔记上,你会发现你的规格“不应该能够看到商家控制其他人的交易”实际上是测试你的视图,而不是你的控制器。您应该剔除您在控制器中使用的任何逻辑,以显示商家控件并将其粘贴到帮助器中并单独进行测试。这将有助于保持您的控制器精简。例如。您可以在视图中使用以下帮助程序

def merchant_controls(deal, business) 
    if business.can? :update, deal 
    # render html 
    end 
end 

而且您可以为此辅助方法提供一个规范...

Describe "merchant_controls(deal, business)" do 
    before(:all) do 
    @business_a = create(:business) 
    @deal_a = create(:deal, :business_id => @business_a) 
    @business_b = create(:business) 
    @deal_b = create(:deal, :business_id => @business_b) 
    end 

    it "a business should see merchant controls next to its own deals" do 
    merchant_controls(@business_a, @deal_a).should eq("blahblah") 
    end 
    it "a business should not see merchant controls next to other business' deals" do 
    merchant_controls(@business_a, @deal_b).should eq("") 
    end 
end 

希望这会有所帮助。

+0

谢谢你的一切!我是rspec和测试新手,这真的很有帮助! – disappearedng

+0

FWIW,我明白,这可能只是发生在我身上,但我发现,对于一个工作与{...}和...工作... end结束,我必须在它之后用括号来解释。即它(“应该做些什么”){...}我使用Rspec 2.13,ruby 2,并且使用spork和guard与dRb进行测试。虽然很好的答案!希望我可以多次赞扬它! :) – engineerDave

相关问题