यूनिट टेस्टिंग एप्लिकेशन लॉजिक और डिस्ट्रेस्टिंग लैंग्वेज कंस्ट्रक्शंस के बीच की लाइन कहां है?


87

इस तरह एक समारोह पर विचार करें:

function savePeople(dataStore, people) {
    people.forEach(person => dataStore.savePerson(person));
}

यह इस तरह इस्तेमाल किया जा सकता है:

myDataStore = new Store('some connection string', 'password');
myPeople = ['Joe', 'Maggie', 'John'];
savePeople(myDataStore, myPeople);

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

savePeople()यूनिट का परीक्षण किया जाना चाहिए , या इस तरह की परीक्षण राशि बिल्ट-इन forEachभाषा निर्माण का परीक्षण करने के लिए होगी ?

हम निश्चित रूप से, एक मॉक में पास कर सकते हैं dataStoreऔर दावा कर सकते हैं कि dataStore.savePerson()प्रत्येक व्यक्ति के लिए एक बार कहा जाता है। आप निश्चित रूप से यह तर्क दे सकते हैं कि इस तरह का परीक्षण कार्यान्वयन परिवर्तनों के खिलाफ सुरक्षा प्रदान करता है: उदाहरण के लिए, अगर हमने forEachपारंपरिक forलूप या पुनरावृत्ति के कुछ अन्य तरीके से बदलने का फैसला किया है । इसलिए परीक्षण पूरी तरह से तुच्छ नहीं है। और फिर भी यह भयानक रूप से करीब लगता है ...


यहाँ एक और उदाहरण है जो अधिक फलदायी हो सकता है। एक फ़ंक्शन पर विचार करें जो अन्य वस्तुओं या कार्यों का समन्वय करने के अलावा कुछ नहीं करता है। उदाहरण के लिए:

function bakeCookies(dough, pan, oven) {
    panWithRawCookies = pan.add(dough);
    oven.addPan(panWithRawCookies);
    oven.bakeCookies();
    oven.removePan();
}

इस तरह के एक फ़ंक्शन को यूनिट परीक्षण कैसे किया जाना चाहिए, यह मानते हुए कि आपको यह सोचना चाहिए? यह मेरे कि बस नकली नहीं है इकाई परीक्षण के किसी भी प्रकार की कल्पना करने के लिए मुश्किल है dough, panऔर oven, और उसके बाद का दावा है कि तरीकों उन पर कहा जाता है। लेकिन ऐसा परीक्षण फ़ंक्शन के सटीक कार्यान्वयन की नकल करने के अलावा और कुछ नहीं कर रहा है।

क्या यह सार्थक ब्लैक बॉक्स में फ़ंक्शन का परीक्षण करने में असमर्थता फ़ंक्शन के साथ एक डिज़ाइन दोष को इंगित करता है? यदि हां, तो इसमें सुधार कैसे किया जा सकता है?


bakeCookiesउदाहरण को प्रेरित करने वाले प्रश्न को और भी अधिक स्पष्टता देने के लिए, मैं एक और अधिक यथार्थवादी परिदृश्य जोड़ूंगा, जो कि मेरे पास एक परीक्षण और रिफैक्टर विरासत कोड को जोड़ने का प्रयास करते समय मिला है।

जब कोई उपयोगकर्ता एक नया खाता बनाता है, तो कई चीजों का होना आवश्यक है: 1) डेटाबेस में एक नया उपयोगकर्ता रिकॉर्ड बनाने की आवश्यकता है 2) एक स्वागत योग्य ईमेल भेजने की आवश्यकता है 3) उपयोगकर्ता के आईपी पते को धोखाधड़ी के लिए रिकॉर्ड करने की आवश्यकता है प्रयोजनों।

इसलिए हम एक ऐसा तरीका बनाना चाहते हैं जो सभी "नए उपयोगकर्ता" चरणों को एक साथ जोड़े:

function createNewUser(validatedUserData, emailService, dataStore) {
  userId = dataStore.insertUserRecord(validateduserData);
  emailService.sendWelcomeEmail(validatedUserData);
  dataStore.recordIpAddress(userId, validatedUserData.ip);
}

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

