जब आप TDD में "वास्तविक" कोड लिखते हैं?


147

प्रशिक्षण वीडियो पर मैंने जितने भी उदाहरण पढ़े और देखे हैं उनके सभी उदाहरण सरल हैं। लेकिन अगर मैं हरे होने के बाद "वास्तविक" कोड कैसे करता हूं, तो मैं क्या नहीं देख सकता हूं। क्या यह "रिफलेक्टर" हिस्सा है?

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

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

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

लेकिन, किसी भी मामले में, टीडी डिज़ाइन मुझे कहानी के माध्यम से सोचने के लिए मजबूर कर रहा है। अगर मैं टेस्ट में फेल हो सकता हूं, तो मुझे पता है कि यह क्यों फेल हो जाता है, लेकिन यह अनुमान है कि मैं इसे पास कर सकता हूं। यह डिजाइनिंग के बारे में है।

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

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

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

या, शायद यह दिखाता है कि मैं अभी भी भ्रमित हूं।


193
टीडीडी के बाद लोग रात को घर जाते हैं।
हॉब्स

14
आपको क्या लगता है कि आपके द्वारा लिखा गया कोड वास्तविक नहीं है?
गोयो जूल

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

1
उत्तर पहले से ही नाखून को सिर पर मारते हैं, लेकिन जब तक आपके सभी परीक्षण गुजर रहे हैं, और आपको किसी भी नए परीक्षण / कार्यक्षमता की आवश्यकता नहीं है, यह माना जा सकता है कि आपके पास कोड समाप्त हो गया है, बार लाइनिंग।
ESR

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

जवाबों:


243

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

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

इससे पहले कि आप रिटेक करने से पहले कितना कोड लिखते हैं? कोई नहीं। आप एक असफल परीक्षण के बिना शून्य कोड लिखते हैं जो आपको अधिक कोड लिखने के लिए मजबूर करता है

पैटर्न पर ध्यान दें?

चलो (एक और) सरल उदाहरण के माध्यम से चलते हैं इस उम्मीद में कि यह मदद करता है।

Assert.Equal("1", FizzBuzz(1));

आसान मोर।

public String FizzBuzz(int n) {
    return 1.ToString();
}

नहीं, जिसे आप वास्तविक कोड कहेंगे, है ना? आइए एक परीक्षण जोड़ें जो परिवर्तन को मजबूर करता है।

Assert.Equal("2", FizzBuzz(2));

हम कुछ मूर्खतापूर्ण की तरह कर सकते हैं if n == 1, लेकिन हम सॉल्यूशन समाधान के लिए छोड़ देंगे।

public String FizzBuzz(int n) {
    return n.ToString();
}

ठंडा। यह सभी गैर-फ़िज़बज़ नंबरों के लिए काम करेगा। अगला इनपुट क्या है जो उत्पादन कोड को बदलने के लिए मजबूर करेगा?

Assert.Equal("Fizz", FizzBuzz(3));

public String FizzBuzz(int n) {
    if (n == 3)
        return "Fizz";
    return n.ToString();
}

और फिर। एक परीक्षण लिखें जो अभी तक पास नहीं होगा।

Assert.Equal("Fizz", FizzBuzz(6));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    return n.ToString();
}

और हमने अब तीन के सभी गुणकों को कवर किया है (जो कि पांच के गुणक भी नहीं हैं, हम इसे नोट करेंगे और वापस आएंगे)।

हमने अभी तक "बज़" के लिए एक परीक्षा नहीं लिखी है, इसलिए हम लिखते हैं कि।

Assert.Equal("Buzz", FizzBuzz(5));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n == 5)
        return "Buzz"
    return n.ToString();
}

और फिर, हम जानते हैं कि एक और मामला है जिसे हमें संभालने की आवश्यकता है।

Assert.Equal("Buzz", FizzBuzz(10));

public String FizzBuzz(int n) {
    if (n % 3 == 0)
        return "Fizz";
    if (n % 5 == 0)
        return "Buzz"
    return n.ToString();
}

और अब हम 5 के सभी गुणकों को संभाल सकते हैं जो कि 3 के गुणक भी नहीं हैं।

इस बिंदु तक, हम रिफैक्टरिंग कदम को नजरअंदाज कर रहे हैं, लेकिन मुझे कुछ दोहराव दिखाई दे रहा है। चलिए अब साफ करते हैं।

