टीडीडी रेड-ग्रीन-रिफैक्टर और यदि / तो निजी बनने वाले तरीकों का परीक्षण कैसे करें


91

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

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

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

इसके बाद, मैं एक फ़ंक्शन, "collectNonNumericColumns" को जारी रखता हूं, जो एक बार में फ़ाइल, एक पंक्ति को पढ़ता है, और सभी स्तंभों को इकट्ठा करने के लिए प्रत्येक पंक्ति पर मेरे "findNonNumericFields" -function को कॉल करता है जो अंततः हटाए जाने चाहिए। लाल-हरे-चक्र के एक जोड़े, और मैं कर रहा हूं, फिर से काम कर रहा है और एक पूर्ण परीक्षण।

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

इसलिए, मैं एक निजी विधियों और परीक्षण के एक सूट के साथ अंत करता हूं जो इसे परीक्षण करता है। चूंकि बहुत से लोग सलाह देते हैं कि निजी तरीकों का परीक्षण नहीं किया जाना चाहिए, ऐसा लगता है कि मैंने खुद को यहां एक कोने में चित्रित किया है। लेकिन वास्तव में मैं कहाँ असफल रहा?

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

इसलिए क्या करना है? क्या TDD (तीव्र लाल-हरे-परावर्तक चक्र के साथ) बस निजी विधियों के अनुकूल नहीं है? या मेरे डिजाइन में कोई खराबी है?



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

26
लोग प्रोग्रामिंग की किताबों और ब्लॉगों से मुहावरों और क्लिच को क्यों लेते हैं, इस पर वास्तविक दिशा-निर्देश हैं कि कैसे मेरे लिए कार्यक्रम है।
AK_

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

1
"अधिकांश लोग इस बात से सहमत प्रतीत होते हैं कि निजी विधियों का सीधे परीक्षण नहीं किया जाना चाहिए" - नहीं, ऐसा करने के लिए समझ में आने पर सीधे किसी विधि का परीक्षण करें। इसे ऐसे छिपाएं जैसे privateयह करने के लिए समझ में आता है।
osa

जवाबों:


44

इकाइयों

मुझे लगता है कि जहां समस्या शुरू हुई, मैं उसे सटीक रूप से इंगित कर सकता हूं:

मुझे लगा, मुझे एक विधि की आवश्यकता होगी जो सभी गैर-संख्यात्मक क्षेत्रों को एक पंक्ति में ढूंढती है।

अपने आप से यह पूछने के साथ तुरंत पालन किया जाना चाहिए "क्या यह एक अलग परीक्षण योग्य इकाई होगी gatherNonNumericColumnsया उसी के हिस्से के लिए?"

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

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


एक छोटा सा चक्र रखते हुए

उपरोक्त करने से आपको उन समस्याओं के लिए नेतृत्व नहीं करना चाहिए जो आप अपने पैराग्राफ में बताए गए हैं:

क्योंकि अगर मैं किसी सार्वजनिक पद्धति के लिए परीक्षण लिखकर शुरू करता हूं, तो निजी तरीकों में काम करने के लिए सभी विवरण प्राप्त करने से पहले कई मिनट (या घंटे, या बहुत जटिल मामलों में दिन) होंगे ताकि परीक्षण का परीक्षण सार्वजनिक हो जाए विधि गुजरती है।

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


रोडमैप

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


2
मुझे लगता है कि यहीं जवाब है। एक ओओपी वातावरण में टीडीडी को अपनाने से, मैंने अक्सर खुद को अपने नीचे-ऊपर की प्रवृत्ति पर काबू पाने के लिए कठिन समय पाया है। हां, फ़ंक्शंस छोटे होने चाहिए, लेकिन यह रीफैक्टरिंग के बाद है। इससे पहले, वे विशाल मोनोलिथ हो सकते हैं। +1
जोओ मेंडेस

2
@ JoãoMendes खैर, मुझे यकीन नहीं है कि आपको रिफैक्टरिंग करने से पहले एक विशाल मोनोलिथ की स्थिति को प्राप्त करना चाहिए, विशेष रूप से बहुत कम आरजीआर चक्रों पर। लेकिन हाँ, एक परीक्षण योग्य इकाई के भीतर , नीचे काम करने से ओपी का वर्णन करने वाली समस्याएं हो सकती हैं।
बेन आरोनसन