मेरे भ्रम का सार यह है कि इस तरह के फ़ंक्शन को इकाई परीक्षण के लिए परीक्षण में सटीक कार्यान्वयन को दोहराने के लिए आवश्यक लगता है (यह निर्दिष्ट करके कि विधियों को एक निश्चित क्रम में मोक्स पर कहा जाता है) और यह गलत लगता है।


44
इसके बाद चलता है। क्या आपके पास कुकीज़ हैं
इवान

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

11
दिन के अंत में, यहां काम का मूल सिद्धांत यह है कि आप अपने आप को आश्वस्त करने के लिए पर्याप्त परीक्षण लिखते हैं कि कोड काम करता है, और जब यह किसी को कुछ बदलता है, तो यह "कोयला खदान में पर्याप्त" कैनरी है। बस। कोई जादुई भस्मीकरण, फार्मूला संबंधी सपोजिशन या हठधर्मी दावे नहीं हैं, यही वजह है कि 85% से 90% कोड कवरेज (100% नहीं) को व्यापक रूप से उत्कृष्ट
रॉबर्ट हार्वे

5
@RobertHarvey दुर्भाग्य से फॉर्मूलाटिक प्लैटिट्यूड और टीडीडी ध्वनि काटता है, जबकि आप समझौते के उत्साही नोड्स अर्जित करना सुनिश्चित करते हैं, वास्तविक दुनिया की समस्याओं को हल करने में मदद नहीं करते हैं। इसके लिए आपको एक वास्तविक प्रश्न का उत्तर देने के लिए अपने हाथों को गंदा और जोखिम में
जोनाह

4
साइक्लोमैटिक जटिलता कम करने के क्रम में यूनिट परीक्षण। मेरा विश्वास करो, इस समारोह में जाने से पहले आप समय से बाहर भाग जाएंगे
नील मैकगिन

जवाबों:


118

savePeople()इकाई परीक्षण किया जाना चाहिए ? हाँ। आप परीक्षण नहीं कर रहे हैं कि dataStore.savePersonकाम करता है, या कि DB कनेक्शन काम करता है, या यहां तक ​​कि foreachकाम करता है। आप परीक्षण कर रहे हैं जो savePeopleअपने अनुबंध के माध्यम से किए गए वादे को पूरा करता है।

इस परिदृश्य की कल्पना करें: कोई व्यक्ति कोड आधार का एक बड़ा रिफ्लेक्टर करता है, और गलती forEachसे कार्यान्वयन के हिस्से को हटा देता है ताकि यह हमेशा केवल पहले आइटम को बचाता है। क्या आप एक इकाई परीक्षण नहीं चाहते हैं जो इसे पकड़ सके?


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

64
"आप परीक्षण कर रहे हैं कि savePeople अपने अनुबंध के माध्यम से किए गए वादे को पूरा करता है।" इस। इतना तो।
लोविस

2
जब तक आपके पास एक "अंत से अंत तक" प्रणाली का परीक्षण नहीं होता है जो इसे कवर करता है।
इयान

6
@ इयान एंड टू एंड टेस्ट यूनिट टेस्ट को रिप्लेस नहीं करते, वे कंफर्टेबल होते हैं। सिर्फ इसलिए कि आपके पास अंत से लेकर अंत तक का परीक्षण हो सकता है जो यह सुनिश्चित करता है कि आप लोगों की सूची को सहेज सकें, इसका मतलब यह नहीं है कि आपके पास इसे कवर करने के लिए इकाई परीक्षण भी नहीं होना चाहिए।
विंसेंट सवार्ड

4
@VincentSavard, लेकिन इकाई परीक्षण की लागत / लाभ को कम किया जाता है यदि जोखिम को अन्य तरीके से नियंत्रित किया जाता है।
इयान

36

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

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

