RSpec: पहले और पहले के ब्लॉक में क्या अंतर है?


90

RSpec में letऔर beforeब्लॉक के बीच क्या अंतर है ?

और प्रत्येक का उपयोग कब करें?

नीचे दिए गए उदाहरण में अच्छा दृष्टिकोण (चलो या पहले) क्या होगा?

let(:user) { User.make !}
let(:account) {user.account.make!}

before(:each) do
 @user = User.make!
 @account = @user.account.make!
end

मैंने इस स्टैकओवरफ़्लो पोस्ट का अध्ययन किया

लेकिन क्या ऊपर की तरह एसोसिएशन के सामान के लिए जाने को परिभाषित करना अच्छा है?


1
मूल रूप से, 'लेट' का उपयोग ऐसे लोग करते हैं जो इंस्टेंस वेरिएबल को नापसंद करते हैं। एक साइड नोट के रूप में, आपको FactoryGirl या एक समान उपकरण का उपयोग करने पर विचार करना चाहिए।
माफी माँगता हूँ

जवाबों:


146

लोगों को लगता है कि कुछ बुनियादी तरीकों के बारे में बताया गया है जिसमें वे अलग-अलग हैं, लेकिन बाहर निकल गए before(:all)और यह स्पष्ट नहीं करते हैं कि उनका उपयोग क्यों किया जाना चाहिए।

यह मेरा विश्वास है कि उदाहरण के चर का कोई स्थान नहीं है, जो कि अधिकांश स्पेक्स में इस्तेमाल किया जा रहा है, आंशिक रूप से इस उत्तर में दिए गए कारणों के कारण , इसलिए मैं उन्हें यहां एक विकल्प के रूप में उल्लेख नहीं करूंगा।

ब्लॉक होने दें

एक letब्लॉक के भीतर कोड केवल तब निष्पादित किया जाता है जब संदर्भित किया जाता है, आलसी लोडिंग का मतलब है कि इन ब्लॉकों का आदेश अप्रासंगिक है। यह आपको अपने चश्मे के माध्यम से दोहराया सेटअप पर कटौती करने के लिए बड़ी मात्रा में बिजली देता है।

इसका एक (अत्यंत छोटा और वंचित) उदाहरण है:

let(:person)     { build(:person) }
subject(:result) { Library.calculate_awesome(person, has_moustache) }

context 'with a moustache' do
  let(:has_moustache) { true } 
  its(:awesome?)      { should be_true }
end

context 'without a moustache' do
  let(:has_moustache) { false } 
  its(:awesome?)      { should be_false }
end

आप देख सकते हैं कि has_moustacheप्रत्येक मामले में अलग-अलग परिभाषित किया गया है, लेकिन subjectपरिभाषा को दोहराने की आवश्यकता नहीं है । नोट करने के लिए कुछ महत्वपूर्ण यह है कि letवर्तमान संदर्भ में परिभाषित अंतिम ब्लॉक का उपयोग किया जाएगा। यह अधिकांश ऐनक के लिए उपयोग किए जाने वाले डिफ़ॉल्ट को सेट करने के लिए अच्छा है, जिसे जरूरत पड़ने पर अधिलेखित किया जा सकता है।

उदाहरण के लिए, calculate_awesomeयदि किसी personमॉडल के top_hatसेट के सही होने पर रिटर्न वैल्यू की जाँच की जाए , लेकिन कोई मूंछ नहीं होगी:

context 'without a moustache but with a top hat' do
  let(:has_moustache) { false } 
  let(:person)        { build(:person, top_hat: true) }
  its(:awesome?)      { should be_true }
end

लेट ब्लॉक्स के बारे में एक और बात ध्यान दें, यदि आप डेटाबेस में सहेजे गए हैं (यानी Library.find_awesome_people(search_criteria)) खोज रहे हैं तो उनका उपयोग नहीं किया जाना चाहिए क्योंकि वे डेटाबेस में तब तक सहेजे नहीं जाएंगे जब तक कि उन्हें पहले ही संदर्भित नहीं किया गया हो। let!या beforeब्लॉक यहां क्या उपयोग किया जाना चाहिए।

इसके अलावा, कभी भी ब्लॉकों के beforeनिष्पादन को ट्रिगर करने के लिए उपयोग करें let, यह वही है जो के let!लिए बनाया गया है!

करते हैं! ब्लॉक

let!ब्लॉकों को उस क्रम में निष्पादित किया जाता है जिसे वे परिभाषित किया गया है (पहले ब्लॉक की तरह)। ब्लॉक करने से पहले एक मुख्य अंतर यह है कि आपको इस चर का एक स्पष्ट संदर्भ मिलता है, बजाय उदाहरण के चर पर वापस आने की आवश्यकता के बजाय।

letब्लॉक के साथ के रूप में , यदि एक let!ही नाम के साथ कई ब्लॉक परिभाषित किए गए हैं, तो सबसे हाल ही में निष्पादन में उपयोग किया जाएगा। इस तरह से उपयोग किए जाने पर मुख्य अंतर यह है कि let!ब्लॉक को कई बार निष्पादित किया letजाएगा , जबकि ब्लॉक केवल अंतिम बार निष्पादित करेगा।

पहले (: प्रत्येक) ब्लॉक

before(:each)ब्लॉक से पहले डिफ़ॉल्ट है, और इसलिए हर बार before {}पूर्ण निर्दिष्ट करने के बजाय संदर्भित किया जा सकता है before(:each) {}