1
ठीक है, मुझे लगता है कि मैं समझता हूं कि यह अब गलत कहां हो गया है। आप सभी को बहुत-बहुत धन्यवाद (इस एक को उत्तर के रूप में चिन्हित किया, लेकिन अधिकांश अन्य उत्तर भी उतने ही मददगार हैं)
हेनरिक बर्ग

66

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

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

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

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

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

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

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


14
मेरे लिए ऐसा लगता है कि यह जवाब पूरी तरह से ओपी के प्रश्न में टीडीडी दृष्टिकोण की उपेक्षा करता है। यह सिर्फ "निजी तरीकों का परीक्षण नहीं है" मंत्र की पुनरावृत्ति है, लेकिन यह स्पष्ट नहीं होता कि कैसे TDD - जो है वास्तव में विधि आधारित - एक गैर विधि आधारित इकाई परीक्षण दृष्टिकोण के साथ काम कर सकते हैं।
डॉक्टर ब्राउन

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

3
@ जीबीजैनब: एक परीक्षण का सुझाव देने की कोशिश करें, जो ओपी को पहले "टीडीडी" का उपयोग करके अपने "गैर-संख्यात्मक क्षेत्रों को एक पंक्ति में इकट्ठा करने" की अनुमति देता है, बिना वर्ग के सार्वजनिक इंटरफ़ेस के बिना वह पहले से ही लिखित लिखने का इरादा रखता है।
डॉक्टर ब्राउन

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

7
@ मैथ्यू: उनकी गलती यह है कि उन्होंने फंक्शन को पहले स्थान पर लिखा। आदर्श रूप में, उन्हें सार्वजनिक विधि को स्पेगेटी कोड के रूप में लिखना चाहिए था फिर इसे रिफैक्टर चक्र में एक निजी फ़ंक्शन में रिफ्लेक्टर करना चाहिए - इसे रिफ्लेक्टर चक्र में निजी के रूप में चिह्नित नहीं करना चाहिए।
स्लीवतमैन

51

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

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

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


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

"अलग से पर्याप्त" के बारे में: मैंने सीखा है (चाचा से फिर से) जो कार्य छोटा होना चाहिए, और यह कि वे उससे छोटा होना चाहिए। इसलिए मूल रूप से मैं 3-4 लाइन फंक्शन बनाने की कोशिश करता हूं। तो कमोबेश सभी कार्यक्षमता को अपने तरीके से अलग किया जाता है, चाहे वह कितना भी छोटा और सरल क्यों न हो।
हेनरिक बर्ग

वैसे भी, मुझे लगता है कि डेटा-मुंगिंग पहलुओं (जैसे, findNonNumericFields) को वास्तव में निजी होना चाहिए। और अगर मैं इसे किसी अन्य वर्ग में अलग करता हूं, तो मुझे इसे वैसे भी सार्वजनिक करना होगा, इसलिए मुझे इसमें कोई बात नहीं दिख रही है।
हेनरिक बर्ग

6
@HenrikBerg को लगता है कि आपके पास पहली जगह में ऑब्जेक्ट क्यों हैं - वे समूह कार्यों के लिए सुविधाजनक तरीके नहीं हैं, लेकिन स्वयं-निहित इकाइयां हैं जो जटिल सिस्टम को काम करना आसान बनाते हैं। इसलिए, आपको कक्षा को एक चीज के रूप में परीक्षण करने के बारे में सोचना चाहिए।
gbjbaanb

@gbjbaanb मैं तर्क दूंगा कि वे दोनों एक ही हैं।
रबरडक

29

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

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

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


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

11

आप आंतरिक रूप से कक्षा क्या करेंगे, इसके आधार पर आप टीडीडी नहीं करते हैं।

आपके परीक्षण मामले बाहरी दुनिया के लिए कक्षा / कार्यक्षमता / कार्यक्रम के आधार पर होना चाहिए। आपके उदाहरण में, क्या उपयोगकर्ता कभी आपके पाठक वर्ग को कॉल करेगाfind all the non-numerical fields in a line?

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

TDD का प्रवाह है:

  • लाल (बाहरी दुनिया के लिए वर्ग / वस्तु / कार्य / आदि क्या है)
  • हरा (इस बाहरी विश्व कार्य को बनाने के लिए न्यूनतम कोड लिखें)
  • रिफैक्टर (इस काम को करने के लिए बेहतर कोड क्या है)

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