अंत में, परीक्षण न केवल यह जांचेंगे कि क्या आप सही तरीके से एक Personको बचा सकते हैं Store, बल्कि कई व्यक्तियों को भी। उदाहरण के लिए, यदि अन्य जांचें आवश्यक हैं, तो मुझे यह प्रश्न करने की ओर ले जाएगा, "क्या मुझे यह सुनिश्चित करने की आवश्यकता है कि savePeopleफ़ंक्शन परमाणु है, या तो सभी को बचा रहा है या नहीं?", "क्या यह किसी तरह लोगों के लिए त्रुटियों को वापस कर सकता है जो नहीं कर सका? ' t को बचाया जा सकता है? उन त्रुटियों को कैसे देखा जाएगा? ", और इसी तरह। यह सब एक forEachया अन्य प्रकार के पुनरावृत्ति के उपयोग के लिए जाँच करने की तुलना में बहुत अधिक है ।

हालाँकि, यदि एक ही समय में एक से अधिक लोगों को बचाने की आवश्यकता केवल savePersonपहले से ही दी गई थी, तो मैं savePersonनए फ़ंक्शन के माध्यम से चलाने के मौजूदा परीक्षणों को अपडेट करूंगा savePeople, यह सुनिश्चित करते हुए कि यह अभी भी एक व्यक्ति को पहले से ही प्रतिनिधि बनाकर बचा सकता है, फिर नए परीक्षणों के माध्यम से एक से अधिक लोगों के लिए व्यवहार का परीक्षण करें, यह सोचें कि क्या व्यवहार को परमाणु बनाना आवश्यक होगा या नहीं।


4
मूल रूप से इंटरफ़ेस का परीक्षण करें, कार्यान्वयन का नहीं।
स्नूप

8
उचित और व्यावहारिक बिंदु। फिर भी मुझे लगता है कि किसी तरह मेरे असली सवाल को चकमा दिया जा रहा है :) आपका जवाब कह रहा है, "वास्तविक दुनिया में, एक अच्छी तरह से डिज़ाइन की गई प्रणाली में, मुझे नहीं लगता कि आपकी समस्या का यह सरलीकृत संस्करण मौजूद होगा।" फिर से, उचित, लेकिन मैंने विशेष रूप से एक अधिक सामान्य समस्या के सार को उजागर करने के लिए इस सरलीकृत संस्करण का निर्माण किया। यदि आप उदाहरण की कृत्रिम प्रकृति को नहीं पा सकते हैं, तो आप शायद एक और उदाहरण की कल्पना कर सकते हैं जिसमें आपके पास समान फ़ंक्शन के लिए एक अच्छा कारण है, जिसने केवल पुनरावृत्ति और प्रतिनिधिमंडल किया था। या शायद आप सोचते हैं कि यह असंभव है?
योना

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

अद्यतन के लिए धन्यवाद। आप वास्तव में कैसे परीक्षण करेंगे savePeople? जैसा कि मैंने ओपी के अंतिम पैराग्राफ में या किसी अन्य तरीके से वर्णित किया है?
योना

1
क्षमा करें, मैंने खुद को "कोई नकली शामिल नहीं" भाग के साथ स्पष्ट नहीं किया। मेरा मतलब था कि मैं savePersonआपके द्वारा सुझाए गए फ़ंक्शन के लिए एक नकली का उपयोग नहीं करूंगा , इसके बजाय मैं इसे और अधिक सामान्य परीक्षण करूँगा savePeople। इसके लिए यूनिट परीक्षणों को सीधे कॉल के बजाए Storeचलाने के लिए बदल दिया जाएगा , इसलिए इसके लिए किसी भी मोक्स का उपयोग नहीं किया जाता है। लेकिन निश्चित रूप से डेटाबेस मौजूद नहीं होना चाहिए, क्योंकि हम वास्तविक डेटाबेस के साथ होने वाली विभिन्न एकीकरण समस्याओं से कोडिंग की समस्याओं को अलग करना चाहते हैं, इसलिए यहां हमारे पास अभी भी एक नकली है। savePeoplesavePerson
3

21

SavePeople () इकाई परीक्षण किया जाना चाहिए

हाँ, यह चाहिए। लेकिन अपनी परीक्षा की शर्तों को इस तरह से लिखने की कोशिश करें जो कार्यान्वयन से स्वतंत्र हो। उदाहरण के लिए, अपने उपयोग के उदाहरण को एक इकाई परीक्षण में बदलना:

