क्या यूनिट परीक्षणों के लिए एक निष्पादन आदेश लागू करना बुरा व्यवहार है?


84

मैं एक परियोजना के लिए परीक्षण लिख रहा हूं जिसमें कई सबमॉड्यूल हैं। प्रत्येक परीक्षण का मामला जो मैंने लिखा है एक दूसरे से स्वतंत्र चलता है और मैं परीक्षणों के बीच सभी डेटा को साफ करता हूं।

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

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

इस मामले में, परीक्षणों के लिए एक निष्पादन आदेश लागू करना ठीक है या क्या यह बुरा व्यवहार है? मुझे ऐसा लगता है कि इस सेटअप में एक गंध है, लेकिन मुझे इसके बारे में बेहतर तरीका नहीं मिल रहा है।

संपादित करें: सवाल यह है कि संरचना परीक्षण कैसे करें जहां एक परीक्षण दूसरे परीक्षण का सेटअप है? जैसा कि "पिछला" परीक्षण सेटअप नहीं है, लेकिन उस कोड का परीक्षण करता है जो सेटअप करता है।



123
यदि आप किसी दूरस्थ सर्वर से कनेक्शन का परीक्षण कर रहे हैं, तो वे परिभाषा के अनुसार इकाई परीक्षण नहीं हैं।
तेलस्तीन

9
पहले उत्तर ने मुझे यहाँ भ्रमित किया क्योंकि आपके शीर्षक में आपने कहा था "क्या यह बुरा अभ्यास है?" और आपके प्रश्न के सारांश में आपने लिखा "क्या यह ठीक है?" कोई भी हाँ या ना में उत्तर देने वाला कोई भी व्यक्ति भ्रमित करने वाला नहीं है!
Liath

8
ऐसा लगता है जैसे आप एकीकरण परीक्षण का सेट बना रहे हैं। यहां तक ​​कि उसके लिए एक परीक्षण अन्य परीक्षणों पर निर्भर नहीं होना चाहिए।
लो फ्लाइंग पेलिकन

17
यदि आदेश मायने रखता है तो आप शायद गलत कर रहे हैं।
मार्क रोजर्स

जवाबों:


236

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

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

लेकिन, यह आपके ऐप की संरचना पर नए सिरे से गौर करने लायक होगा। पहले सबमोडुले और बाहरी सर्वर को मॉक करने में सक्षम होने के बाद आप संभावित रूप से अन्य सभी सबमॉड्यूल के लिए सही यूनिट परीक्षण लिखने की अनुमति देंगे।


14
यह उल्लेख नहीं करने के लिए कि कुछ परीक्षण को विशेष रूप से जांचना है कि अपेक्षित व्यवहार तब होता है जब दूरस्थ सर्वर अनुपलब्ध है।
अलेक्जेंडर

2
या, शायद, आप वास्तव में एकीकरण परीक्षण लिखने का इरादा कर रहे हैं, और इस प्रकार डेटा का मजाक उड़ाने से वह हासिल नहीं होने वाला है जो आप इन परीक्षणों के साथ पूरा करने की कोशिश कर रहे हैं।
गाइ शालनाट

10
समस्या सबसे अधिक संभावना है कि जुनित के नाम में "इकाई" है।
थोरबजोरन रावन एंडरसन

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

1
@MasonWheeler या यहां तक ​​कि गैर-तकनीकी प्रबंधकों द्वारा सह-चयन का मतलब स्वीकृति परीक्षण है।
TKK

32

हाँ, यह एक बुरा अभ्यास है।

आम तौर पर, एक इकाई परीक्षण कोड की एक इकाई (उदाहरण के लिए एक ज्ञात स्थिति के आधार पर एक एकल फ़ंक्शन) का परीक्षण करने का इरादा है।