यदि आप अपने आप को अक्सर उन तरीकों के लिए परीक्षण लिखते हैं जो निजी तरीके बन जाते हैं तो आप कुछ चीजों में से एक कर रहे हैं:

  • अपने इंटरफ़ेस / सार्वजनिक स्तर को सही ढंग से न समझकर उनके लिए परीक्षण लिखने के लिए मामलों का अच्छी तरह से उपयोग करें
  • नाटकीय रूप से अपने डिज़ाइन को बदलना और कई परीक्षणों को दूर करना (जो कि एक अच्छी बात हो सकती है, यह इस बात पर निर्भर करता है कि नए परीक्षणों में कार्यक्षमता का परीक्षण किया गया है)

9

आप सामान्य रूप से परीक्षण के साथ एक आम गलतफहमी का सामना कर रहे हैं।

अधिकांश लोग जो परीक्षण के लिए नए हैं वे इस तरह से सोचना शुरू करते हैं:

  • फ़ंक्शन F के लिए एक परीक्षण लिखें
  • एफ लागू करें
  • फ़ंक्शन G के लिए एक परीक्षण लिखें
  • F को कॉल का उपयोग करके G लागू करें
  • फ़ंक्शन एच के लिए एक परीक्षण लिखें
  • G को कॉल का उपयोग करके H को लागू करें

और इसी तरह।

यहाँ समस्या यह है कि वास्तव में आपके पास फ़ंक्शन एच के लिए कोई इकाई परीक्षण नहीं है। जिस परीक्षण को एच का परीक्षण करना है, वह वास्तव में उसी समय एच, जी और एफ का परीक्षण कर रहा है।

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

यह वास्तव में कैसे किया जा सकता है यह आपकी प्रोग्रामिंग भाषा पर निर्भर करता है। कई भाषाओं में आप अन्य कार्यों के तर्क के रूप में फ़ंक्शंस (या उनके लिए संकेत) पास कर सकते हैं। यह आपको अलगाव में प्रत्येक फ़ंक्शन का परीक्षण करने में सक्षम करेगा।


3
काश मैं इसे कई बार वोट कर पाता। मैं बस इसे संक्षेप में बताऊंगा, आपने अपना समाधान सही ढंग से नहीं किया है।
जस्टिन ओम्स

C जैसी भाषा में, यह समझ में आता है, लेकिन OO भाषाओं के लिए जहां इकाई को आम तौर पर एक वर्ग होना चाहिए (सार्वजनिक और निजी तरीकों के साथ) तब आपको कक्षा का परीक्षण करना चाहिए, न कि प्रत्येक निजी विधि को अलग-थलग करना चाहिए। अपनी कक्षाओं को अलग करते हुए, हाँ। प्रत्येक कक्षा में विधियों को अलग करते हुए, नहीं।
gbjbaanb

8

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

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

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

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


4

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

(मैं पूरी तरह से स्पष्ट नहीं हूं कि आपका कार्य क्या करता है। क्या यह गैर-संख्यात्मक मानों के साथ फ़ाइल सामग्री के साथ एक स्ट्रिंग लौटाता है?)

यदि आपकी विधि एक स्ट्रिंग लौटाती है तो आप उस रिटर्न मान की जांच करते हैं। तो आप बस इसका निर्माण जारी रखें।

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


3

ऐसा लगता है कि मैंने खुद को यहां एक कोने में चित्रित किया है। लेकिन वास्तव में मैं कहाँ असफल रहा?

एक पुरानी कहावत है।

जब आप योजना बनाने में विफल रहते हैं तो आप विफलता की योजना बना रहे होते हैं।

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

हांफते हुए मैंने कोई भी टेस्ट लिखने से पहले कुछ "कोड" लिखे! नहीं। मैंने नहीं किया। मैंने एक अनुबंध लिखा जिसका पालन किया जाना चाहिए, एक डिज़ाइन । मुझे संदेह है कि आप ग्राफ पेपर पर एक यूएमएल आरेख नीचे लिखकर समान परिणाम प्राप्त कर सकते हैं। मुद्दा यह है, आपके पास एक योजना होनी चाहिए। TDD कोड के एक टुकड़े पर विली नीली हैकिंग जाने का लाइसेंस नहीं है।