function testSavePeople() {
    myDataStore = new Store('some connection string', 'password');
    myPeople = ['Joe', 'Maggie', 'John'];
    savePeople(myDataStore, myPeople);
    assert(myDataStore.containsPerson('Joe'));
    assert(myDataStore.containsPerson('Maggie'));
    assert(myDataStore.containsPerson('John'));
}

यह परीक्षण कई काम करता है:

  • यह फ़ंक्शन के अनुबंध की पुष्टि करता है savePeople()
  • इसे लागू करने की परवाह नहीं है savePeople()
  • इसका उदाहरण उपयोग का दस्तावेज है savePeople()

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

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

या इस तरह के परीक्षण में निर्मित भाषा के निर्माण के परीक्षण के लिए राशि होगी?

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

आपके प्रश्न के अपडेट के बारे में:

राज्य परिवर्तन के लिए परीक्षण! उदाहरण के लिए, कुछ आटे का उपयोग किया जाएगा। आपके कार्यान्वयन के अनुसार, उपयोग की जाने वाली राशि का उपयोग किया doughगया है panया जोर देता doughहै। panफ़ंक्शन कॉल के बाद कुकीज़ को शामिल करें। दावा करें कि ovenपहले की तरह ही खाली / खाली है।

अतिरिक्त परीक्षणों के लिए, किनारे के मामलों की पुष्टि करें: ovenकॉल से पहले खाली न होने पर क्या होता है? यदि पर्याप्त नहीं है तो क्या होगा dough? यदि panपहले से ही भरा हुआ है?

आपको आटा, पैन और ओवन की वस्तुओं से इन परीक्षणों के लिए सभी आवश्यक डेटा को स्वयं करने में सक्षम होना चाहिए। फ़ंक्शन कॉल को कैप्चर करने की आवश्यकता नहीं है। फ़ंक्शन को मानें जैसे कि इसका कार्यान्वयन आपको उपलब्ध नहीं होगा!

वास्तव में, अधिकांश TDD उपयोगकर्ता फ़ंक्शन लिखने से पहले अपने परीक्षण लिखते हैं ताकि वे वास्तविक कार्यान्वयन पर निर्भर न हों।


अपने नवीनतम जोड़ के लिए:

जब कोई उपयोगकर्ता एक नया खाता बनाता है, तो कई चीजों का होना आवश्यक है: 1) डेटाबेस में एक नया उपयोगकर्ता रिकॉर्ड बनाने की आवश्यकता है 2) एक स्वागत योग्य ईमेल भेजने की आवश्यकता है 3) उपयोगकर्ता के आईपी पते को धोखाधड़ी के लिए रिकॉर्ड करने की आवश्यकता है प्रयोजनों।

इसलिए हम एक ऐसा तरीका बनाना चाहते हैं जो सभी "नए उपयोगकर्ता" चरणों को एक साथ जोड़े:

function createNewUser(validatedUserData, emailService, dataStore) {
    userId = dataStore.insertUserRecord(validateduserData);
    emailService.sendWelcomeEmail(validatedUserData);
    dataStore.recordIpAddress(userId, validatedUserData.ip);
}

इस तरह के एक समारोह के लिए मैं / स्टॉक / नकली (जो भी अधिक सामान्य लगता है) dataStoreऔर emailServiceमापदंडों का मजाक उड़ाएगा । यह फ़ंक्शन किसी भी पैरामीटर पर अपने आप में कोई स्टेट ट्रांज़िशन नहीं करता है, यह उन्हें उनमें से कुछ के तरीकों को दर्शाता है। मैं यह सत्यापित करने का प्रयास करूंगा कि फ़ंक्शन को कॉल ने 4 चीजें कीं:

  • इसने एक उपयोगकर्ता को डेटा स्टोर में डाला
  • इसने एक स्वागतयोग्य ईमेल भेजा (या कम से कम इसी पद्धति को कहा जाता है)
  • यह उपयोगकर्ताओं को डेटा स्टोर में IP दर्ज करता है
  • इसने किसी भी अपवाद / त्रुटि का प्रतिनिधित्व किया (यदि कोई हो)