private bool isDivisibleBy(int divisor, int input) {
    return (input % divisor == 0);
}

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
}

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

Assert.Equal("FizzBuzz", FizzBuzz(15));

public String FizzBuzz(int n) {
    if (isDivisibleBy(3, n) && isDivisibleBy(5, n))
        return "FizzBuzz";
    if (isDivisibleBy(3, n))
        return "Fizz";
    if (isDivisibleBy(5, n))
        return "Buzz"
    return n.ToString();
}

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

public String FizzBuzz(int n) {

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
}

और हमने हर उचित इनपुट को कवर किया है, लेकिन अनुचित इनपुट के बारे में क्या ? यदि हम 0 या नकारात्मक पास करते हैं तो क्या होगा? उन परीक्षण मामलों को लिखें।

public String FizzBuzz(int n) {

    if (n < 1)
        throw new InvalidArgException("n must be >= 1);

    var isDivisibleBy3 = isDivisibleBy(3, n);
    var isDivisibleBy5 = isDivisibleBy(5, n);

    if ( isDivisibleBy3 && isDivisibleBy5 )
        return "FizzBuzz";
    if ( isDivisibleBy3 )
        return "Fizz";
    if ( isDivisibleBy5 )
        return "Buzz"
    return n.ToString();
}

क्या यह अभी तक "वास्तविक कोड" जैसा दिखाई देने लगा है? इससे भी महत्वपूर्ण बात यह है कि किस बिंदु पर "अवास्तविक कोड" होना और "वास्तविक" होने के लिए संक्रमण होना बंद हो गया? उस पर विचार करने के लिए कुछ है ...

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

  • नकारात्मक
  • शून्य
  • एक
  • दो
  • तीन
  • चार
  • पांच
  • छह (3 के गैर तुच्छ कई)
  • नौ (3 वर्ग)
  • दस (गैर तुच्छ 5 से अधिक)
  • 15 (3 और 5 के कई)
  • 30 (3 और 5 के गैर तुच्छ कई)

3
टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
maple_shaft

47
जब तक मैं इस उत्तर को पूरी तरह से गलत नहीं समझ लेता: "हम मूर्खतापूर्ण कुछ कर सकते हैं जैसे कि n == 1, लेकिन हम समाधान को छोड़ देंगे।" - पूरी बात मूर्खतापूर्ण थी। यदि आपको पता है कि आप एक ऐसा फंक्शन चाहते हैं जो <spec> करता है, तो <कल्पना> के लिए परीक्षण लिखें और उस हिस्से को छोड़ दें जहां आप ऐसे संस्करण लिखते हैं जो स्पष्ट रूप से विफल होते हैं <spec>। यदि आपको <युक्ति> में बग दिखाई देता है, तो सुनिश्चित करें: यह सत्यापित करने के लिए पहले एक परीक्षण लिखें कि आप इसे ठीक करने से पहले अभ्यास कर सकते हैं और तय होने के बाद परीक्षण पास का निरीक्षण कर सकते हैं। लेकिन इन सभी मध्यवर्ती चरणों को नकली करने की कोई आवश्यकता नहीं है।
GManNickG

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

2
@GManNickG मेरा मानना ​​है कि परीक्षण की सही मात्रा प्राप्त करने के लिए बिंदु है। पहले से परीक्षण लिखने से यह याद रखना आसान हो जाता है कि विशेष मामलों का क्या परीक्षण किया जाना चाहिए, जिससे या तो स्थितियों को परीक्षणों में पर्याप्त रूप से कवर नहीं किया जा सकता है, या अनिवार्य रूप से उसी स्थिति को परीक्षणों में समय के भार को कवर किया जा रहा है। यदि आप इन मध्यवर्ती चरणों के बिना कर सकते हैं, महान! हर कोई अभी तक ऐसा नहीं कर सकता है, यह कुछ ऐसा है जो अभ्यास करता है।
hvd

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

46

"वास्तविक" कोड वह कोड है जिसे आप अपना टेस्ट पास बनाने के लिए लिखते हैं। वास्तव में । यह इत्ना आसान है।

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

रिफ्लेक्टर स्टेप का विचार सिर्फ यह है कि जो आपने एक बार खुश हो जाने के बाद लिखा है कि उसे आवश्यकताओं को पूरा करना है।

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


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

8
@DerekElkins TDD ने असफल परीक्षणों को अनिवार्य कर दिया है। इकाई परीक्षण विफल नहीं।
तैमूर

6
@DerekElkins यही कारण है कि आप सिर्फ यूनिट परीक्षण नहीं लिखते हैं, और यह भी कि एक सामान्य धारणा क्यों है कि आप कुछ बनाने की कोशिश कर रहे हैं न कि केवल नकली!
जोंशरशेप

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

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

14

संक्षिप्त उत्तर यह है कि "वास्तविक कोड" वह कोड है जो टेस्ट पास करता है। यदि आप असली कोड के अलावा किसी अन्य चीज़ के साथ अपना टेस्ट पास कर सकते हैं, तो अधिक परीक्षण जोड़ें!

मैं मानता हूं कि TDD के बारे में बहुत सारे ट्यूटोरियल सरल हैं। जो उनके खिलाफ काम करता है। एक विधि के लिए बहुत सरल परीक्षण, जो कहता है, 3 + 8 की गणना वास्तव में कोई विकल्प नहीं है, बल्कि 3 + 8 की गणना करने और परिणाम की तुलना करने के लिए। इससे ऐसा लगता है कि आप सिर्फ कोड को डुप्लिकेट कर रहे होंगे, और यह परीक्षण व्यर्थ है, त्रुटि-रहित अतिरिक्त कार्य।

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

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


6
व्यक्तिगत रूप से, मैं जो परीक्षण लिखूंगा वह assertEqual(plus(3,8), 11)नहीं होगा assertEqual(plus(3,8), my_test_implementation_of_addition(3,8))। अधिक जटिल मामलों के लिए, आप हमेशा परिणाम, सही साबित करने का एक साधन के लिए देखो के अलावा अन्य गतिशील परीक्षण में सही परिणाम की गणना और समानता की जाँच।
स्टीव जेसोप

इसलिए इस उदाहरण के लिए वास्तव में मूर्खतापूर्ण तरीके से, आप यह साबित कर सकते हैं कि plus(3,8)इसमें से 3 घटाकर, 8 से घटाकर, और परिणाम की जांच करके सही परिणाम लौटाया है। यह स्पष्ट assertEqual(plus(3,8), 3+8)रूप से एक के समान है। थोड़ा बेतुका, लेकिन अगर परीक्षण के तहत कोड सिर्फ एक पूर्णांक की तुलना में कुछ अधिक जटिल है, तो परिणाम लेना और शुद्धता के लिए प्रत्येक भाग की जांच करना अक्सर सही दृष्टिकोण होता है। वैकल्पिक रूप से, कुछ इस तरह सेfor (i=0, j=10; i < 10; ++i, ++j) assertEqual(plus(i, 10), j)
स्टीव जेसप

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

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

6

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

लेकिन ऐसा मत सोचो कि असली कोड जादू की तरह दिखाई देता है-यह गलत है। आपको सबसे बेहतर समझ की आवश्यकता है कि आप क्या हासिल करना चाहते हैं और फिर आपको सबसे आसान मामलों और कोने के मामलों से शुरू करके तदनुसार परीक्षा लेने की आवश्यकता है।

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

बॉब मार्टिन इसे पूरी तरह से यहाँ बताते हैं


5

जब आप थक जाते हैं तो रिफैक्टर का हिस्सा साफ हो जाता है और आप घर जाना चाहते हैं।

जब आप एक फीचर जोड़ने वाले हों तो रिफ्लेक्टर वाला हिस्सा वह होता है जिसे आप अगले टेस्ट से पहले बदलते हैं। आप नई सुविधा के लिए जगह बनाने के लिए कोड को रिफलेक्टर करते हैं। आप ऐसा तब करते हैं जब आप जानते हैं कि नई सुविधा क्या होगी। तब नहीं जब आप सिर्फ इसकी कल्पना कर रहे हों।

यह एक श्रेणी बनाने के लिए (परीक्षण जोड़ने के बाद) बनाने GreetImplसे GreetWorldपहले आपको GreetMom"हाय मॉम" प्रिंट करने वाली सुविधा को जोड़ने के लिए सरल हो सकता है ।


1

लेकिन असली कोड TDD चरण के रिफैक्टर चरण में दिखाई देगा। यानी वह कोड जो अंतिम रिलीज का हिस्सा होना चाहिए।

हर बार जब आप बदलाव करते हैं तो टेस्ट चलाया जाना चाहिए।

TDD जीवन चक्र का आदर्श वाक्य होगा: RED GREEN REFACTOR

लाल : परीक्षण लिखें

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

Refactor : कोड को साफ, ठीक से चर नाम। सूखी कोड अप।


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

2
@mcottle: आप आश्चर्यचकित हो सकते हैं कि केवल-प्राप्त भंडार के कितने कार्यान्वयन कोडबेस में हार्डकोड किए गए मान हो सकते हैं। :)
ब्रायन बोएचर