beforeकुछ मुख्य स्थितियों में ब्लॉक का उपयोग करना मेरी व्यक्तिगत प्राथमिकता है। मैं ब्लॉक से पहले उपयोग करूंगा यदि:

  • मैं मॉकिंग, स्टबिंग या डबल्स का उपयोग कर रहा हूं
  • कोई भी उचित आकार का सेटअप है (आमतौर पर यह एक संकेत है कि आपके कारखाने के लक्षण सही ढंग से सेटअप नहीं हुए हैं)
  • ऐसे कई चर हैं जिन्हें मुझे सीधे संदर्भित करने की आवश्यकता नहीं है, लेकिन सेटअप के लिए आवश्यक हैं
  • मैं रेल में कार्यात्मक नियंत्रक परीक्षण लिख रहा हूं, और मैं परीक्षण (यानी before { get :index }) के लिए एक विशेष अनुरोध निष्पादित करना चाहता हूं । भले ही आप subjectबहुत सारे मामलों में इसके लिए उपयोग कर सकते हों , कभी-कभी आपको संदर्भ की आवश्यकता नहीं होने पर यह अधिक स्पष्ट लगता है।

यदि आप अपने आप beforeको अपने चश्मे के लिए बड़े ब्लॉक लिखते हैं , तो अपने कारखानों की जांच करें और सुनिश्चित करें कि आप लक्षण और उनके लचीलेपन को पूरी तरह से समझते हैं।

पहले (: सभी) ब्लॉक

वर्तमान संदर्भ (और उसके बच्चों) में चश्मा से पहले ये केवल एक बार निष्पादित किए जाते हैं। अगर सही ढंग से लिखा जाए तो इनका इस्तेमाल बड़े फायदे के लिए किया जा सकता है, क्योंकि कुछ ऐसी परिस्थितियां हैं जो निष्पादन और प्रयास में कटौती कर सकती हैं।

एक उदाहरण (जो शायद ही निष्पादन समय को प्रभावित करेगा) एक परीक्षण के लिए एक ईएनवी चर का मजाक उड़ा रहा है, जिसे आपको केवल एक बार करने की आवश्यकता होगी।

उम्मीद है की वो मदद करदे :)


मिनिटेस्ट उपयोगकर्ताओं के लिए, जो कि मैं हूं, लेकिन मैंने इस प्रश्नोत्तर के RSpec टैग पर ध्यान नहीं दिया, before(:all)विकल्प मिनिटेस्ट में मौजूद नहीं है। यहाँ टिप्पणियों में कुछ समाधान हैं: github.com/seattlerb/minitest/issues/61
MrYoshiji

अनुच्छेद संदर्भित एक मृत कड़ी है: \
डायलन पियर्स

धन्यवाद @DylanPierce मुझे उस लेख की कोई भी प्रति नहीं मिल रही है, इसलिए मैंने एक SO उत्तर का संदर्भ दिया है जो इस के बजाय :) को संबोधित करता है
Jay

धन्यवाद :) बहुत सराहना की
डायलन पियर्स

1
itsअब rspec- कोर में नहीं है अधिक आधुनिक, मुहावरेदार तरीका है it { is_expected.to be_awesome }
जुबिन

26

लगभग हमेशा, मुझे पसंद है let। आप जिस पोस्ट को लिंक करते हैं letवह निर्दिष्ट करता है। हालाँकि, कई बार, जब कई कमांड्स को निष्पादित करना होता है, तो मैं उपयोग कर सकता हूं before(:each)क्योंकि कई कमांड शामिल होने पर इसका सिंटैक्स अधिक स्पष्ट होता है।

आपके उदाहरण में, मैं निश्चित रूप से letइसके बजाय उपयोग करना पसंद करूंगा before(:each)। सामान्यतया, जब बस कुछ वैरिएबल इनिशियलाइजेशन किया जाता है, तो मैं उपयोग करना पसंद करता हूं let


15

एक बड़ा अंतर जिसका उल्लेख नहीं किया गया है, वह यह है कि letजब तक आप इसे पहली बार नहीं कहते हैं, तब तक परिभाषित चर नहीं मिलते हैं। इसलिए जब एक before(:each)ब्लॉक सभी चर को तुरंत रोक देगा, letतो आप कई प्रकार के चर को परिभाषित कर सकते हैं जिनका आप कई परीक्षणों में उपयोग कर सकते हैं, यह स्वचालित रूप से उन्हें तुरंत नहीं करता है। यह जानने के बिना, आपके परीक्षण स्वयं को काटने के लिए वापस आ सकते हैं यदि आप सभी डेटा के पहले से लोड होने की उम्मीद कर रहे हैं। कुछ मामलों में, आप कई letवेरिएबल्स को परिभाषित करना चाह सकते हैं , फिर before(:each)प्रत्येक letउदाहरण को कॉल करने के लिए एक ब्लॉक का उपयोग करें ताकि यह सुनिश्चित किया जा सके कि डेटा को शुरू करने के लिए उपलब्ध है।


20
आप उन let!तरीकों को परिभाषित करने के लिए उपयोग कर सकते हैं जिन्हें प्रत्येक उदाहरण से पहले कहा जाता है। RSpec डॉक्स देखें ।
जिम स्टीवर्ट

3

ऐसा लगता है कि आप मशीनिस्ट का उपयोग कर रहे हैं। खबरदार, आप कुछ मुद्दों को देख सकते हैं! वैश्विक स्थिरता लेन-देन के बाहर होने वाले लेट (नॉन-बैंग संस्करण) के अंदर (यदि आप ट्रांसेक्शनल जुड़नार का उपयोग कर रहे हैं) तो अपने अन्य परीक्षणों के लिए डेटा को दूषित करना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.