पहले 3 चेक को मोक्स, स्टब्स या फेक के साथ किया जा सकता है dataStoreऔर emailService(आप वास्तव में परीक्षण करते समय ईमेल नहीं भेजना चाहते हैं)। चूँकि मुझे कुछ टिप्पणियों के लिए इसे देखना था, ये अंतर हैं:

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

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

अपेक्षित अपवाद / त्रुटियां वैध परीक्षण मामले हैं: आप पुष्टि करते हैं कि, यदि ऐसी कोई घटना होती है, तो फ़ंक्शन उस तरीके का व्यवहार करता है जिस तरह से आप अपेक्षा करते हैं। यह वांछित होने पर संबंधित नकली / नकली / ठूंठ वस्तु को फेंकने से प्राप्त किया जा सकता है।

मेरे भ्रम का सार यह है कि इस तरह के फ़ंक्शन को इकाई परीक्षण के लिए परीक्षण में सटीक कार्यान्वयन को दोहराने के लिए आवश्यक लगता है (यह निर्दिष्ट करके कि विधियों को एक निश्चित क्रम में मोक्स पर कहा जाता है) और यह गलत लगता है।

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

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

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

एक उदाहरण के लिए, oven.preheat()अपने कुकी बेकिंग उदाहरण में किसी को कॉल (अनुकूलन!) जोड़ने पर विचार करें :

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

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


1
समस्या यह है कि जैसे ही आप लिखते हैं myDataStore.containsPerson('Joe')आप एक कार्यात्मक परीक्षण डेटाबेस के अस्तित्व को मान रहे हैं। एक बार जब आप ऐसा कर लेते हैं, तो आप एकीकरण परीक्षण लिख रहे होते हैं न कि एक इकाई परीक्षण।
योना

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

स्पष्ट करने के लिए, यदि आप एक मॉक का उपयोग कर रहे हैं, तो आप केवल इतना कर सकते हैं कि उस मॉक पर एक विधि कहा जाता है , शायद कुछ विशिष्ट पैरामीटर के साथ। आप बाद में नकली की स्थिति पर जोर नहीं दे सकते। इसलिए यदि आप परीक्षण के तहत विधि को कॉल करने के बाद डेटाबेस की स्थिति पर जोर देना चाहते हैं myDataStore.containsPerson('Joe'), तो आपको किसी प्रकार के कार्यात्मक DB का उपयोग करना होगा। एक बार जब आप यह कदम उठा लेते हैं तो यह इकाई परीक्षण नहीं रह जाता है।
जोनाह

1
इसका वास्तविक डेटाबेस होना जरूरी नहीं है - सिर्फ एक ऑब्जेक्ट जो वास्तविक डेटा स्टोर के समान इंटरफ़ेस को लागू करता है (पढ़ें: यह डेटा स्टोर इंटरफ़ेस के लिए प्रासंगिक इकाई परीक्षण पास करता है)। मैं अभी भी इस पर विचार करूँगा। किसी सरणी में ऐसा करने के लिए किसी भी विधि द्वारा जोड़े जाने वाले सब कुछ को मॉक स्टोर करें और जांचें कि क्या सरणी में परीक्षण डेटा (तत्व myPeople) हैं। IMHO एक मॉक में अभी भी वही देखने योग्य व्यवहार होना चाहिए जो किसी वास्तविक ऑब्जेक्ट से अपेक्षित है, अन्यथा आप मॉक इंटरफ़ेस के अनुपालन के लिए परीक्षण कर रहे हैं, न कि वास्तविक इंटरफ़ेस के लिए।
हॉफमैले

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

13

इस तरह का परीक्षण प्रदान करने वाला प्राथमिक मूल्य यह है कि यह आपके क्रियान्वयन को परिष्कृत बनाता है।

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

दूसरी ओर, हम समय से पहले या तो अनुकूलन नहीं करना चाहते हैं। यदि आप आमतौर पर एक बार में केवल 1 - 3 लोगों को बचाते हैं, तो एक अनुकूलित बैच लिखना ओवरकिल हो सकता है।

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

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

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

