2012-02-13 9 views
6

के साथ डीआरवाई नियंत्रक चश्मा मैं वर्तमान में प्रति नियंत्रक चश्मा DRY और संक्षेप में नीचे एक उदाहरण के लिए एक प्रयास करने के लिए कोशिश कर रहा हूँ। मैं कुछ कठिनाइयों में विशेष रूप से कह रहा हूं कि विभिन्न किनारे के मामलों से मेल खाने के लिए घोंसला वाली संरचना के भीतर वास्तविक नियंत्रक अनुरोध कॉल कहां रखा जाए।आरएसपीईसी

यहाँ एक उदाहरण है, समस्या का प्रदर्शन करने के लिए सरल है:

describe MyController do 
    let(:item) { Factory(:item) } 
    subject { response } 

    describe "GET #show" do 
    before(:each) do 
     get :show 
    end 

    context "published item" do 
     it { should redirect_to(success_url) } 
    end 

    context "unpublished item" do 
     before(:each) do 
     item.update_attribute(published: false) 
     end 

     it { should redirect_to(error_url) } 
    end 
    end 
end 

जाहिर है यह एक काल्पनिक उदाहरण है, लेकिन यह दिखाता है मैं क्या करना चाहते हैं और क्या काम नहीं कर रहा है। मुख्य रूप से, "अप्रकाशित" संदर्भ के तहत before ब्लॉक समस्या है। क्या होता है सेटअप सेटअप में किए गए परिवर्तन वास्तव में get संदर्भों के कारण कॉल के कारण कॉल करते हैं, इसलिए उस संदर्भ में उदाहरण वास्तव में प्रारंभिक परिदृश्य के साथ काम कर रहा है, जिसका इरादा मैं चाहता हूं।

मुझे समझ में आता है कि ऐसा क्यों होता है और घोंसला का संदर्भ कैसे होता है। मुझे लगता है कि मैं क्या तरह चाहते है की किसी तरह RSpec बताने के लिए मैं इसे किसी दिए गए संदर्भ में किसी भी दावे से पहले सही किसी भी बाद before हुक अभी तक सही चलाना चाहते हैं क्या है। यह नियंत्रक चश्मा के लिए एकदम सही होगा। मैं अपने नियंत्रक चश्मा में घोंसले का लाभ लेना चाहता हूं ताकि get कॉल को स्कैटर किए बिना किनारे के मामलों में धीरे-धीरे बढ़ोतरी हो या मेरे it सम्मिलनों में से प्रत्येक में do_get सहायक को कॉल करें। यह विशेष रूप से किसी भी कस्टम it_should मैक्रोज़ के साथ सिंक में रहने के लिए परेशान हो जाएगा जो मैं उपयोग कर रहा हूं।

क्या आरएसपीईसी में वर्तमान में कुछ भी ऐसा करने के लिए कुछ है? क्या कोई चाल है जो मैं करीब आने के लिए उपयोग कर सकता हूं? ऐसा लगता है कि मैंने अपने नियंत्रक चश्मा लिखने वाले बहुत से लोगों को देखा है; जो मैंने पाया है, लोगों ने मूल रूप से do_get सहायता करने वालों को हर दावे से पहले बुलाया है। क्या कोई बेहतर तरीका है? आप के लिए

उत्तर

6

सूखी सिद्धांत कहता है कि "ज्ञान का प्रत्येक भाग एक एकल, स्पष्ट, आधिकारिक एक प्रणाली के भीतर प्रतिनिधित्व होना चाहिए।" आप जो कुछ भी कर रहे हैं, वह चीजों को कम रखने के बजाय यहां और वहां कुछ पात्रों को सहेजने के बारे में बहुत कुछ है, और नतीजा निर्भरता का एक उलझन वाला वेब है जो पदानुक्रम को ऊपर और नीचे करता है, जैसा कि आप देख सकते हैं, ऐसा करने के लिए एक कुतिया है आप इसे और इसके परिणामस्वरूप नाजुक और भंगुर चाहते हैं।

गया है कि आप एक तरीका है कि वर्बोज़ है और काम करता है में लिखा गया गया है साथ शुरू करते हैं:

describe MyController do 
    describe "GET #show" do 
    context "published item" do 
     it "redirects to the success url" do 
     item = Factory(:item, published: true) 
     get :show, :id => item.id 
     response.should redirect_to success_url 
     end 
    end 

    context "unpublished item" do 
     it "redirects to the error url" do 
     item = Factory(:item, published: false) 
     get :show, :id => item.id 
     response.should redirect_to error_url 
     end 
    end 
    end 
end 
अब केवल "ज्ञान के टुकड़े" कि दोहराया उदाहरण के नाम हैं किया जा रहा है, जो कर सकते थे

प्रत्येक उदाहरण के अंत में matchers द्वारा उत्पन्न किया जाना चाहिए।वहाँ

describe MyController do 
    describe "GET #show" do 
    context "published item" do 
     example do 
     item = Factory(:item, published: true) 
     get :show, :id => item.id 
     response.should redirect_to success_url 
     end 
    end 

    context "unpublished item" do 
     example do 
     item = Factory(:item, published: false) 
     get :show, :id => item.id 
     response.should redirect_to error_url 
     end 
    end 
    end 
