रिपॉजिटरी विधियों के परीक्षण के लिए मुझे यूनिट परीक्षणों की आवश्यकता क्यों है?


19

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

मान लीजिए कि मैंने निम्नलिखित इकाई परीक्षण का निर्माण किया है:

[TestMethod]
public void GetOrderByIDTest()
{
   //Uses Moq for dependency for getting order to make sure 
   //ID I set up in 'Arrange' is same one returned to test in 'Assertion'
}

इसलिए अगर मैं सेट करता हूं OrderIdExpected = 5और मेरी नकली वस्तु 5आईडी के रूप में लौटती है तो मेरा परीक्षण पास हो जाएगा। मैं समझ गया। मैंने यह सुनिश्चित करने के लिए कोड का परीक्षण किया कि मेरा कोड क्या अपेक्षित वस्तु और आईडी लौटाता है और कुछ और नहीं।

मुझे जो तर्क मिलेगा वह यह है:

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

मैं इसे एक पाठ्य पुस्तक की परिभाषा के साथ बचाव कर सकता था: "वैसे यह एक एकीकरण परीक्षण है और हमें एक इकाई परीक्षण के रूप में कोड को अलग से परीक्षण करने की आवश्यकता है और, यादा, यादा, यादा ..." यह एक ऐसा मामला है जहां प्रथाओं का शुद्ध विवरण है बनाम वास्तविकता बाहर खो रही है। मैं कभी-कभी इसमें भाग लेता हूं और अगर मैं यूनिट परीक्षण कोड के पीछे के तर्क का बचाव नहीं कर सकता हूं जो अंततः बाहरी निर्भरता पर निर्भर करता है, तो मैं इसके लिए एक मामला नहीं बना सकता।

इस सवाल पर कोई मदद काफी सराहना की है, धन्यवाद!


2
मैं कहता हूं कि इसे सीधे उपयोगकर्ता परीक्षण के लिए भेजें ... वे किसी भी तरह आवश्यकताओं को बदलने जा रहे हैं ...
नातान हाईफ़ील्ड

+1 कटाक्ष के लिए समय
15

2
इसका सरल उत्तर यह है कि प्रत्येक विधि में एक्स मामलों की संख्या हो सकती है (मान लीजिए कि आप सकारात्मक आईडी, 0 की आईडी और नकारात्मक आईडी का परीक्षण करना चाहते हैं)। यदि आप कुछ कार्यक्षमता का परीक्षण करना चाहते हैं जो इस पद्धति का उपयोग करता है, जिसमें स्वयं 3 किनारे मामले हैं, तो आपको किनारे के मामलों के प्रत्येक संयोजन का परीक्षण करने के लिए 9 परीक्षण मामले लिखने की आवश्यकता होगी। उन्हें अलग-थलग करके, आपको केवल 6 लिखने की ज़रूरत है। इसके अलावा, परीक्षण आपको एक और विशिष्ट विचार देते हैं कि कुछ क्यों टूट गया। शायद आपकी रिपॉजिटरी विफलता पर शून्य हो जाती है, और शून्य अपवाद को कोड के नीचे कई सौ पंक्तियों में फेंक दिया जाता है।
रोब

मुझे लगता है कि आप "इकाई" परीक्षण की अपनी परिभाषा पर बहुत सख्त हो रहे हैं। रिपॉजिटरी वर्ग के लिए "काम की इकाई" क्या है?
कालेब

और सुनिश्चित करें कि आप इस पर विचार कर रहे हैं: यदि आपकी इकाई परीक्षण आपके परीक्षण की कोशिश कर रही हर चीज को खत्म कर देती है, तो आप वास्तव में क्या परीक्षण कर रहे हैं?
कालेब

जवाबों:


20

यूनिट परीक्षणों और एकीकरण परीक्षणों के अलग-अलग उद्देश्य हैं।

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

इकाई परीक्षण, जब सही ढंग से किया जाता है, तो एकीकरण परीक्षणों की तुलना में स्थापित करना आसान होता है। यदि आप पूरी तरह से एकीकरण परीक्षणों पर भरोसा करते हैं, तो आपका परीक्षण निम्न पर जा रहा है:

  1. समग्र रूप से लिखना अधिक कठिन है,
  2. सभी आवश्यक निर्भरता के कारण, और अधिक भंगुर हो
  3. कम कोड कवरेज प्रदान करें।

नीचे पंक्ति: यह सत्यापित करने के लिए एकीकरण परीक्षण का उपयोग करें कि ऑब्जेक्ट के बीच कनेक्शन ठीक से काम कर रहे हैं, लेकिन कार्यात्मक आवश्यकताओं को सत्यापित करने के लिए पहले यूनिट परीक्षण पर दुबला ।


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