मैं एक विचार जोड़ूंगा जो मुझे एक TDD प्रशिक्षक से मिला है। विधि का परीक्षण न करें। व्यवहार का परीक्षण करें। दूसरे शब्दों में, आप परीक्षण नहीं करते हैं कि savePeopleकाम करता है, आप परीक्षण कर रहे हैं कि एकाधिक उपयोगकर्ताओं को एक कॉल में बचाया जा सकता है।

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


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

1
@ jpmc26 एक परीक्षण के बारे में क्या है कि लोगों को बचाया गया था कि परीक्षण ...?
इबिबिस

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

1
@ मिनीबिस मैं उस उपयोगी परीक्षण पर विचार नहीं करता। नकली डेटा स्टोर का उपयोग करने से मुझे कोई विश्वास नहीं होता है कि यह वास्तविक चीज़ के साथ काम करेगा। मुझे कैसे पता है कि मेरे नकली काम असली चीज़ की तरह हैं? मैं बल्कि एकीकरण परीक्षणों के एक सूट को कवर करने देना चाहता हूं। (मुझे शायद यह स्पष्ट करना चाहिए कि यहां मेरी पहली टिप्पणी में मेरा मतलब "किसी भी इकाई परीक्षण" से है।)
jpmc26

1
@ मिनीबिस मैं वास्तव में अपनी स्थिति पर पुनर्विचार कर रहा हूं। मैं इस तरह की समस्याओं के कारण इकाई परीक्षणों के मूल्य के बारे में संदेह कर रहा हूं, लेकिन शायद मैं मूल्य को कम करके आंक रहा हूं, भले ही आप किसी इनपुट से बाहर नकली हों। मैं करना जानते हैं कि इनपुट / आउटपुट परीक्षण हो जाता है ज्यादा नकली भारी परीक्षण की तुलना में अधिक उपयोगी है, लेकिन साथ एक नकली वास्तव में समस्या का एक हिस्सा यहाँ है शायद एक इनकार एक इनपुट को बदलने के लिए।
jpmc26

6

bakeCookies()परीक्षण किया जाना चाहिए? हाँ।

इस तरह के एक फ़ंक्शन को यूनिट परीक्षण कैसे किया जाना चाहिए, यह मानते हुए कि आपको यह सोचना चाहिए? मेरे लिए किसी भी प्रकार के यूनिट टेस्ट की कल्पना करना कठिन है जो केवल आटा, पैन और ओवन का मजाक नहीं उड़ाता है, और फिर उस तरीके का दावा करता है जो उनके लिए कहा जाता है।

ज़रुरी नहीं। फ़ंक्शन को बारीकी से देखो कि क्या करना है - यह ovenकिसी विशिष्ट स्थिति में ऑब्जेक्ट सेट करना है । कोड को देखते हुए ऐसा प्रतीत होता है कि वस्तुओं panऔर doughवस्तुओं की स्थिति वास्तव में ज्यादा मायने नहीं रखती है। तो आपको एक ovenऑब्जेक्ट पास करना चाहिए (या इसे मॉक करना चाहिए ) और यह दावा करना चाहिए कि यह फ़ंक्शन कॉल के अंत में एक विशेष स्थिति में है।

दूसरे शब्दों में, आपको bakeCookies()कुकीज़ बेक करने का दावा करना चाहिए

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

यूनिट परीक्षण दो कार्य करता है:

  1. यह परीक्षण करता है कि सब कुछ काम करता है। यह कम से कम उपयोगी फ़ंक्शन इकाई परीक्षण कार्य करता है और ऐसा प्रतीत होता है कि प्रश्न पूछने पर आप केवल इस कार्यक्षमता पर विचार करते हैं।

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

फ़ंक्शन के अंदर कोड का परीक्षण न करें। इसके बजाय परीक्षण करें कि फ़ंक्शन वह करता है जो वह कहता है। जब आप इकाई परीक्षणों को इस तरह देखते हैं (परीक्षण कार्य, कोड नहीं) तो आपको एहसास होगा कि आप कभी भी भाषा निर्माण या यहां तक ​​कि तर्क का परीक्षण नहीं करते हैं। आप एक एपीआई का परीक्षण कर रहे हैं।


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

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

