यूनिट टेस्ट पास करने के लिए न्यूनतम कोड लिखना - बिना धोखा दिए!


36

TDD कर रहे हैं और एक इकाई परीक्षण लिख रहे हैं, "परीक्षण" कोड के पहले पुनरावृत्ति को लिखते समय आप "धोखा" देने का आग्रह कैसे करते हैं कि आप परीक्षण कर रहे हैं?

उदाहरण के लिए:
आइए मुझे किसी संख्या के गुणनखंड की गणना करने की आवश्यकता है। मैं एक इकाई परीक्षण (MSTest का उपयोग करके) कुछ इस तरह से शुरू करता हूं:

[TestClass]
public class CalculateFactorialTests
{
    [TestMethod]
    public void CalculateFactorial_5_input_returns_120()
    {
        // Arrange
        var myMath = new MyMath();
        // Act
        long output = myMath.CalculateFactorial(5);
        // Assert
        Assert.AreEqual(120, output);
    }
}

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

बात यह है, मैं लगातार निम्नलिखित लिखने के लिए ललचा रहा हूँ:

public class MyMath
{
    public long CalculateFactorial(long input)
    {
        return 120;
    }
}

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

तो, मेरा सवाल यह है कि "टेस्ट पास करने के लिए न्यूनतम कोड लिखने" के बीच आप उस संतुलन को कैसे प्राप्त करते हैं?


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

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

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

3
यदि यह पता चलता है कि क्लाइंट कोड कोड केवल 5 में ही गुजरता है, तो 120 वापस करना न सिर्फ धोखा है, बल्कि वास्तव में एक वैध समाधान है।
क्रामि ने मोनिका

मैं @PaBButcher से सहमत हूं - वास्तव में, ग्रंथों और लेखों में बहुत सारे यूनिट परीक्षण उदाहरण इस दृष्टिकोण को ले जाएंगे।
होरस्कॉल

जवाबों:


45

यह पूरी तरह से कानूनी है। लाल, हरा, रिफलेक्टर।

पहला टेस्ट पास करता है।

नए इनपुट के साथ, दूसरा परीक्षण जोड़ें।

अब जल्दी से हरे रंग के लिए, आप एक और जोड़ सकते हैं, जो ठीक काम करता है। यह गुजरता है, लेकिन आप अभी तक नहीं किए गए हैं।

रेड, ग्रीन, रिफैक्टर का तीसरा भाग सबसे महत्वपूर्ण है। दोहराव को दूर करने के लिए रिफ्लेक्टर । अब आपके कोड में दोहराव होगा। दो कथन पूर्णांक लौटाते हैं। और उस दोहराव को हटाने का एकमात्र तरीका फ़ंक्शन को सही ढंग से कोड करना है।

मैं यह नहीं कह रहा हूँ कि यह पहली बार सही ढंग से नहीं लिखें। मैं कह रहा हूँ कि यह धोखा नहीं है यदि आप नहीं करते हैं।


12
यह सिर्फ सवाल उठाता है, क्यों न केवल फ़ंक्शन को सही तरीके से लिखा जाए?
रॉबर्ट हार्वे

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

1
@ रॉबर्ट, यह आप ही हैं जो परीक्षा पास करने के बजाय समस्या को हल करने के बारे में चिंतित हैं। मैं आपको बता रहा हूं कि गैर-तुच्छ समस्याओं के लिए यह कठिन डिजाइन को स्थगित करने के लिए बेहतर काम करता है जब तक कि आपके पास परीक्षण न हों।

1
@ Thorbjørn रावन एंडरसन, नहीं, मैं यह नहीं कह रहा हूं कि आपके पास केवल एक रिटर्न हो सकता है। कई (यानी, गार्ड स्टेटमेंट) के वैध कारण हैं। मुद्दा यह है कि, दोनों रिटर्न स्टेटमेंट "बराबर" थे। उन्होंने वही did बात ’की। वे सिर्फ विभिन्न मूल्यों के लिए हुए थे। TDD कठोरता, और परीक्षण / कोड अनुपात के एक विशिष्ट आकार का पालन करने के बारे में नहीं है। यह आपके कोड आधार के भीतर एक आराम स्तर बनाने के बारे में है। यदि आप एक असफल परीक्षण लिख सकते हैं, तो एक फ़ंक्शन जो उस फ़ंक्शन के भविष्य के परीक्षण के लिए काम करेगा, महान। ऐसा करें, फिर अपने एज केस के परीक्षण को सुनिश्चित करें कि आपका फ़ंक्शन अभी भी काम करता है।
कैफ़ीक नेक

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

25

स्पष्ट रूप से अंतिम लक्ष्य की समझ, और उस लक्ष्य को पूरा करने वाले एल्गोरिथ्म की उपलब्धि की आवश्यकता है।

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

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

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

