2012-02-15 16 views
5

प्रौद्योगिकी ढेर: .NET 4, C#, NUnitटीडीडी: क्या यह एकीकरण परीक्षण करने के लिए व्यवहार्य है, लेकिन कोई यूनिट परीक्षण नहीं है?

मैं छवि प्रसंस्करण करने वाली एक नई परियोजना में परीक्षण संचालित विकास को लागू करने का प्रयास कर रहा हूं। मेरे पास एक बेस क्लास है जिसमें साझा फ़ाइल I/O विधियां और उप-वर्ग शामिल हैं जो विभिन्न विशिष्ट प्रोसेसिंग एल्गोरिदम निष्पादित करते हैं। जैसा कि मैं इसे समझता हूं, यूनिट परीक्षण फाइल सिस्टम या अन्य ऑब्जेक्ट्स को स्पर्श नहीं करते हैं, और नकली व्यवहार जहां होता है। मेरी बेस क्लास में केवल सरल एक्सेसर्स और सीधा फ़ाइल सिस्टम I/O कॉल शामिल हैं।

public class BaseFile 
{ 
    public String Path { get; set; } 

    public BaseFile() 
    { 
     Path = String.Empty; 
    } 

    public BaseFile(String path) 
    { 
     if (!File.Exists(path)) 
     { 
      throw new FileNotFoundException("File not found.", path); 
     } 

     Path = path; 
    } 
} 

क्या इन तरीकों का परीक्षण करने में कोई मूल्य है? यदि हां, तो मैं फाइल सिस्टम में कॉल को कैसे दूर कर सकता हूं?

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

+4

यदि टीडीडी लागू करना मुश्किल है, या अपर्याप्त है, तो इसे लागू न करें। यह चांदी की गोली नहीं है। – CharlesB

+1

@ चार्ल्स बी, मैं सहमत हूं। दुर्भाग्य से यह भावना अक्सर टीडीडी का उपयोग न करने के लिए बहाना के रूप में प्रयोग की जाती है जब यह वास्तव में सही और फायदेमंद होता है। कभी-कभी बड़ा वक्र होता है या करने के लिए बहुत सारी आधार होती है लेकिन यह आमतौर पर भुगतान करती है। –

+1

@CharlesB यकीन नहीं है कि मैं इसके साथ सहमत हूं। समस्या यह है कि तब यह वर्ग जो कुछ काम करता है उसका परीक्षण नहीं किया जाता है, और इस प्रकार इसे बदलने का आपका विश्वास कम हो जाता है। समस्या यह है कि System.IO में स्थैतिक तरीकों का नकल करना आसान नहीं है, लेकिन इसका मतलब यह नहीं है कि परीक्षण पर छोड़ दें, इसका मतलब है कि आपको उन्हें टेस्ट करने योग्य बनाने के लिए थोड़ा और काम करने की आवश्यकता है। यही कारण है कि एमएस सिस्टम.Web.HttpContextBase पेश करता है, जो उन समस्याओं को हल करने के लिए आसानी से HttpContext को नकल करने में सक्षम नहीं है। हमें httpContext का परीक्षण करने की आवश्यकता नहीं है, बस हमारे कोड सही ढंग से इसके साथ इंटरैक्ट करते हैं। – Andy

उत्तर

4

आपके पहले प्रश्न के उत्तर में, हाँ इन तरीकों का परीक्षण करने में मूल्य है। मैंने एक पुस्तकालय प्रकाशित किया है जो वास्तव में फाइल सिस्टम को मारने के बिना यह सुनिश्चित करता है कि https://bitbucket.org/mylesmcdonnell/mpm.io/wiki/Home

आपके दूसरे प्रश्न का उत्तर (नहीं) में मुझे कुछ कोड देखने की आवश्यकता होगी, लेकिन मुझे संदेह है कि आपको ऐसा ही करने की आवश्यकता हो सकती है उपरोक्त lib के लिए दृष्टिकोण। अर्थात्; इंटरफ़ेस को परिभाषित करें, कंक्रीट को प्रॉक्सी परिभाषित करें, प्रॉक्सी या नकली वापस करने के लिए कारखाने को परिभाषित करें।

+0

इस स्रोत कोड को पोस्ट करने के लिए धन्यवाद। मैं आपकी पोस्ट को उत्तर के रूप में चिह्नित कर रहा हूं क्योंकि आपने सर्वोत्तम सामान्य समाधान प्रदान किया है। – Noren