@ जेम्स_पिक, बिल्कुल। और हाँ, यह मॉक परिभाषा है जिसका मैं उपयोग कर रहा हूं। तो अपनी टिप्पणी दी, आप इस तरह के मामले में क्या करते हैं? परीक्षण को भूल जाओ? वैसे भी भंगुर, कार्यान्वयन-दोहराव परीक्षण लिखें? कुछ और?
जोनाह

@ जोना मैं आमतौर पर उस घटक के परीक्षण को एकीकरण परीक्षणों के साथ देखूँगा (मैंने पाया है कि इसके बारे में चेतावनियाँ डीबग करना कठिन हो सकता है, संभवतः आधुनिक टूलिंग की गुणवत्ता के कारण), या एक बनाने की मुसीबत पर जाएँ अर्ध-आश्वस्त नकली।
जेम्स_पिक

3

SavePeople () इकाई परीक्षण किया जाना चाहिए, या इस तरह के परीक्षण के निर्माण में निर्मित भाषा के निर्माण के परीक्षण के लिए राशि होगी?

हाँ। लेकिन आप इसे इस तरह से कर सकते हैं जो सिर्फ निर्माण को बनाए रखेगा।

यहां ध्यान देने वाली बात यह है कि जब savePersonआधा रास्ता विफल हो जाता है तो यह कार्य कैसे करता है ? यह कैसे काम करने वाला है?

यह सूक्ष्म व्यवहार का प्रकार है जो फ़ंक्शन प्रदान करता है कि आपको यूनिट परीक्षणों के साथ लागू करना चाहिए।


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

@ जोनाह: यदि आप अपनी यूनिट के परीक्षण को केवल foreachनिर्माण तक ही सीमित रखने पर जोर देने जा रहे हैं , और इसके बाहर किसी भी स्थिति, दुष्प्रभाव या व्यवहार नहीं हैं, तो आप सही हैं; नई इकाई परीक्षण वास्तव में यह सब दिलचस्प नहीं है।
रॉबर्ट हार्वे

1
@ जोनाह - क्या इसके माध्यम से पुनरावृति होनी चाहिए और संभव के रूप में कई को बचा सकता है या त्रुटि पर रोक सकता है? एकल बचत यह तय नहीं कर सकती , क्योंकि यह नहीं जान सकती कि इसका उपयोग कैसे किया जा रहा है।
तेलस्टीन

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

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

3

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

यह तथ्य कि परीक्षण लिखना बहुत आसान है, यह संकेत होना चाहिए कि आपका डिज़ाइन उतना बुरा नहीं है। क्या आप ऐसे डिज़ाइन को पसंद करेंगे जो परीक्षण करना आसान न हो?

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

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


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

1

SavePeople () इकाई परीक्षण किया जाना चाहिए, या इस तरह के परीक्षण के निर्माण में निर्मित भाषा के निर्माण के परीक्षण के लिए राशि होगी?

इसका उत्तर @BryanOakley ने पहले ही दे दिया है, लेकिन मेरे कुछ अतिरिक्त तर्क हैं (मुझे लगता है):

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

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

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

C ++ लिखते समय, मेरी कक्षाओं के लिए, मैं एक तुच्छ परीक्षा लिखना चाहता हूं जो किसी वस्तु को तत्काल लिखती है और इन्वर्टर (असाइन, नियमित, आदि) की जांच करती है। मुझे यह आश्चर्यजनक लगा कि विकास के दौरान यह परीक्षण कितनी बार टूटा है (उदाहरण के लिए - एक कक्षा में एक गैर-चल सदस्य जोड़कर, गलती से)।


1

मुझे लगता है कि आपका प्रश्न नीचे उबलता है:

एकीकरण इकाई होने के बिना मैं एक शून्य फ़ंक्शन का परीक्षण कैसे कर सकता हूं?

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

यदि हमें फ़ंक्शन को कॉल करने के बाद पैन कॉल करना है। हालांकि हम यह सवाल कर सकते हैं कि क्या इसका 'वास्तव में एकीकरण परीक्षण है' या 'लेकिन क्या हम पैन ऑब्जेक्ट का परीक्षण कर रहे हैं?'

