परीक्षण में तर्क से बचने के दौरान एक संग्रह लौटाता है कि इकाई परीक्षण विधि कैसे करें


14

मैं एक ऐसी विधि का परीक्षण कर रहा हूं, जो डेटा ऑब्जेक्ट का एक संग्रह उत्पन्न करने के लिए है। मैं यह सत्यापित करना चाहता हूं कि वस्तुओं के गुणों को सही ढंग से सेट किया जा रहा है। कुछ गुणों को एक ही चीज़ पर सेट किया जाएगा; दूसरों को एक मूल्य पर सेट किया जाएगा जो संग्रह में उनकी स्थिति पर निर्भर है। ऐसा करने का स्वाभाविक तरीका लूप के साथ लगता है। हालांकि, रॉय ओशेरोव यूनिट परीक्षणों ( आर्ट ऑफ यूनिट टेस्टिंग , 178) में तर्क का उपयोग करने के खिलाफ दृढ़ता से सलाह देते हैं । वह कहता है:

एक परीक्षण जिसमें तर्क होता है, आमतौर पर एक समय में एक से अधिक चीजों का परीक्षण होता है, जिसकी अनुशंसा नहीं की जाती है, क्योंकि परीक्षण कम पठनीय और अधिक नाजुक होता है। लेकिन परीक्षण तर्क भी जटिलता जोड़ता है जिसमें एक छिपा हुआ बग हो सकता है।

टेस्ट, एक सामान्य नियम के रूप में, विधि नियंत्रणों की एक श्रृंखला होनी चाहिए जिसमें कोई नियंत्रण प्रवाह न हो try-catch, यहां तक ​​कि और न ही मुखर कॉल के साथ।