6
मैं कभी भी बकवास कोड क्यों लिखूंगा और इसे साफ कर दूंगा, जब मैं अच्छा, उत्पादन गुणवत्ता कोड लगभग उतना ही तेज़ कर सकता हूं जितना मैं टाइप कर सकता हूं? :)
कज़

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

1
@TimothyTruckle सबसे सरल संभव परिवर्तन को खोजने में 50 मिनट लगते हैं, लेकिन दूसरा सबसे सरल संभव परिवर्तन खोजने के लिए केवल 5? क्या हम दूसरे सरल के साथ जाते हैं या सबसे सरल खोज करते रहते हैं?
कज़

1

जब आप TDD में "वास्तविक" कोड लिखते हैं?

लाल चरण है जहाँ आप लिखना कोड।

में रिफैक्टरिंग चरण प्राथमिक लक्ष्य है हटाना कोड।

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

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

अंत में आप पहचानकर्ताओं का नाम बदलकर पठनीयता में सुधार करते हैं और स्थिरांक के लिए जादुई संख्या और / या शाब्दिक तार निकालते हैं ।


यह लाल-परावर्तक नहीं है, यह लाल-हरा-परावर्तक है। - रोब किन्योन

इस ओर इशारा करने के लिए धन्यवाद।

तो यह हरे रंग का चरण है जहां आप वास्तविक कोड लिखते हैं