मुझे लगता है कि आप इस बात में सही हैं कि यूनिट परीक्षण में हर चीज का मजाक उड़ाया गया है और सिर्फ xy और z को फंक्शन मान की कमी कहा गया है।

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

--- CreateNewUser उदाहरण के लिए अद्यतन करें

  • डेटाबेस में एक नया उपयोगकर्ता रिकॉर्ड बनाने की आवश्यकता है
  • एक स्वागत योग्य ईमेल भेजने की आवश्यकता है
  • उपयोगकर्ता के आईपी पते को धोखाधड़ी के उद्देश्यों के लिए रिकॉर्ड किया जाना चाहिए।

ठीक है, इसलिए इस बार फ़ंक्शन का परिणाम आसानी से वापस नहीं आया है। हम मापदंडों की स्थिति को बदलना चाहते हैं।

यह वह जगह है जहां मैं थोड़ा विवादास्पद हो जाता हूं। मैं राज्य के मापदंडों के लिए ठोस नकली कार्यान्वयन बनाता हूं

कृपया, प्रिय पाठकों, कोशिश करें और अपने गुस्से को नियंत्रित करें!

इसलिए...

var validatedUserData = new UserData(); //we can use the real object for this
var emailService = new MockEmailService(); //a simple mock which saves sentEmails to a List<string>
var dataStore = new MockDataStore(); //a simple mock which saves ips to a List<string>

//run the test
target.createNewUser(validatedUserData, emailService, dataStore);

//check the results
Assert.AreEqual(1, emailService.EmailsSent.Count());
Assert.AreEqual(1, dataStore.IpsRecorded.Count());
Assert.AreEqual(1, dataStore.UsersSaved.Count());

यह वांछित व्यवहार से परीक्षण के तहत विधि के कार्यान्वयन विवरण को अलग करता है। एक वैकल्पिक कार्यान्वयन:

function createNewUser(validatedUserData, emailService, dataStore) {
  userId = dataStore.bulkInsedrtUserRecords(new [] {validateduserData});
  emailService.addEmailToQueue(validatedUserData);
  emailService.ProcessQueue();
  dataStore.recordIpAddress(userId, validatedUserData.ip);
}

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


यह केवल एक एकीकरण परीक्षण नहीं है क्योंकि आप 2 ठोस वर्गों के नाम का उल्लेख करते हैं ... एकीकरण परीक्षण बाहरी सिस्टम के साथ एकीकरण के परीक्षण के बारे में हैं, जैसे डिस्क IO, DB, बाहरी वेब सेवाएँ और इतने पर। pan.getCookies () में है -मोरोरी, फास्ट, जिस चीज में हम रुचि रखते हैं, उसके लिए जांच आदि मैं सहमत हूं कि विधि कुकीज़ को सीधे वापस लेना बेहतर डिजाइन की तरह लगता है।
सारा

3
रुको। सभी के लिए हम जानते हैं कि pan.getcookies एक कुक को एक ईमेल भेजता है जब उन्हें मौका मिलने पर ओवन से कुकीज़ निकालने के लिए कहा जाता है
ईवान

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

2
यह एक आलंकारिक प्रश्न था, लेकिन: "किसने कभी ओवन उपकरण के बारे में सुना जो ईमेल भेजते हैं?" वेंचरबीट.कॉम 2016
03/

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

0

आपको परीक्षण भी करना चाहिए bakeCookies- क्या होना चाहिए / ई..जी bakeCookies(egg, pan, oven)उपज? तला हुआ अंडा या एक अपवाद? अपने दम पर, न तो panहै और न ही oven, वास्तविक सामग्री के बारे में परवाह करेगा क्योंकि उनमें से कोई भी करने वाले हैं, लेकिन bakeCookiesआम तौर पर कुकीज़ उपज चाहिए। आम तौर पर यह कैसे पर निर्भर कर सकता doughप्राप्त किया जाता है और वहाँ है कि क्या है यह मात्र बनने का कोई मौका eggया जैसे waterबजाय।

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