चाचा बॉब मार्टिन यह कहते हैं:

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

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

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


वास्तव में सवाल का जवाब नहीं, लेकिन 1+
कोई भी

2
@rmx: उम, सवाल यह है: "परीक्षण पास करने के लिए न्यूनतम कोड लिखने" के बीच आप उस संतुलन को कैसे प्राप्त करते हैं? क्या हम वही प्रश्न पढ़ रहे हैं?
रॉबर्ट हार्वे

आदर्श समाधान एक एल्गोरिथ्म है और इसका वास्तुकला से कोई लेना-देना नहीं है। टीडीडी करने से आप एल्गोरिदम का आविष्कार नहीं कर पाएंगे। कुछ बिंदु पर आपको एक एल्गोरिथ्म / समाधान के संदर्भ में कदम बनाने की आवश्यकता है।
जोप नोव

मैं @rmx से सहमत हूं। यह वास्तव में मेरे विशिष्ट प्रश्न का उत्तर नहीं देता है, प्रति se, लेकिन यह विचार के लिए भोजन को जन्म देता है कि कैसे TDD सामान्य रूप से समग्र सॉफ्टवेयर विकास प्रक्रिया की बड़ी तस्वीर में फिट बैठता है। तो, इस कारण से, +1।
क्रेगटीपी

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

16

एक बहुत अच्छा सवाल ... और मुझे @Robert को छोड़कर लगभग सभी से असहमत होना पड़ा है।

लिख रहे हैं

return 120;

एक फैक्टरियल फ़ंक्शन के लिए एक टेस्ट पास करना समय की बर्बादी है । यह "धोखा" नहीं है, न ही यह लाल-हरा-रिफ्लेक्टर का शाब्दिक रूप से पालन कर रहा है। यह गलत है

यहाँ पर क्यों:

  • गणना फैक्टरियल की विशेषता है, न कि "एक स्थिर लौटें"। "वापसी 120" एक गणना नहीं है।
  • 'रिफ्लेक्टर' के तर्क गुमराह करते हैं; अगर आप 5 और 6 के लिए दो परीक्षण मामलों है, इस कोड, गलत अब भी है, क्योंकि आप एक भाज्य की गणना नहीं कर रहे हैं सभी पर :

    if (input == 5) { return 120; } //input=5 case
    else { return 720; }   //input=6 case
    
  • यदि हम 'रिफ्लेक्टर' तर्क का अक्षरशः पालन ​​करते हैं , तो जब हमारे पास 5 परीक्षण मामले होंगे तो हम YAGNI को आमंत्रित करेंगे और लुकअप टेबल का उपयोग करके फ़ंक्शन को लागू करेंगे:

    if (factorialDictionary.Contains(input)) {
        return factorialDictionary[input]; 
    }
    throw new Exception("Input failure");
    

इनमें से कोई भी वास्तव में कुछ भी गणना नहीं कर रहा है, आप हैं । और यह काम नहीं है!


1
@rmx: नहीं, यह याद नहीं था; "डुप्लीकेशन हटाने के लिए रिफ्लेक्टर" एक लुकअप टेबल से संतुष्ट हो सकता है। BTW सिद्धांत है कि यूनिट परीक्षण आवश्यकताओं को एन्कोड करता है BDD के लिए विशिष्ट नहीं है, यह एजाइल / एक्सपी का एक सामान्य सिद्धांत है। यदि आवश्यकता थी "प्रश्न का उत्तर दें '5' का भाज्य क्या है" तो 'वापसी 120'? कानूनी होगा ;-)
स्टीवन ए। लोव

2
@ जो सभी अनावश्यक काम है - बस फ़ंक्शन को पहली बार लिखें ;-)
स्टीवन ए लोवे

2
@Steven A.Lowe, उस तर्क से, कोई परीक्षण क्यों लिखते हैं ?! "बस पहली बार आवेदन लिखो!" टीडीडी का बिंदु, छोटा, सुरक्षित, वृद्धिशील परिवर्तन है।
कैफीक नेक

1
@Chad: स्ट्रोमैन।
स्टीवन ए। लोव

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

10

जब आपने केवल एक इकाई परीक्षण लिखा है, तो एक-पंक्ति कार्यान्वयन ( return 120;) वैध है। 120 के मान की गणना करते हुए एक लूप लिखना - जो धोखा होगा!

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

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


2
"-1" मामला दिलचस्प होगा। क्योंकि यह अच्छी तरह से परिभाषित नहीं है, इसलिए परीक्षण लिखने वाले और कोड लिखने वाले लड़के दोनों को पहले सहमत होना चाहिए कि क्या होना चाहिए।
gnasher729

