2011-01-13 10 views
15

Salatalık Senaryoları'nın verim ve kullanışlılığından çok etkilendim, farklı vakaların yükünü test etmenin harika bir yolu.Salatalık'ın "Senaryoları" na RSpec'de bir eşdeğer var mı yoksa RSpec'i yanlış şekilde mi kullanıyorum?

örn. (Kod Ryan Bates' More on Cucumber Screencast alınan) örnek Salatalık senaryosu

Feature: Manage Users 
In order to manage user details 
As a security enthusiast 
I want to edit user profiles only when authorized 

Scenario Outline: Show or hide edit profile link 
    Given the following user records 
    | username | password | admin | 
    | bob  | secret | false | 
    | admin | secret | true | 
    Given I am logged in as "<login>" with password "secret" 
    When I visit profile for "<profile>" 
    Then I should <action> 

    Examples: 
    | login | profile | action     | 
    | admin | bob  | see "Edit Profile"  | 
    | bob | bob  | see "Edit Profile"  | 
    |  | bob  | not see "Edit Profile" | 
    | bob | admin | not see "Edit Profile" | 

RSpec eşdeğer bir var mıdır?

RSpec'te aynı şeyi yapmak ve bir senaryo tablosundaki bir satıra kadar farklı testleri düşürerek kodumu yükseltmek istiyorum. Bunu kendim için kod yazabilirsiniz rağmen

, onu düşünüyorum aslında bu ise iki şeyi

  1. meraklandırıyor kullanışlı muhtemelen zaten nasıl kullanırım bu durumda mevcut o?

  2. Eğer mevcut değilse, bu şekilde yapılmaması gerektiğini ve yanlış bir şekilde yaklaşmaya çalıştığımı öneririm, yaklaşımımı RSpec'e nasıl yeniden bakmalıyım?

Hangi yanıt doğru ve yararlıysa, nasıl yapabilirim?

cevap

20

Aşağıdaki yaklaşımı deneyin. Çıkış şeklini beğeniyorum.

describe StateDateMethods do 
    before :each do 
    @product = OpenStruct.new 
    @product.extend StateDateMethods 
    end 

    def parse_date(unparsed_date_value) 
    unless unparsed_date_value.nil? 
     DateTime.strptime(unparsed_date_value, '%m/%d/%Y') 
    end 
    end 

    context '#pre_order?' do 
    examples = [ 
     # [visible_on, pre_order_on, for_sale_on] => method_result 
     { :inputs => [nil, nil, nil], :expected => false }, 
     { :inputs => ['1/1/2001', nil, nil], :expected => false }, 
     { :inputs => ['1/1/2001', '1/1/2001', nil], :expected => true }, 
     { :inputs => ['1/1/2001', '1/2/2001', nil], :expected => true }, 
     { :inputs => ['1/1/2001', '1/1/2001', '1/2/2001'], :expected => false }, 
     { :inputs => ['1/1/2001', '1/1/2001', '1/1/3001'], :expected => true }, 
     { :inputs => ['1/1/2001', '1/1/3001', '1/2/3001'], :expected => false }, 
     { :inputs => ['1/1/3001', '1/1/3001', '1/2/3001'], :expected => false }, 
     { :inputs => ['1/1/2001', nil, '1/1/2001'], :expected => false }, 
     { :inputs => ['1/1/2001', nil, '1/1/3001'], :expected => false } 
    ] 
    examples.each do |example| 
     inputs = example[:inputs] 

     it "should return #{example[:expected].inspect} when visible_on == #{inputs[0].inspect}, pre_order_on == #{inputs[1].inspect}, for_sale_on == #{inputs[2].inspect}" do 
     @product.visible_on = parse_date(inputs[0]) 
     @product.pre_order_on = parse_date(inputs[1]) 
     @product.for_sale_on = parse_date(inputs[2]) 

     @product.pre_order?.should == example[:expected] 
     end 
    end 
    end 
end 

Ben kendimi tekrar beni tutan çünkü bu, her iki dünyanın en iyisini verir düşünüyorum ve her koşul için farklı bir test oluşturur.

İşte bir başarısızlık gibi görünür: Burada

....F..... 

Failures: 

    1) StateDateMethods#pre_order? should return false when visible_on == "1/1/2001", pre_order_on == "1/1/2001", for_sale_on == "1/2/2001" 
    Failure/Error: @product.pre_order?.should == example[:expected] 
     expected: false 
      got: true (using ==) 
    # ./spec_no_rails/state_date_methods_spec.rb:40:in `block (4 levels) in <top (required)>' 

Finished in 0.38933 seconds 
10 examples, 1 failure 

Failed examples: 

rspec ./spec_no_rails/state_date_methods_spec.rb:35 # StateDateMethods#pre_order? should return false when visible_on == "1/1/2001", pre_order_on == "1/1/2001", for_sale_on == "1/2/2001" 

Ve ne gibi tüm yeşil görünüyor: bunun için

.......... 

Finished in 0.3889 seconds 
10 examples, 0 failures 
+0

Hoşuma gitti - güzel yaklaşım –

+0

Büyük cevap. Specs2 'veri tablolarını anımsatıyor. –

1

Bu yolla RSpec'i kullanmam. RSpec, bir seferde sınıftaki küçük bir davranışa davranışı yönlendirmek için kullanılmalıdır. Her davranış benzersiz olduğundan, onu tanımlamak için farklı bir özellik kullanmalısınız. Yukarıdaki Senaryo ise

gibi davranışını belirtir gözlük olabilir:

it "should allow user to edit his own profile" 
it "should allow admin to edit other users profile" 
it "should not allow non-admin to edit admin profile" 
it "should not allow anonymous user to edit any profile" 

Bir şey daha, uygulamanın çoklu katmanlar aracılığıyla sürücüye RSpec kullanmak iyi bir fikir değildir. Diğer bir deyişle, denetleyicilerinizi tanımlarken, modellerinizle olan etkileşimlerinizi taklit etmelisiniz.

+0

Merhaba cheezy, teşekkür. Her ne kadar salatalıktan bir bütünleşme testi örneği kullanıyor olsam da, RSpec ile kullanılması gereken tanecikliği bilmem (her zaman çekmeme rağmen).Sorum şu söz konusu özel teknikler hakkında daha azdı ve tablo güdümlü senaryolara sahip olma fikri hakkında daha fazlaydı. RSpec'in bunu destekleyip desteklemediğini biliyor musunuz? –

+0

rspec'te tablo sağlayan bir mücevher görmedim. Yine bunun uygun olacağı bir örnek düşünemiyorum. – Cheezy

+1

Aynı satırlarda, rspec'te Given/When/Then anahtar sözcüklerini biraz oynattığımı gösteren bir mücevher var. https://github.com/jimweirich/rspec-given – Cheezy

İlgili konular