में लाल चरण आपके द्वारा लिखी गई निष्पादन विनिर्देश ...


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

1

आप पूरे समय रियल कोड लिख रहे हैं ।

प्रत्येक चरण में आप उन शर्तों को पूरा करने के लिए कोड लिख रहे हैं, जो आपका कोड आपके कोड के भविष्य के कॉल करने वालों के लिए संतुष्ट करेगा (जो आप हो सकते हैं या नहीं ...)।

आपको लगता है कि आप उपयोगी ( वास्तविक ) कोड नहीं लिख रहे हैं , क्योंकि एक पल में आप इसे हटा सकते हैं।

कोड-रीफैक्टरिंग मौजूदा कंप्यूटर कोड के पुनर्गठन की प्रक्रिया है - अपने बाहरी व्यवहार को बदले बिना फैक्टरिंग को बदलना।

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

एक और कारण आप सोच सकते हैं कि यह वास्तविक कोड नहीं है, यह है कि आप ऐसे उदाहरण हैं जहां अंतिम कार्यक्रम पहले से ही आपके द्वारा पूर्वाभास किया जा सकता है। यह बहुत अच्छा है, क्योंकि यह दिखाता है कि आप जिस डोमेन में प्रोग्रामिंग कर रहे हैं, उसके बारे में आपको जानकारी है।
लेकिन कई बार प्रोग्रामर एक ऐसे डोमेन में होते हैं, जो उनके लिए नया , अज्ञात होता है। वे क्या अंतिम परिणाम हो जाएगा पता नहीं है और TDD एक है तकनीक , कदम से कदम programms लिखने के लिए हमारे दस्तावेजीकरण ज्ञान कैसे इस प्रणाली काम करते हैं और चाहिए के बारे में verifing कि हमारे कोड कि जिस तरह से काम करता है।

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

(*) केंट बेक द्वारा "टेस्ट ड्रिवेन डेवलपमेंट: बाय उदाहरण"


2
केंट बेक द्वारा "टेस्ट ड्रिवेन डेवलपमेंट: बाय उदाहरण"
रॉबर्ट एंड्रेजुक जूल

1

