2012-03-11 13 views
8

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

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

classUnderTest.AssertWasCalled(cut => cut.SomeMethod(someArgs)) 

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

public DataSet ExportExcelDocToDataSet(bool headerRowProvided) 
    { 
     DataSet ds = new DataSet(); 

     for (int i = 0; i < currentWorkbook.NumberOfSheets; i++) 
     {    
      ISheet tmpSheet = currentWorkbook.GetSheetAt(i); 

      if (tmpSheet.PhysicalNumberOfRows == 0) { continue; } 
      DataTable dt = GetDataTableFromExcelSheet(headerRowProvided, ds, tmpSheet); 

      if (dt.Rows.Count > 0) 
      { 
       AddNonEmptyTableToDataSet(ds, dt); 
      } 
     } 

     return ds; 
    } 

    public DataTable GetDataTableFromExcelSheet(bool headerRowProvided, DataSet ds, ISheet tmpSheet) 
    { 
     DataTable dt = new DataTable(); 
     for (int sheetRowIndex = 0; sheetRowIndex <= tmpSheet.LastRowNum; sheetRowIndex++) 
     { 
      DataRow dataRow = GetDataRowFromExcelRow(dt, tmpSheet, headerRowProvided, sheetRowIndex); 
      if (dataRow != null && dataRow.ItemArray.Count<object>(obj => obj != DBNull.Value) > 0) 
      { 
       dt.Rows.Add(dataRow); 
      } 
     } 

     return dt; 
    } 

... 

आप देख सकते हैं:

यहाँ कुछ उदाहरण कोड मैं मदद करने के लिए मेरी बात को वर्णन के साथ काम कर रहा है (मैं NPOI का उपयोग कर Excel फ़ाइलों के आयात/निर्यात प्रबंधन करने के लिए एक वर्ग लिखा है) ExportExcelDocToDataSet (मेरी "उच्च-स्तरीय" इस मामले में विधि) GetDataTableFromExcelSheet जो GetDataRowFromExcelRow, जो अन्य तरीकों कि यह वही वर्ग के भीतर परिभाषित कर रहे हैं के एक जोड़े कॉल कॉल कहते हैं।

तो इस कोड को पुन: सक्रिय करने के लिए अनुशंसित रणनीति क्या है, इसे सबमिशन द्वारा बुलाए गए मूल्यों को बिना स्टब किए बिना अधिक यूनिट टेस्टेबल बनाने के लिए? परीक्षण के तहत कक्षा के भीतर नकली विधि कॉल करने का कोई तरीका है?

किसी भी मदद या सलाह के लिए अग्रिम धन्यवाद!

उत्तर

6

विषय under test (SUT) संशोधित करें। अगर इकाई परीक्षण के लिए कुछ मुश्किल है, तो डिजाइन अजीब हो सकता है।

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

निर्दिष्ट परीक्षणों से बचने के लिए, सार्वजनिक तरीकों पर ध्यान केंद्रित करें। यदि यह विधि कक्षा के भीतर अन्य विधियों को कॉल करती है, तो इन कॉल का परीक्षण न करें। दूसरी ओर: अन्य dependend on component (DOCs) पर विधि कॉल का परीक्षण किया जाना चाहिए।

आपको लगता है कि करने के लिए छड़ी और लग रहा है कि आप अपने परीक्षण में कुछ महत्वपूर्ण बात याद आती है, तो यह एक वर्ग या एक तरीका है जिसके बहुत ज्यादा कर रहा है के लिए एक संकेत हो सकता है। कक्षा के मामले में: Single Responsibility Principle (SRP) के उल्लंघन की तलाश करें। कक्षाओं को निकालें और उन्हें अलग से जांचें। किसी विधि के मामले में: इसे विधि को कई सार्वजनिक तरीकों से विभाजित करें और उनमें से प्रत्येक को अलग से जांचें। यदि यह अभी भी बहुत अजीब है, तो आपके पास निश्चित रूप से एक कक्षा है जो एसआरपी का उल्लंघन करती है।

अपने विशिष्ट मामले में आप निम्न कर सकते हैं: तरीकों (शायद उन्हें ExcelToDataSetExporter और ExcelSheetToDataTableExporter कहते हैं) दो अलग अलग वर्गों में ExportExcelDocToDataSet और GetDataTableFromExcelSheet निकालें। मूल वर्ग जिसमें दोनों विधियों को शामिल किया गया है, दोनों वर्गों को संदर्भित करना चाहिए और उन विधियों को कॉल करना चाहिए, जिन्हें आपने पहले निकाला था। अब आप अलगाव में सभी तीन वर्गों का परीक्षण करने में सक्षम हैं। Extract Class refactoring (book) अपने मूल वर्ग के संशोधन को प्राप्त करने के लिए लागू करें।