हालाँकि, मैं अपने डिज़ाइन में कुछ भी गलत नहीं देख सकता (आप डेटा ऑब्जेक्ट्स की एक सूची कैसे बनाते हैं, जिनके कुछ मान इस पर निर्भर हैं कि वे इस क्रम में कहाँ हैं? - बिल्कुल उत्पन्न नहीं करेंगे और उन्हें अलग से परीक्षण करेंगे)। क्या मेरे डिजाइन के साथ कुछ गैर-परीक्षण-अनुकूल है? या फिर ओशेरोव के शिक्षण के लिए बहुत कठोर रूप से समर्पित किया जा रहा है? या वहाँ कुछ गुप्त इकाई परीक्षण जादू है कि मुझे इस समस्या के बारे में पता नहीं है? (मैं C # / VS2010 / NUnit में लिख रहा हूं, लेकिन यदि भाषा-अज्ञेय उत्तर की तलाश कर रहे हैं)।


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

1
@AnthonyPegram सेट अनियंत्रित हैं - फ्रोब कभी-कभी 3rd हो सकता है, कभी-कभी 2nd हो सकता है। आप इस पर भरोसा नहीं कर सकते हैं, एक लूप (या पायथन की तरह भाषा की सुविधा in) बनाने के लिए, यदि परीक्षण "फ्रोब को सफलतापूर्वक एक मौजूदा संग्रह में जोड़ा गया था"।
इज़्काता Iz

1
@ इज़बेटा, उनके प्रश्न में विशेष रूप से उल्लेख है कि आदेश देना महत्वपूर्ण है। उनके शब्द: "दूसरों को एक मूल्य पर सेट किया जाएगा जो संग्रह में उनकी स्थिति पर निर्भर है।" C # (वह जिस भाषा को संदर्भित करता है) में बहुत सारे संग्रह प्रकार हैं जो प्रविष्टि के आदेश दिए गए हैं। उस मामले के लिए, आप पायथन में सूचियों के साथ आदेश पर भी भरोसा कर सकते हैं, जिस भाषा का आप उल्लेख करते हैं।
एंथनी पेग्राम

इसके अलावा, मान लीजिए कि आप किसी संग्रह पर रीसेट विधि का परीक्षण कर रहे हैं। आपको संग्रह के माध्यम से लूप करने और प्रत्येक आइटम की जांच करने की आवश्यकता है। संग्रह के आकार के आधार पर, लूप में इसका परीक्षण नहीं करना हास्यास्पद है। या मान लें कि मैं किसी ऐसी चीज का परीक्षण कर रहा हूं जिसे संग्रह में प्रत्येक आइटम को बढ़ाना है। आप सभी वस्तुओं को एक ही मूल्य पर सेट कर सकते हैं, अपने वेतन वृद्धि को बुला सकते हैं, फिर जांच सकते हैं। वह परीक्षण बेकार है। आपको उनमें से कई को अलग-अलग मूल्यों पर सेट करना चाहिए, वेतन वृद्धि को कॉल करना चाहिए, और जांचना चाहिए कि सभी अलग-अलग मूल्य सही तरीके से बढ़े हैं। संग्रह में सिर्फ एक यादृच्छिक आइटम की जाँच करने से बहुत कुछ छूट जाता है।
इहानी जू

मैं इस तरह से जवाब देने नहीं जा रहा हूं क्योंकि मुझे एक गज़लियन डाउनवोट मिलेगा, लेकिन मैं अक्सर सिर्फ toString()कलेक्शन करता हूं और इसकी तुलना होनी चाहिए। सरल और काम करता है।
user949300

जवाबों:


16

टी एल; डॉ:

  • परीक्षण लिखो
  • यदि परीक्षण बहुत अधिक करता है, तो कोड बहुत अधिक भी कर सकता है।
  • यह एक यूनिट टेस्ट (खराब टेस्ट नहीं) हो सकता है।

परीक्षण के लिए पहली बात हठधर्मिता के बारे में है। मुझे द वे ऑफ टेस्टिवस पढ़ने में मजा आता है जो कुछ मुद्दों को हठधर्मिता के साथ हठधर्मिता के साथ बताता है।

जिस परीक्षा को लिखना है, उसे लिखें।

यदि परीक्षण को किसी तरह से लिखने की आवश्यकता है, तो इसे उस तरह से लिखें। परीक्षण को कुछ आदर्शित परीक्षा लेआउट में लागू करने का प्रयास करना या बिल्कुल नहीं करना अच्छी बात नहीं है। आज का परीक्षण करने के बाद इसका परीक्षण "परफेक्ट" टेस्ट करने से बेहतर है कि कुछ दिन बाद किया जाए।

मैं भी बदसूरत परीक्षण पर बिट की ओर इशारा करेंगे:

जब कोड बदसूरत होता है, तो परीक्षण बदसूरत हो सकते हैं।

आपको बदसूरत परीक्षण लिखना पसंद नहीं है, लेकिन बदसूरत कोड को सबसे अधिक परीक्षण की आवश्यकता है।

बदसूरत कोड को परीक्षण लिखने से न रोकें, लेकिन बदसूरत कोड आपको इसे अधिक लिखने से रोकें।

ये उन लोगों के लिए ट्रूइज्म माने जा सकते हैं जो लंबे समय से पीछा कर रहे हैं ... और वे सिर्फ सोचने और परीक्षण लिखने के तरीके में निपुण हो जाते हैं। उन लोगों के लिए जो उस बिंदु पर नहीं गए और कोशिश कर रहे हैं, रिमाइंडर मददगार हो सकते हैं (मैं उन्हें फिर से पढ़ना चाहता हूं जो मुझे किसी हठधर्मिता में बंद होने से बचने में मदद करता है)।


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

आपको इस तरह के सरल परीक्षणों के माध्यम से उचित कवरेज के साथ सभी कोड का उपयोग करने में सक्षम होना चाहिए । ऐसे परीक्षण जो अंत से अधिक परीक्षण करते हैं जो बड़े सवालों से निपटते हैं ("मेरे पास यह वस्तु है, xml में marshalled, वेब सेवा को भेजा जाता है, नियमों के माध्यम से, बैक आउट और अनमर्सहल्ड") एक उत्कृष्ट परीक्षा है - लेकिन निश्चित रूप से। एक इकाई परीक्षण नहीं है (और एकीकरण परीक्षण क्षेत्र में आता है - भले ही इसकी सेवाओं का मजाक उड़ाया गया हो, जो परीक्षण करने के लिए मेमोरी डेटाबेस में कॉल और कस्टम करता है)। यह अभी भी परीक्षण के लिए XUnit ढांचे का उपयोग कर सकता है, लेकिन परीक्षण ढांचा इसे इकाई परीक्षण नहीं बनाता है।


7

मैं एक नया उत्तर जोड़ रहा हूं क्योंकि मेरा दृष्टिकोण मूल प्रश्न और उत्तर लिखने के समय से अलग है; यह उन्हें एक में एक साथ जाल करने के लिए कोई मतलब नहीं है।

मैंने मूल प्रश्न में कहा

हालाँकि, मैं अपने डिज़ाइन के साथ कुछ भी गलत नहीं देख सकता (आप डेटा ऑब्जेक्ट की एक सूची कैसे बनाते हैं, जिनके कुछ मान इस पर निर्भर हैं कि वे इस क्रम में कहाँ हैं?

यहीं पर मैं गलत हो गया। पिछले वर्ष के लिए कार्यात्मक प्रोग्रामिंग करने के बाद, मुझे अब एहसास हुआ कि मुझे एक संचायक के साथ एक संग्रह संचालन की आवश्यकता है। तब मैं अपने फ़ंक्शन को एक शुद्ध फ़ंक्शन के रूप में लिख सकता था जो एक चीज़ पर संचालित होता था और संग्रह में इसे लागू करने के लिए कुछ मानक लाइब्रेरी फ़ंक्शन का उपयोग करता था।

तो मेरा नया जवाब है: कार्यात्मक प्रोग्रामिंग तकनीकों का उपयोग करें और आप इस समस्या से पूरी तरह से बचेंगे। आप अपने कार्यों को एकल चीजों पर संचालित करने के लिए लिख सकते हैं और केवल अंतिम समय में चीजों के संग्रह के लिए उन्हें लागू कर सकते हैं। लेकिन अगर वे शुद्ध हैं तो आप उन्हें संग्रह के संदर्भ में बिना परीक्षण कर सकते हैं।

अधिक जटिल तर्क के लिए, संपत्ति-आधारित परीक्षणों पर झुकाव करें । जब उनके पास तर्क होते हैं, तो यह कम से कम होना चाहिए और परीक्षण के तहत कोड के तर्क के विपरीत होना चाहिए, और प्रत्येक परीक्षण एक केस-आधारित इकाई परीक्षण की तुलना में बहुत अधिक सत्यापित करता है कि तर्क की छोटी राशि इसके लायक है।

ऊपर से हमेशा अपने प्रकारों पर झुकना । अपने फायदे के लिए सबसे मजबूत प्रकार प्राप्त करें और उनका उपयोग करें। यह आपके द्वारा पहले स्थान पर लिखे गए परीक्षणों की संख्या को कम कर देगा।


4

एक ही बार में कई चीजों का परीक्षण करने की कोशिश मत करो। संग्रह में प्रत्येक डेटा ऑब्जेक्ट के गुणों में से प्रत्येक एक परीक्षण के लिए बहुत अधिक है। इसके बजाय, मैं सुझाव देता हूं:

  1. यदि संग्रह निर्धारित लंबाई है, तो लंबाई को मान्य करने के लिए एक इकाई परीक्षण लिखें। यदि यह परिवर्तनशील लंबाई है, तो लंबाई के लिए कई परीक्षण लिखें जो इसके व्यवहार को चिह्नित करेंगे (जैसे 0, 1, 3, 10)। किसी भी तरह से, इन परीक्षणों में गुणों को मान्य न करें।
  2. प्रत्येक गुण को मान्य करने के लिए एक इकाई परीक्षण लिखें। यदि संग्रह निश्चित-लंबाई और छोटा है, तो प्रत्येक परीक्षण के लिए तत्वों में से प्रत्येक की एक संपत्ति के खिलाफ जोर दें। यदि यह निश्चित-लंबाई है, लेकिन लंबी है, तो एक संपत्ति के खिलाफ दावा करने के लिए तत्वों का एक छोटा लेकिन प्रतिनिधि चुनें। यदि यह चर-लंबाई है, तो अपेक्षाकृत कम लेकिन प्रतिनिधि संग्रह (यानी शायद तीन तत्व) उत्पन्न करें और प्रत्येक की एक संपत्ति के खिलाफ जोर दें।

इस तरह से करने से यह परीक्षण काफी छोटा हो जाता है कि छोरों को छोड़ना दर्दनाक नहीं लगता है। C # / Unit उदाहरण, परीक्षण के तहत दी गई विधि ICollection<Foo> generateFoos(uint numberOfFoos):

[Test]
void generate_zero_foos_returns_empty_list() { ... }
void generate_one_foo_returns_list_of_one_foo() { ... }
void generate_three_foos_returns_list_of_three_foos() { ... }
void generated_foos_have_sequential_ID()
{
    var foos = generateFoos(3).GetEnumerable();
    foos.MoveNext();
    Assert.AreEqual("ID1", foos.Current.id);
    foos.MoveNext();
    Assert.AreEqual("ID2", foos.Current.id);
    foos.MoveNext();
    Assert.AreEqual("ID3", foos.Current.id);
}
void generated_foos_have_bar()
{
    var foos = generateFoos(3).GetEnumerable();
    foos.MoveNext();
    Assert.AreEqual("baz", foos.Current.bar);
    foos.MoveNext();
    Assert.AreEqual("baz", foos.Current.bar);
    foos.MoveNext();
    Assert.AreEqual("baz", foos.Current.bar);
}

यदि आप "फ्लैट यूनिट टेस्ट" प्रतिमान (कोई नेस्टेड संरचना / तर्क) के लिए उपयोग किए जाते हैं, तो ये परीक्षण बहुत साफ लगते हैं। इस प्रकार मूल समस्या की पहचान करके परीक्षणों में तर्क को टाल दिया जाता है, क्योंकि लूप की कमी के बजाय एक ही बार में कई गुणों का परीक्षण करने की कोशिश की जाती है।


1
ओशेरोव के पास 3 मुखर होने के लिए एक थाली पर आपका सिर होगा। ;) असफल होने का पहला मतलब है कि आप कभी भी बाकी को मान्य नहीं करते हैं। ध्यान दें कि आप वास्तव में लूप से बचते नहीं थे । आपने इसे अपने निष्पादित रूप में स्पष्ट रूप से विस्तारित किया है। एक कठिन आलोचना नहीं है, लेकिन सिर्फ कुछ और अभ्यास प्राप्त करने के लिए एक सुझाव है जो आपके परीक्षण मामलों को न्यूनतम राशि तक संभव कर सकता है, अपने आप को अधिक विशिष्ट प्रतिक्रिया देने के लिए जब कुछ विफल हो जाता है, जबकि अन्य मामलों को मान्य करना जारी रखना चाहिए जो अभी भी गर्भधारण कर सकते हैं (या असफल, साथ उनकी अपनी विशिष्ट प्रतिक्रियाएं)।
एंथनी पेग्राम

3
@AnthonyPegram मैं वन-एस्टर-प्रति-परीक्षण प्रतिमान के बारे में जानता हूं। मैं "टेस्ट एक बात" मंत्र को पसंद करता हूं (जैसा कि बॉब मार्टिन ने वकालत की, क्लीन-कोड में एक-प्रति-परीक्षण के खिलाफ )। साइड नोट: यूनिट टेस्टिंग फ्रेमवर्क जिसमें "उम्मीद" बनाम "जोर" है (Google टेस्ट) हैं। बाकी के लिए, आप अपने सुझावों को एक पूर्ण उत्तर में क्यों नहीं विभाजित करते हैं, उदाहरण के साथ? मुझे लगता है कि मुझे फायदा हो सकता है।
काज़ार्क
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.