2
+1 वास्तव में इंगित करने के लिए कि factorial(5)यह एक बुरा पहला परीक्षण है। हम सबसे सरल संभव मामलों से शुरू करते हैं और प्रत्येक पुनरावृत्ति में हम परीक्षणों को थोड़ा अधिक विशिष्ट बनाते हैं, कोड को थोड़ा सामान्य बनाने का आग्रह करते हैं। यह चाचा बॉब परिवर्तन प्राथमिकता को आधार कहता है ( blog.8thlight.com/uncle-bob/2013/05/27/… )
सारा

5

जब तक आपके पास केवल एक ही परीक्षण होता है, तब परीक्षण पास करने के लिए आवश्यक न्यूनतम कोड सही मायने में होता है return 120;, और आप इसे आसानी से तब तक रख सकते हैं जब तक आपके पास कोई और परीक्षण न हो।

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

कृपया याद रखें कि परीक्षण आपके विनिर्देश का रन करने योग्य संस्करण है, और यदि वह सभी विनिर्देश कहता है कि f (6) = 120 है तो बिल को पूरी तरह से फिट बैठता है।


गंभीरता से? इस तर्क के द्वारा, आपको हर बार किसी नए इनपुट के साथ आने वाले कोड को फिर से लिखना होगा।
रॉबर्ट हार्वे

6
@Robert, SOME बिंदु पर एक नया मामला जोड़ने से अब सबसे सरल संभव कोड नहीं होगा, जिस बिंदु पर आप एक नया कार्यान्वयन लिखते हैं। जैसा कि आपके पास पहले से ही परीक्षण हैं, आप ठीक से जानते हैं कि आपका नया कार्यान्वयन पुराने के समान ही है।

1
@ Thorbjørn रावन एंडरसन, वास्तव में, रेड-ग्रीन-रिफैक्टर का सबसे महत्वपूर्ण हिस्सा, रिफैक्टरिंग है।
कैफ़ीक नेक

+1: यह मेरे ज्ञान के साथ-साथ सामान्य विचार है, लेकिन निहित अनुबंध को पूरा करने के बारे में कुछ कहा जाना चाहिए (यानी, विधि नाम फैक्टोरियल )। यदि आप केवल कभी कल्पना करते हैं (अर्थात परीक्षण) f (6) = 120 तो आपको केवल '120 वापस' करने की आवश्यकता है। एक बार जब आप यह सुनिश्चित करने के लिए परीक्षण जोड़ना शुरू कर देते हैं कि f (x) == x * x-1 ... * xx-1: UpperBound> = x> = 0 तो आप एक ऐसे फंक्शन में पहुंचेंगे जो फैक्टरियल समीकरण को संतुष्ट करता है।
स्टीवन एवर्स

1
@SnOrfus, "निहित अनुबंध" के लिए जगह परीक्षण मामलों में है। यदि आप अनुबंध factorials के लिए है, तो आप परीक्षण करते हैं यदि ज्ञात factorials हैं और यदि ज्ञात non-factorials नहीं हैं। उनमें से बहुत कुछ। दस पहले factorials की सूची को एक लूप परीक्षण के लिए दसवें factorial तक हर संख्या में बदलने में लंबा समय नहीं लगता है।

4

यदि आप इस तरह से "धोखा" देने में सक्षम हैं, तो यह सुझाव देता है कि आपकी इकाई परीक्षण त्रुटिपूर्ण हैं।

एकल मान के साथ फैक्टोरियल विधि का परीक्षण करने के बजाय, यह मानों की एक श्रृंखला थी। डेटा-संचालित परीक्षण यहां मदद कर सकता है।

अपनी इकाई परीक्षणों को आवश्यकताओं की अभिव्यक्ति के रूप में देखें - उन्हें सामूहिक रूप से उस पद्धति के व्यवहार को परिभाषित करना होगा जो वे परीक्षण करते हैं। (यह व्यवहार संचालित विकास के रूप में जाना जाता है - इसका भविष्य ;-))

तो अपने आप से पूछें - अगर किसी को गलत तरीके से कार्यान्वयन को बदलना था, तो क्या आपके परीक्षण अभी भी पास होंगे या वे कहेंगे "एक मिनट पर लटकाओ!"।

इस बात को ध्यान में रखते हुए, यदि आपका एकमात्र परीक्षण आपके प्रश्न में से एक था, तो तकनीकी रूप से, संबंधित कार्यान्वयन सही है। समस्या को तब खराब-परिभाषित आवश्यकताओं के रूप में देखा जाता है।


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

आप तकनीकी रूप से से मूल्यों का परीक्षण कर सकते Int64.MinValueकरने के लिए Int64.MaxValue। इसे चलाने में लंबा समय लगेगा लेकिन यह स्पष्ट रूप से त्रुटि के लिए कमरे की आवश्यकता को परिभाषित नहीं करेगा। वर्तमान तकनीक के साथ, यह अक्षम्य है (मुझे संदेह है कि यह भविष्य में अधिक सामान्य हो सकता है) और मैं सहमत हूं, आप धोखा दे सकते हैं लेकिन मुझे लगता है कि ओपी प्रश्न एक व्यावहारिक नहीं था (कोई भी वास्तव में इस तरह से धोखा नहीं देगा व्यवहार में), लेकिन एक सैद्धांतिक एक।
कोई भी