3

मैं टीडीडी विधियों का सख्ती से पालन कैसे कर सकता हूं और पहले इस मामले में असफल परीक्षण लिख सकता हूं?

आसान! आप फ़ाइल सिस्टम का नकल करते हैं :)

यह बहुत सारे काम की तरह लग सकता है, लेकिन आम तौर पर आपको केवल कुछ तरीकों को लागू करने की आवश्यकता होती है, और आवश्यकतानुसार विस्तार करना पड़ता है। उपरोक्त मामले में ... आपको केवल एक की आवश्यकता है।

public interface IFileStore 
{ 
    Boolean FileExists(String path); 
} 

विचार यह है कि इंटरफ़ेस के पीछे अपनी फ़ाइल का काम सौंपना और भारी उठाने के लिए ठोस कार्यान्वयन करना है। असल में Adapter pattern

मैं इस तरह की चीज के लिए "गरीब आदमी की डी" पर भी ऑब्जेक्ट नहीं करता क्योंकि आप इसके बाद किसी कंटेनर को लागू कर सकते हैं यदि आपका एप्लिकेशन इसके लिए कॉल करता है। इस मामले में ... आप शायद असली फाइल सिस्टम का उपयोग करने जा रहे हैं।

public class BaseFile 
{ 
    private IFileStore _fileStore 
    public IFileStore FileStore 
    { 
     get 
     { 
      return _fileStore ?? (_fileStore = new ConcreteFileStore()); 
     } 
     set 
     { 
      _fileStore = value; 
     } 
    } 

    //SNIP... 
} 

अब आपके पास एक परीक्षण योग्य कार्यान्वयन है, और आपको किसी भी "गोल्डन" फ़ाइलों पर भरोसा नहीं करना पड़ेगा।

+0

आपकी पोस्ट के लिए धन्यवाद। अभी के लिए, मैं आपके समाधान को लागू करने जा रहा हूं जब तक कि मुझे सिस्टम.आईओ कॉल की अधिक आवश्यकता न हो, जिस बिंदु पर मैं माइल्स के कोड का उपयोग करूंगा। – Noren

0

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

केवल एकीकरण परीक्षण कुछ चीजों को निश्चित रूप से बता सकता है। (एकीकरण परीक्षणों के नुकसान भी हैं!)।

+0

सही। मैं यह नहीं कह रहा हूं कि आपको * एकीकरण परीक्षण नहीं करना चाहिए। इसके बजाय, टीडीडी अभी भी उन चीजों पर भी किया जा सकता है जिन्हें हम आमतौर पर फाइल सिस्टम की तरह नहीं मानते हैं। – Josh

+0

मेरा मतलब यह नहीं था कि आप अपनी व्याख्या को विचलित करें। मैंने इसका संदर्भ दिया क्योंकि यह अच्छा था। – usr

1

वहाँ इन तरीकों

परीक्षण यह तुच्छ लाभ के लिए अतिरिक्त काम की तरह अभी लगता है, BaseFile तरह परीक्षण जोड़ने FileNotFoundException फेंक जब फ़ाइल मौजूद नहीं है सिद्ध कम से कम दो गोल चाहिए में मूल्य है :

उम्मीद व्यवहार की एक सूची निर्धारित परियोजना के लिए

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

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

स्वचालित प्रतिगमन परीक्षण का एक सूट के लिए आगे बढ़ें

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

आपके प्रश्न के दूसरे भाग के लिए, मुझे लगता है कि जोश और माइल्स दोनों ने पहले से ही अच्छी सलाह प्रदान की है।

+0

आपने अच्छे अंक बनाए हैं। मेरा मानना ​​है कि मैं इन सरल तरीकों के परीक्षणों में छोड़ दूंगा। – Noren

1

इंटरफ़ेस का उपयोग करके सरल फ़ाइल सिस्टम कॉल मॉकिंग एक ओवरकिल की तरह लगता है। ITimeService का उपयोग कर वर्तमान समय पर नकल करने जैसी चीजों के लिए भी यही है।

public static Func<string, bool> FileExists = System.IO.File.Exists; 
public static Func<DateTime> GetCurrentTime =() => DateTime.Now; 

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

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