भी ध्यान रखें कि retrofitting परीक्षण हमेशा एक सा बोझिल लिख सकते हैं और बनाए रखने के लिए कर रहे हैं। इसका कारण यह है कि एसयूटी, जो यूनिट परीक्षणों के बिना लिखे गए हैं, में एक अजीब डिज़ाइन होता है और इस प्रकार परीक्षण करना कठिन होता है। इसका मतलब है कि यूनिट परीक्षणों की समस्याओं को एसयूटी को संशोधित करके हल किया जाना चाहिए और यूनिट परीक्षणों को पंप करके हल नहीं किया जा सकता है।

+0

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

+1

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

1

मैं तुम्हें सार्वजनिक विधि GetDataTableFromExcelSheet परीक्षण कर रहे हैं अलग, इसलिए ExportExcelDocToDataSet के परीक्षण के लिए आप (तथ्य यह है कि के रूप में उम्मीद ExportExcelDocToDataSet काम करता है परे) GetDataTableFromExcelSheet के व्यवहार को सत्यापित करने की जरूरत नहीं है लगता है।

एक आम रणनीति केवल सार्वजनिक तरीकों का परीक्षण करना है, क्योंकि सार्वजनिक विधियों की अपेक्षा की जाने वाली निजी विधियों को डिफ़ॉल्ट रूप से परीक्षण किया जाता है यदि सार्वजनिक विधियों की अपेक्षा की जाती है।

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

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

यदि आप किसी परीक्षण से नकली विधियां चाहते हैं तो आप अपने कोड को नकली करने के तरीके के लिए इंटरफ़ेस लेने के लिए पुनः प्रतिक्रिया दे सकते हैं। command pattern देखें।

इस मामले में हालांकि स्पष्ट परिवर्तन ExportExcelDocToDataSet के लिए एक कार्यपुस्तिका को तर्क के रूप में लेने के लिए होगा। परीक्षण में आप एक नकली कार्यपुस्तिका भेज सकते हैं। inversion of control देखें।

+0

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

2

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

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

  • अपने परीक्षण किया वर्ग का नाम क्या है:

    अब, आप कुछ संकेत देने के लिए? ExcelExporterAndToDataSetConverter ... या ExcelManager की तर्ज पर कुछ तरीकों से उभर रहा है? ऐसा लगता है कि यह वर्ग too many things at once कर रहा है; यह थोड़ा रिफैक्टरिंग के लिए पूछता है। डेटासेट में डेटा निर्यात करना एक्सेल डेटा को डेटासेट/डेटारो में परिवर्तित करने से आसानी से अलग किया जा सकता है।

  • क्या होता है जब GetDataTableFromExcelSheet विधि बदलती है? अन्य वर्ग में स्थानांतरित हो जाता है या इसे तृतीय पक्ष कोड द्वारा प्रतिस्थापित किया जाता है? क्या यह आपके निर्यात परीक्षण तोड़ना चाहिए? यह नहीं होना चाहिए - यह कारण है कि आपके निर्यात परीक्षणों को यह सत्यापित नहीं करना चाहिए कि इसे बुलाया गया था या नहीं।

मैं क्लास को अलग करने के लिए डेटासेट/डेटारो रूपांतरण विधियों पर जाने का सुझाव देता हूं - यह यूनिट परीक्षणों के लेखन को आसान बनाएगा और आपके निर्यात परीक्षण नाजुक नहीं होंगे।

+0

क्लास के नाम पर अनुमान अच्छा है: यह "ExcelHelper" कहा जाता है और विचार है यह एक विलक्षण वर्ग अपने आवेदन में कुछ भी संबंधित एक्सेल के साथ सौदा करने के बाकी के द्वारा कहा जाता है होने के लिए। मुझे शायद कम से कम एक एक्सेलइम्पॉर्टर और एक्सेल एक्सपोर्टर क्लास बनाना चाहिए, और इन टिप्पणियों को पढ़ने के बाद मेरे पास कोड को आगे बढ़ाने के लिए कुछ विचार हैं। मैंने हमेशा विशिष्ट उद्देश्यों के साथ अधिक कक्षाएं लिखने के बजाय काम को संभालने के लिए एक ही कक्षा में छोटी, निजी विधियों में विभाजित कोड के संदर्भ में दोबारा विचार करने का विचार किया था। –

+1

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

0

एक बात निश्चित आप TDD सही तरीके से :) कर रहे हैं अच्छी तरह से कोड में ऊपर आप ExportExcelDocToDataSet विधि परीक्षण से पहले विधि GetDataTableFromExcelSheet नकली करना होगा के लिए है।

लेकिन एक चीज जो आप कर सकते हैं वह है अपने डेटा में जगह से GetDataTableFromExcelSheet से लौटाए गए डेटाटेबल को पास करें जहां आपने एक और पैरामीटर जोड़कर ExportExcelDocToDataSet विधि कहा है।

कुछ इस

DataTable dtExcelData = GetData की तरह ....; और नीचे

सार्वजनिक डेटासेट ExportExcelDocToDataSet (bool headerRowProvided, DataTable dtExcelData)

इस तरह आप ExportExcelDocToDataSet विधि के अंदर GetDataTableFromExcelSheet उपहास करने के लिए जब ExportExcelDocToDataSet विधि का परीक्षण की जरूरत नहीं होगी के रूप में विधि को संशोधित।

+0

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

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

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