जब आप घटनाओं की एक श्रृंखला का परीक्षण करना चाहते हैं जो जंगली में हो सकती हैं, तो आप एक अलग परीक्षण शैली चाहते हैं, जैसे कि एकीकरण परीक्षण। यदि आप किसी तृतीय पक्ष सेवा पर निर्भर हैं, तो यह और भी सही है।

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


8
माना। मुझे लगता है कि यह भ्रम इस तथ्य से उपजा है कि बहुत से लोगों को यह विचार है कि एकीकरण परीक्षणों का अंत-टू-एंड होना है, और केवल एक परत का परीक्षण करने वाले किसी भी परीक्षण को संदर्भित करने के लिए "यूनिट टेस्ट" का उपयोग करना है ।
autophage

8
@ अनाथालय: निश्चित रूप से इससे सहमत हैं। वास्तव में मैं इसके साथ सहमत इतना है कि मैं नियमित रूप से अपने आप को एक ही जाल में गिरने लगता है सहमत हैं कि यह एक जाल है के बावजूद 😂
कक्षा में लपट दौड़

16

लागू किया गया निष्पादन आदेश जो आप प्रस्तावित करते हैं, केवल तभी समझ में आता है जब आप पहली असफलता के बाद टेस्ट रन को निरस्त कर देते हैं।

पहली असफलता पर टेस्ट रन को निरस्त करने का मतलब है कि प्रत्येक टेस्ट रन केवल एक ही समस्या को उजागर कर सकता है और जब तक सभी पूर्ववर्ती समस्याओं को ठीक नहीं किया जाता है तब तक यह नई समस्याएं नहीं पा सकता है। यदि चलाने के लिए पहला परीक्षण एक ऐसी समस्या का पता लगाता है जिसे ठीक करने में एक महीने का समय लगता है, तो उस महीने के दौरान प्रभावी रूप से कोई परीक्षण निष्पादित नहीं किया जाएगा।

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

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


7

जिस गंध का आप उल्लेख कर रहे हैं, वह आपके परीक्षणों के लिए बाधाओं और नियमों के गलत सेट का अनुप्रयोग है।

यूनिट टेस्ट अक्सर "स्वचालित परीक्षण", या "प्रोग्रामर द्वारा स्वचालित परीक्षण" के साथ भ्रमित हो जाते हैं।

यूनिट टेस्ट छोटे, स्वतंत्र और तेज़ होने चाहिए।

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

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


6

जैसा कि ऊपर उल्लेख किया गया है, जो आप चला रहे हैं वह एकीकरण परीक्षण प्रतीत होता है, हालाँकि आप कहते हैं कि:

उदाहरण के लिए, एक सबमॉड्यूल डेटा उत्पन्न कर रहा है, और एक अन्य डेटा पर क्वेरी चला रहा है। यदि सबमॉड्यूल उत्पन्न करने वाले डेटा में कोई त्रुटि है, तो क्वेरी सबमॉड्यूल के लिए परीक्षण भी विफल हो जाएगा, भले ही सबमॉड्यूल स्वयं ठीक काम करता हो।

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

जैसे

यदि आपके पास है:

class Queries {

    int GetTheNumber() {
        var dataModule = new Submodule1();
        var data = dataModule.GetData();
        return ... run some query on data
    }
}

इसके बजाय पसंद करें:

interface DataModule {
    Data GetData();
}


class Queries {

    IDataModule _dataModule;

    ctor(IDataModule dataModule) {
       _dataModule = dataModule;
    }

    int GetTheNumber() {
        var data = _dataModule.GetData();
        return ... run some query on data
    }
}

यह आपके डेटा स्रोत पर प्रश्नों से निर्भरता को हटाता है और आपको विशेष परिदृश्यों के लिए आसानी से दोहराए जाने वाले यूनिट परीक्षण स्थापित करने की अनुमति देता है।


6

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


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

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

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

@ माइकहालर तब वे इकाई परीक्षण नहीं कर रहे हैं। वास्तव में कोई भ्रम नहीं होना चाहिए कि यूनिट परीक्षण क्या हैं
रॉबी डी

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