हां, त्वरित प्रतिक्रिया के लिए धन्यवाद, मैं इसकी सराहना करता हूं। प्रतिक्रिया की मेरी एकमात्र आलोचना यह है कि यह मेरे अंतिम पैराग्राफ की चिंता में है। मेरा विरोध अभी भी अमूर्त व्याख्याओं और परिभाषाओं को सुनेगा, कुछ गहरे तर्क को नहीं। उदाहरण के लिए, क्या आप मेरे कोड के संबंध में संग्रहीत कार्यविधि / DB के परीक्षण के मेरे उपयोग के मामले में लागू तर्क प्रदान कर सकते हैं और इस विशेष उपयोग के मामले के संदर्भ में इकाई परीक्षण अभी भी मूल्यवान क्यों हैं ?
atconway

1
यदि SP डेटाबेस से केवल एक परिणाम दे रहा है, तो एक एकीकरण परीक्षण पर्याप्त हो सकता है। यदि इसमें गैर-तुच्छ तर्क है, तो यूनिट परीक्षणों का संकेत दिया जाता है। यह भी देखें stackoverflow.com/questions/1126614/... और msdn.microsoft.com/en-us/library/aa833169(v=vs.100).aspx (SQL सर्वर विशिष्ट)।
रॉबर्ट हार्वे

12

मैं प्रगतिवादियों के पक्ष में हूं। दो बार अपने कोड का परीक्षण न करें।

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

  1. टीडीडी करते समय वे यूनिट परीक्षणों के लिए स्थानापन्न कर सकते हैं। जबकि वास्तविक कोड के साथ शुरू करने से पहले लिखने के लिए कुछ और परीक्षण कोड बॉयलरप्लेट है, यह सब कुछ होने के बाद लाल / हरे / रिफ्लेक्टर दृष्टिकोण के साथ बहुत अच्छी तरह से काम करता है।
  2. वे रिपॉजिटरी के वास्तविक कोड का परीक्षण करते हैं - SQL स्ट्रिंग्स या ORM कमांड में निहित कोड। यह सत्यापित करना अधिक महत्वपूर्ण है कि क्वेरी सही है यह सत्यापित करने के लिए कि आपने वास्तव में एक स्टेटमेंट एक्ज़ीक्यूटिव को कुछ स्ट्रिंग भेजा है।
  3. वे प्रतिगमन परीक्षण के रूप में उत्कृष्ट हैं। यदि वे विफल हो जाते हैं, तो यह हमेशा एक वास्तविक समस्या के कारण होता है, जैसे कि स्कीमा में परिवर्तन जिसका कोई हिसाब नहीं है।
  4. डेटाबेस स्कीमा बदलते समय वे अपरिहार्य हैं। आप आश्वस्त हो सकते हैं कि आपने स्कीमा को उस तरीके से नहीं बदला है जो आपके आवेदन को तब तक के लिए तोड़ देता है जब तक कि परीक्षा पास नहीं हो जाती। (इस मामले में इकाई परीक्षण बेकार है, क्योंकि जब संग्रहीत प्रक्रिया अब मौजूद नहीं है, तो इकाई परीक्षण अभी भी पास होगा)।

वास्तव में बहुत व्यावहारिक। मैंने इस मामले का अनुभव किया है कि इन-मेमोरी डेटाबेस वास्तव में मेरे वास्तविक डेटाबेस में भिन्न (प्रदर्शन के मामले में नहीं) है, क्योंकि थोड़ा-बहुत ओआरएम है। अपने एकीकरण परीक्षणों में इसका ध्यान रखें।
मार्सेल

1
@ मार्सेल, मैं उस में चला गया हूँ। मैंने इसे कभी-कभी असली डेटाबेस के खिलाफ अपने सभी परीक्षण चलाकर हल किया।
विंस्टन इर्वर्ट

4

इकाई परीक्षण एक स्तर का माप प्रदान करते हैं जो एकीकरण परीक्षण (डिजाइन द्वारा) नहीं कर सकते हैं। जब एक प्रणाली पुनर्संशोधित है या recomposed, (और यह होगा हो) इकाई परीक्षण अक्सर, पुन: उपयोग किया जा सकता है जबकि एकीकरण परीक्षणों अक्सर फिर से लिखा होना चाहिए। एकीकरण परीक्षण जो एक इकाई परीक्षण में होने वाली चीज़ के काम को करने की कोशिश करते हैं, वे अक्सर बहुत अधिक होते हैं, जिससे उन्हें बनाए रखना मुश्किल होता है।

इसके अतिरिक्त, यूनिट परीक्षण सहित निम्नलिखित लाभ हैं:

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

यूनिट और इंटीग्रेशन टेस्ट दोनों का उपयोग करते हुए अपने काम को विभाजित करना (और DRY दृष्टिकोण लागू करना) संभव है। बस कार्यक्षमता की छोटी इकाइयों के लिए यूनिट परीक्षणों पर भरोसा करते हैं, और किसी भी तर्क को दोहराते नहीं हैं जो पहले से ही एकीकरण परीक्षण में एक इकाई परीक्षण में है। यह अक्सर कम काम (और इसलिए कम फिर से काम) को जन्म देगा।


