2010-06-30 15 views
6

मेरे पास टीडीडी के साथ विकसित एक गैर-सेवा सेवा वस्तु है। यह एक साधारण कार्य के साथ शुरू हुआ: कतार से किसी ऑब्जेक्ट के लिए, एसिंक्रोनस प्रोसेसिंग के लिए प्रयास करें। तो मैं अपने constructAttempt() विधि के चारों ओर एक परीक्षण लिखा है:टीडीडी - ब्लैक-बॉक्स में रिफैक्टरिंग?

void constructAttempt() {...} 

कई संभव परिदृश्यों ध्यान में रखा जाना करने की जरूरत है कि कर रहे हैं, इसलिए मैं इस विधि के लिए एक दर्जन से अधिक परीक्षण किया है।


तब मैंने इसे लागू करने के लिए वास्तव में आवश्यकतानुसार लागू किया: पूरी कतार स्कैन करें और प्रयासों का एक बैच बनाएं।

public void go() { 
    for (QueuedItem item : getQueuedItems()) { 
     constructAttempt(item); 
    } 
} 

तो मैं इस go() विधि के लिए एक नया परीक्षण या दो कहा: तो कोड अधिक की तरह दिखता है।


अंततः मुझे पता चला कि मुझे कुछ प्रीप्रोकैसिंग की आवश्यकता है जो कभी-कभी constructAttempt() को प्रभावित कर सकता है। अब कोड लग रहा है और अधिक की तरह:

public void go() { 
    preprocess(); 
    for (QueuedItem item : getQueuedItems()) { 
     constructAttempt(item); 
    } 
} 

मैं अब मुझे क्या करना चाहिए के बारे में कुछ संदेह हो।

क्या मैं constructAttempt(), preprocess() और go() के साथ कोड को स्वतंत्र रूप से परीक्षण कर सकता हूं? हाँ क्यों/क्यों नहीं? मुझे preprocessing और ब्रेक encapsulation के साइड इफेक्ट्स को कवर नहीं करने का जोखिम है।

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

+0

यदि आप अपने परीक्षण सूट को केवल go() विधि का परीक्षण करने के लिए दोबारा प्रतिक्रिया देते हैं ... यदि आप पाए गए बग प्रीप्रोसेस() या निर्माण पर हैं तो आप कैसे पहचानेंगे ?? –

उत्तर

6

go विधि वास्तव में कई इंटरैक्शन को व्यवस्थित कर रही है, और अपने आप में बहुत दिलचस्प नहीं है। यदि आप अपने अधीनस्थ तरीकों के बजाय go के खिलाफ अपने परीक्षण लिखते हैं, तो परीक्षण संभवतः जटिल रूप से जटिल हो सकते हैं क्योंकि आपको preprocess और constructAttempt (और यहां तक ​​कि getQueuedItems) के बीच इंटरैक्शन के संयोजन के विस्फोट के लिए खाते हैं, हालांकि यह अपेक्षाकृत सरल लगता है)।

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

1

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

मुझे आशा है कि आप प्रीप्रोकैसिंग/कतार सामग्री के लिए उपयोग की जाने वाली कक्षाओं के लिए निर्भरता उलटापन का उपयोग कर रहे हैं- इस तरह आप स्वतंत्र रूप से प्रीप्रोकैसिंग का परीक्षण कर सकते हैं और फिर इसे अपने जाने() परीक्षण में नकल कर सकते हैं।

3

@ जेफ के पास यह सही है। इस वस्तु में आपके पास वास्तव में क्या दो जिम्मेदारियां हैं। आप कतारबद्ध वस्तुओं को अपनी कक्षा में खींच सकते हैं।व्यक्तिगत वस्तुओं में preprocess और constructAttempt दबाएं। आईएमएचओ जब आपके पास एक वर्ग है जो व्यक्तिगत वस्तुओं से संबंधित है और वस्तुओं की एक सूची है तो आपके पास कोड गंध है। जिम्मेदारियां आइटम पर सूची कंटेनर कार्य करती हैं।

public void go() { 
    for (QueuedItem item : getQueuedItems()) { 
     item.preprocess(); 
     item.constructAttempt(); 
    } 
} 

नोट: यह एक कमांड वस्तु पैटर्न

[संपादित करें 1a] यह यह वास्तव में आसान मजाक के साथ परीक्षण करने के लिए बनाता है के साथ काम करने के समान है। go विधि केवल एक कतार आइटम या कोई कतार आइटम के साथ परीक्षण करने की आवश्यकता है। इसके अलावा प्रत्येक item अब उनके व्यक्ति go के संयोजन विस्फोट से अलग परीक्षण कर सकते हैं।

[संपादित करें 1b] तुम भी आइटम में preprocess गुना करने में सक्षम हो सकता है:

public void go() { 
    for (QueuedItem asyncCommunication: getQueuedItems()) { 
     asyncCommunication.attempt(); 
    } 
} 

अब आप एक सच्चे command pattern है।

संबंधित मुद्दे