end 

: यह example विधि है, जो it के उपनाम है का उपयोग करके एक पठनीय रास्ते में हल किया जा सकता। सूखी। और काफी पठनीय और बदलने के लिए आसान है। अब, जब आप संदर्भों में से किसी के लिए और अधिक उदाहरण जोड़ने के लिए होता है, आप जोड़ सकते हैं एक let:

describe MyController do 
    describe "GET #show" do 
    context "published item" do 
     let(:item) { Factory(:item, published: true) } 
     example do 
     get :show, :id => item.id 
     response.should redirect_to success_url 
     end 

     example do 
     # other example 
     end 
    end 
    # ... 
    end 
end 

अब केवल डुप्लिकेट किए गए कोड (सूखी सिद्धांत के रूप में ही नहीं) get है। यदि आप वास्तव में इसके बारे में दृढ़ता से महसूस करते हैं, तो आप get_show(id) या कुछ ऐसे तरीकों से उन कॉल को आउट कर सकते हैं, लेकिन यह वास्तव में उस बिंदु पर अधिक खरीद नहीं रहा है। यह get के लिए एपीआई की तरह नहीं है, जो आपके अंतर्गत से बदल रहा है, और get का एकमात्र तर्क item की आईडी है, जिसे आप वास्तव में उदाहरण में देखते हैं (इसलिए कोई अनावश्यक जानकारी नहीं है)।

प्रतिक्रिया को पकड़ने के लिए subject का उपयोग करने के लिए और सौदे से एक-लाइनर प्राप्त करने के लिए, जो चीजों को पढ़ने में वाकई मुश्किल बनाता है और आपको बहुत बचाता नहीं है। असल में, मैं इस तरह to be a smell में subject का उपयोग करने पर विचार करने आया हूं।

आशा है कि यह सब मदद करता है।

चीयर्स, डेविड

+0

अच्छा बिंदु। चश्मा को स्पष्ट रखने के लिए अतिरिक्त क्रियात्मकता उपयोगी हो सकती है, भले ही 'get' कॉल अभी भी दोहराया गया हो। फिर भी, यह कंट्रोलर चश्मे की तरह लगता है, जिसमें एक आरईएसटी कार्रवाई के जवाब में speccing का एक बहुत ही विशिष्ट उपयोग मामला है, किसी भी तरह से इस तरह के पुनरावृत्ति को कम कर सकता है। –

+0

क्रिस - मैं मानता हूं कि कुछ प्रकार का शॉर्टकट अच्छा होगा और मैं इस विचार के लिए खुला हूं, लेकिन मैंने अभी तक एक ऐसा देखा है जो मुझे लगता है कि स्पष्टता का उचित स्तर है। यदि आपके पास कोई विचार है, तो हर तरह से कृपया https://github.com/rspec/rspec-rails/issues पर एक सुविधा अनुरोध सबमिट करें। –

3

विल

context "unpublished item" do 
    let(:item) do 
    Factory(:item, published: false) 
    end 

    it { should redirect_to(error_url) } 
end 

काम करता है? डिफ़ॉल्ट रूप से बीटीडब्ल्यू, beforebefore(:each) है ताकि आप थोड़ा और अधिक चश्मा डालें।

अद्यतन: आप भी उदाहरण गुमनाम संदर्भों के साथ अलग कर सकते हैं, जैसे:

describe "GET #show" do 
    let(:show!) do 
    get :show 
    end 

    context do 
    before { show! } 

    context "published item" do 
     it { should redirect_to(success_url) } 
    end 

    # another examples with show-before-each 
    end 

    context "unpublished item" do 
    before do 
     item.update_attribute(published: false) 
     show! 
    end 

    it { should redirect_to(error_url) } 
    end 
end 
+0

यह यह काफी नहीं है। मैं इसे मौजूदा आइटम को पूरी तरह से बदलने की बजाय इसे संपादित करने में सक्षम हूं, जो यह समाधान करेगा। तर्क यह है कि यह पुन: प्रयोज्य संदर्भों को बनाना आसान बनाता है जो सेटअप स्थिति में वृद्धिशील परिवर्तन करते हैं ताकि विभिन्न संदर्भों को उन संदर्भों के संयोजन से परीक्षण किया जा सके। –

+0

अद्यतन उत्तर में एक और दृष्टिकोण देखें। मुझे लगता है कि घोंसला वाले हुक तर्क को बदलने का कोई और तरीका नहीं है। –

+0

मैं एक समान समाधान का उपयोग कर समाप्त हुआ। यह अभी भी थोड़ा गंदे लगता है, लेकिन यह काम करता है। आपको बस यह सुनिश्चित करना होगा कि 'शो!' को नेस्टेड संदर्भों में सही ढंग से कहा जाता है और सुनिश्चित करें कि यह दो बार बुलाया नहीं जाता है। यह मेरी इच्छा से अधिक मानसिक उपर है, लेकिन अब यह काम पूरा हो गया है। –