@rmx: यदि आप ऐसा कर सकते हैं, तो परीक्षण एल्गोरिथ्म होगा, और आपको एल्गोरिथ्म लिखने की आवश्यकता नहीं होगी।
रॉबर्ट हार्वे

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

इसके अलावा, क्या हम इंसानों के रूप में, यूनिट-परीक्षणों में गलती करने की संभावना रखते हैं जैसा कि हम कार्यान्वयन कोड में हैं? तो इकाई परीक्षण आखिर क्यों?
कोई भी

3

अभी और परीक्षण लिखो। आखिरकार, यह लिखना कम होगा

public long CalculateFactorial(long input)
{
    return input <= 1 ? 1 : CalculateFactorial(input-1)*input;
}

से

public long CalculateFactorial(long input)
{
    switch (input) {
       case 0: return 1;
       case 1: return 1;
       case 2: return 2;
       case 3: return 6;
       case 4: return 24;
       case 5: return 120;
    }
}

:-)


3
जो पहले से ही एल्गोरिथ्म को सही तरीके से नहीं लिखता है?
रॉबर्ट हार्वे

3
@Robert, यह है इसके अलावा 5. 0 से किसी संख्या का फ़ैक्टोरियल की गणना के लिए सही एल्गोरिथ्म, क्या करता है "सही ढंग से" मतलब? यह एक बहुत ही सरल उदाहरण है, लेकिन जब यह अधिक जटिल हो जाता है, तो "सही" के कई अर्थ हो जाते हैं। क्या एक प्रोग्राम जिसे रूट एक्सेस की आवश्यकता है "सही" पर्याप्त है? CSV का उपयोग करने के बजाय XML "सही" का उपयोग कर रहा है? आप इसका जवाब नहीं दे सकते। कोई भी एल्गोरिथ्म तब तक सही है जब तक कि यह कुछ व्यावसायिक आवश्यकताओं को पूरा करता है, जिसे टीडीडी में परीक्षण के रूप में तैयार किया गया है।
पी शुड

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

3

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

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

साझा करें और आनंद लें।


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

1

मैं रॉबर्ट हार्वेस के सुझाव से 100% सहमत हूं, यह सिर्फ टेस्ट पास करने के बारे में नहीं है, आपको समग्र लक्ष्य को भी ध्यान में रखना होगा।

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

Factorials के लिए, एक परीक्षण इस तरह दिखेगा:

    [Theory]
    [InlineData(0, 1)]
    [InlineData( 1, 1 )]
    [InlineData( 2, 2 )]
    [InlineData( 3, 6 )]
    [InlineData( 4, 24 )]
    public void Test_Factorial(int input, int expected)
    {
        int result = Factorial( input );
        Assert.Equal( result, expected);
    }

आप एक परीक्षण-डेटा प्रदान भी लागू कर सकते हैं (जो कि रिटर्न IEnumerable<Tuple<xxx>>) और एक गणितीय इनवेरियंट को सांकेतिक शब्दों में बदलना, जैसे कि एन द्वारा बार-बार विभाजित करना n-1 होगा।

मुझे लगता है कि यह tp परीक्षण का एक बहुत शक्तिशाली तरीका है।


1

यदि आप अभी भी धोखा देने में सक्षम हैं तो परीक्षण पर्याप्त नहीं हैं। अधिक परीक्षण लिखें! आपके उदाहरण के लिए, मैं इनपुट 1, -1, -1000, 0, 10, 200 के साथ परीक्षण जोड़ने का प्रयास करूंगा।

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

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


1
तो ऐसा लगता है कि आप कह रहे हैं कि टेस्ट पास करने के लिए केवल पर्याप्त कोड लिखना (जैसा कि TDD अधिवक्ता) पर्याप्त नहीं है। आपको ध्वनि सॉफ़्टवेयर डिज़ाइन सिद्धांतों को भी ध्यान में रखना होगा। मैं आपसे सहमत हूँ BTW।
रॉबर्ट हार्वे

0

मेरा सुझाव है कि आपकी पसंद का परीक्षण सबसे अच्छा परीक्षण नहीं है।

मैं इसके साथ शुरू होगा:

पहला परीक्षण के रूप में factorial (1),

दूसरे के रूप में भाज्य (को ०)

तीसरे के रूप में भाज्य (-ve)

और फिर गैर-तुच्छ मामलों के साथ जारी रखें

और एक अतिप्रवाह मामले के साथ खत्म।


क्या है -ve??
रॉबर्ट हार्वे

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