2010-04-29 2 views
3

사양이 너무 복잡해 지므로 클린업하려고합니다. Rspec 사양 리펙토링

나는 다음과 같은 사양을

describe "Countries API" do 
    it "should render a country list" do 
     co1 = Factory(:country) 
     co2 = Factory(:country) 
     result = invoke :GetCountryList, "empty_auth" 

     result.should be_an_instance_of(Api::GetCountryListReply) 
     result.status.should be_an_instance_of(Api::SoapStatus) 
     result.status.code.should eql 0 
     result.status.errors.should be_an_instance_of Array 
     result.status.errors.length.should eql 0 
     result.country_list.should be_an_instance_of Array 
     result.country_list.first.should be_an_instance_of(Api::Country) 
     result.country_list.should have(2).items 
    end 
    it_should_behave_like "All Web Services" 
    it "should render a non-zero status for an invalid request" 
    end 

50 ~ 60 API를 내 사양 모두에 표시되는 상태를 확인하는 코드의 블록을 가지고있다. 내 첫번째 생각은 방법에 그것을 이동하는 것이었다 다음과 같이 그 리팩토링은 확실히 많이 건조 일을한다 : -

def status_should_be_valid(status) 
    status.should be_an_instance_of(Api::SoapStatus) 
    status.code.should eql 0 
    status.errors.should be_an_instance_of Array 
    status.errors.length.should eql 0 
end 

describe "Countries API" do 
    it "should render a country list" do 
     co1 = Factory(:country) 
     co2 = Factory(:country) 
     result = invoke :GetCountryList, "empty_auth" 

     result.should be_an_instance_of(Api::GetCountryListReply) 
     status_should_be_valid(result.status) 
     result.country_list.should be_an_instance_of Array 
     result.country_list.first.should be_an_instance_of(Api::Country) 
     result.country_list.should have(2).items 
    end 
    end 

이 내가이 그것을 할 수있는 "권리"방법이 아닌 느낌 도움이되지 수 있지만 작동 나는 공유 스펙을 사용해야한다. 그러나 공유 스펙을 정의하는 방법을 살펴보면 공유 스펙을 사용하기 위해이 예제를 리팩터링하는 방법을 쉽게 볼 수 없다.

어떻게 공유 사양으로하고

co1 = Factory(:country) 
    co2 = Factory(:country) 
    result = invoke :GetCountryList, "empty_auth" 

답변

3

여기 RSpec에 새로운 틱 "대상"기능을 사용하여, 하나 개의 옵션들, 즉 시작에 상대적으로 비용이 많이 드는 블록을 다시 실행하지 않고이 작업을 수행 할 것입니다. 이것은 각각 before :all 블록을 두 번, 중첩 된 "describe"블록마다 한 번씩 실행합니다. 이것이 너무 느려지는 경우 상태 공유 예제 (주제가 사용 된 전체 설명 블록에 적용되므로)를 "주제"구문을 사용할 수없는 비용으로 처리 할 수 ​​있습니다.

shared_examples_for "valid status" do 
    it { should be_an_instance_of(Api::SoapStatus) } 
    its(:code) { should eql(0) } 
    its(:errors) { should be_an_instance_of(Array) } 
    its(:errors) { should be_empty } 
end 

describe "Countries API" do 
    before :all do 
    co1 = Factory(:country) 
    co2 = Factory(:country) 
    @result = invoke :GetCountryList, "empty_auth" 
    end 

    subject { @result } 
    it { should be_an_instance_of(Api::GetCountryListReply) } 
    its(:country_list) { should be_an_instance_of (Array) } 
    it "should have countries in the country list" do 
    @result.country_list.each {|c| c.should be_an_instance_of(Api::Country)} 
    end 
    its(:country_list) { should have(2).items } 

    describe "result status" do 
    subject { @result.status } 
    it_should_behave_like "valid status" 
    end 
end 
+0

+1 정말 멋지 네요. 고마워 그렉 –

+0

이것과 함께 몇 가지 이상한 문제가 있습니다. 이전 : all은 다음 오류를 던졌습니다.'NoMethodError in 'AdminlwController Countries API before (: all)' 정의되지 않은 메소드'recycle! ' for nil : NilClass' 이전 (: 각각)으로 변경하는 것은 더 이상되지만 (: country_list) borks는 새로운 질문을 시작할 것이라고 생각합니다. –

+0

그래, 분명히, 나는 코드에 접근 할 수 없다. (필자는 문법이 옳았는지 확인하기 위해이 테스트를 완전히 비웃은 객체에 대해 실행했다. 그러나 그 것이다.) 그래서 내가 모르고있는 문제가있을 수있다. . –