मुझे वास्तव में ऐसा लगता है कि "टेस्ट फर्स्ट" एक मिथ्या नाम है। डिजाइन पहले तो परीक्षण।

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


2

याद रखें कि परीक्षणों को भी रिफैक्ट किया जा सकता है! यदि आप एक विधि को निजी बनाते हैं, तो आप सार्वजनिक API को कम कर रहे हैं, और इसलिए यह "खो कार्यक्षमता" (AKA कम की जटिलता) के लिए कुछ इसी परीक्षण को फेंकने के लिए पूरी तरह से स्वीकार्य है।

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

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

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


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

2

ऐसे समय होते हैं जब किसी निजी पद्धति को दूसरे वर्ग की सार्वजनिक पद्धति बनाया जा सकता है।

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

(यह तब स्पष्ट होता है जब आप कल्पना करते हैं कि कोई सूची वर्ग नहीं था, और यदि आपने सूची के कार्यों को निजी विधियों के रूप में लागू करने का प्रयास किया जो उस श्रेणी में हैं।)


2
"ऐसे समय होते हैं जब किसी निजी पद्धति को दूसरे वर्ग का सार्वजनिक तरीका बनाया जा सकता है।" मैं इस पर और अधिक ज़ोर नहीं दे सकता। कभी-कभी, एक निजी तरीका अपनी पहचान के लिए चिल्लाता हुआ एक और वर्ग होता है।

0

मुझे आश्चर्य है कि आपकी भाषा में गोपनीयता के दो स्तर क्यों हैं, पूरी तरह से सार्वजनिक और पूरी तरह से निजी।

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

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


3
परीक्षण चलाने के लिए सिर्फ एक विधि अभिगम संशोधक बदलना एक ऐसी स्थिति है जहां एक पूंछ एक कुत्ते को बंद कर देती है। मुझे लगता है कि एक इकाई के आंतरिक भागों का परीक्षण करना केवल बाद में रिफ्लेक्टर को कठिन बना रहा है। सार्वजनिक इंटरफ़ेस का परीक्षण करना, इसके विपरीत, महान है क्योंकि यह एक इकाई के लिए "अनुबंध" के रूप में काम करता है।
scriptin

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

0

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


0

मैंने यह अनुभव किया है और आपका दर्द महसूस किया है।

मेरा समाधान यह था:

मोनोलिथ के निर्माण जैसे परीक्षणों को रोकना।

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

उदाहरण के लिए मेरे पास अक्सर है:

  • निम्न स्तर की परीक्षा १
  • इसे पूरा करने के लिए कोड
  • निम्न स्तर की परीक्षा २
  • इसे पूरा करने के लिए कोड
  • निम्न स्तर की परीक्षा ३
  • इसे पूरा करने के लिए कोड
  • निम्न स्तर की परीक्षा ४
  • इसे पूरा करने के लिए कोड
  • निम्न स्तर की परीक्षा ५
  • इसे पूरा करने के लिए कोड

तो मेरे पास है

  • निम्न स्तर की परीक्षा १
  • निम्न स्तर की परीक्षा २
  • निम्न स्तर की परीक्षा ३
  • निम्न स्तर की परीक्षा ४
  • निम्न स्तर की परीक्षा ५

हालाँकि, अगर मैं अब उच्च स्तर के फंक्शन जोड़ता हूँ, जो इसे कहते हैं, जिसमें बहुत सारे परीक्षण हैं, तो मैं अब उन निम्न स्तर के परीक्षणों को कम करने में सक्षम हो सकता हूँ :

  • निम्न स्तर की परीक्षा १
  • निम्न स्तर की परीक्षा ५

शैतान विवरणों में है और इसे करने की क्षमता परिस्थितियों पर निर्भर करेगी।


-2

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

इसे आज़माएं: दो विधियाँ जोड़ें, एक जिसमें कोई इनपुट नहीं है, लेकिन सिर्फ निजी परीक्षणों की संख्या वापस करता है और एक जो एक पैरामीटर के रूप में एक परीक्षण संख्या लेता है और पास / असफल हो जाता है।


1
चुने गए अपमानों का उपयोग गैलीलियो और द पोप द्वारा किया गया था, इस प्रश्न के किसी भी उत्तर द्वारा नहीं।
14
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.