4

जब वे टूटते हैं तो परीक्षण उपयोगी होते हैं: सक्रिय रूप से या फिर से सक्रिय रूप से।

यूनिट टेस्ट सक्रिय हैं और एक निरंतर कार्यात्मक सत्यापन हो सकता है जबकि एकीकरण टेस्ट एक मंचित / नकली डेटा पर प्रतिक्रियाशील होते हैं।

यदि विचाराधीन प्रणाली गणना तर्क से अधिक डेटा के करीब / निर्भर है, तो एकीकरण टेस्ट को अधिक महत्व मिलना चाहिए।

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

रिपोजिटरी पैटर्न में कम्प्यूटेशनल या व्यावसायिक तर्क नहीं होना चाहिए। यह डेटाबेस के बहुत करीब है। लेकिन रिपॉजिटरी व्यावसायिक तर्क के करीब भी है जो इसका उपयोग करता है। तो यह BALANCE हड़पने का सवाल है।

यूनिट टेस्ट, कैसे रिपोजिटरी व्यवहार का परीक्षण कर सकते हैं। एकीकरण टेस्ट क्या परीक्षण कर सकता है जब रिपॉजिटरी को बुलाया गया था।

अब, "वास्तव में क्या हुआ" बहुत मोहक लग सकता है। लेकिन यह लगातार और बार-बार चलाने के लिए बहुत महंगा हो सकता है। भंगुर परीक्षणों की क्लासिक परिभाषा यहां लागू होती है।

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


मुझे यह पसंद है: "अब," क्या वास्तव में "बहुत मोहक लग सकता है। लेकिन यह लगातार और बार-बार चलाने के लिए बहुत महंगा हो सकता है।"
atconway

2

3 अलग-अलग चीजें हैं जो परीक्षण की आवश्यकता होती हैं: संग्रहीत कार्यविधि, कोड जो संग्रहीत कार्यविधि (यानी आपका भंडार वर्ग), और उपभोक्ता को कॉल करता है। रिपॉजिटरी का काम एक क्वेरी उत्पन्न करना और लौटाए गए डेटा को एक डोमेन ऑब्जेक्ट में बदलना है। यूनिट परीक्षण का समर्थन करने के लिए पर्याप्त कोड है जो क्वेरी के वास्तविक निष्पादन और डेटा सेट के निर्माण से अलग है।

तो (यह एक बहुत ही सरल उदाहरण है):

interface IOrderRepository
{
    Order GetOrderByID(Guid id);
}

class OrderRepository : IOrderRepository
{
    private readonly ISqlExecutor sqlExecutor;
    public OrderRepository(ISqlExecutor sqlExecutor)
    {
        this.sqlExecutor = sqlExecutor;
    }

    public Order GetOrderByID(Guid id)
    {
        var sql = "SELECT blah, blah FROM Order WHERE OrderId = @p0";
        var dataset = this.sqlExecutor.Execute(sql, p0 = id);
        var result = this.orderFromDataset(dataset);
        return result;
    }
}

फिर परीक्षण करते समय OrderRepository, एक मॉकडाउन में पास ISqlExecutorकरें और जांचें कि परीक्षण के तहत ऑब्जेक्ट सही एसक्यूएल (जो कि उसका काम है) में गुजरता है और एक उचित Orderऑब्जेक्ट देता है जो कुछ परिणाम डाटासेट (भी नकली) दिया जाता है। संभवत: कंक्रीट SqlExecutorक्लास का परीक्षण करने का एकमात्र तरीका एकीकरण परीक्षण है, काफी उचित है, लेकिन यह एक पतला आवरण वर्ग है और शायद ही कभी बदल जाएगा, इसलिए बहुत बड़ी बात है।

आपको अभी भी अपनी संग्रहीत प्रक्रियाओं का परीक्षण करना है।


0

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

आगे के कारण उन्हीं नियमों से प्राप्त होते हैं जो OO विकास का मार्गदर्शन करते हैं क्योंकि वे परीक्षणों पर भी लागू होते हैं। उदाहरण के लिए, एकल जिम्मेदारी सिद्धांत।

यदि कुछ इकाई परीक्षण ऐसा लगता है कि वे करने लायक नहीं हैं, तो शायद यह संकेत है कि विषय वास्तव में होने लायक नहीं है। या शायद इसकी कार्यक्षमता इसके समकक्ष से अधिक सार है, और इसके लिए परीक्षण (साथ ही इसके कोड) को उच्च स्तर पर सार किया जा सकता है।

कुछ के साथ के रूप में, वहाँ अपवाद हैं। और प्रोग्रामिंग अभी भी कुछ हद तक एक कला के रूप में है, इसलिए कई समस्याएं सबसे अच्छे दृष्टिकोण के लिए प्रत्येक का आकलन करने के लिए वारंट के लिए पर्याप्त हैं।

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