आप अपने परीक्षणों को विफल बनाने के लिए कोड नहीं लिख रहे हैं।

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

प्रारंभिक रूप से असफल परीक्षण लिखने के बारे में पूरी बात दो काम करने की है:

  1. सभी मामलों को कवर करें - सभी नाममात्र मामले, सभी किनारे मामले, आदि।
  2. अपने परीक्षणों को मान्य करें। यदि आप केवल उन्हें कभी पास करते हुए देखते हैं, तो आप कैसे सुनिश्चित कर सकते हैं कि जब वे किसी एक घटना में असफलता की रिपोर्ट करेंगे?

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

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


0

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

एक बार जब आप सभी छोटी "इकाइयों" का परीक्षण कर लेते हैं, तो आप उन सभी इकट्ठे, या "एकीकृत" का परीक्षण करते हैं। यह आमतौर पर एक पूरा कार्यक्रम या पुस्तकालय है।

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

वह सब भी ALSO परीक्षण कर रहा है, लेकिन मेरे पास परिणामों के लिए एक सुंदर लाल / हरी डिस्प्ले नहीं है। यह या तो सफल होता है, या मैं यह जानने के लिए कि त्रुटि कोड की कुछ हजार पंक्तियों के माध्यम से खुदाई करता हूं।

यहीं आप "वास्तविक कोड" का परीक्षण करते हैं।

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


(इसके = अधिकारवादी, यह = "यह है" या "इसके पास" है। उदाहरण के लिए देखें कि इसका उपयोग कैसे करें और इसका उपयोग करें ।)
पीटर मोर्टेंसन

-6

प्रश्न के शीर्षक के उत्तर में: "आप TDD में" वास्तविक "कोड कब लिखते हैं?", उत्तर है: 'शायद ही कभी' या 'बहुत धीरे-धीरे'।

आप एक छात्र की तरह लग रहे हैं, इसलिए मैं जवाब दूंगा जैसे कि एक छात्र को सलाह देना।

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

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

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

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

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

कृपया इस जाल में न पड़ें और कोडिंग की अपनी भूमिका देखें कि यह क्या है - कोडर का काम केवल कोड तैयार करना है। कोड जो वास्तव में अच्छी तरह से काम करता है। अब, याद रखें कि आप एक पेशेवर कोडर के रूप में घड़ी पर रहेंगे, और यदि आपने 100,000 दावे लिखे हैं, या आपका क्लाइंट परवाह नहीं करेगा, या वे केवल कोड चाहते हैं जो काम करता है। वास्तव में अच्छी तरह से, वास्तव में।


3
मैं एक छात्र के करीब भी नहीं हूं, लेकिन मैं पढ़ता हूं और अच्छी तकनीकों को लागू करने और पेशेवर होने की कोशिश करता हूं। तो उस अर्थ में, मैं एक "छात्र" हूं। मैं बस बहुत ही बुनियादी सवाल पूछता हूं क्योंकि मैं यही हूं। मुझे यह जानना पसंद है कि मैं जो कर रहा हूं, वह क्यों कर रहा हूं। इस मामले का दिल। अगर मुझे वह नहीं मिलता है, तो मुझे यह पसंद नहीं है और सवाल पूछने लगते हैं। मुझे यह जानने की आवश्यकता है कि, यदि मैं इसका उपयोग करने जा रहा हूं। TDD कुछ मायनों में सहज रूप से अच्छा लगता है जैसे यह जानना कि आपको किन चीजों को बनाने और सोचने की ज़रूरत है, लेकिन कार्यान्वयन को समझना मुश्किल था। मुझे लगता है कि मेरे पास अब बेहतर समझ है।
जॉनी


4
वे TDD के नियम हैं। आप चाहे तो कोड लिखने के लिए स्वतंत्र हैं, लेकिन यदि आप उन तीन नियमों का पालन नहीं करते हैं जो आप टीडीडी नहीं कर रहे हैं।
सीन बर्टन

2
एक व्यक्ति का "नियम"? TDD आपको धर्म नहीं बल्कि कोड की मदद करने का सुझाव है। यह बहुत दुख की बात है कि इतने सारे लोग एक विचार का पालन करते हैं। यहां तक ​​कि टीडीडी की उत्पत्ति विवादास्पद है।
user3791372

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