2012-09-24 18 views
5

निम्नलिखित टेम्पलेट विधि कार्यान्वयन मान लीजिए।
हालांकि, लगता है मैं अपने Conc वर्ग परीक्षण करना चाहते हैं:इकाई परीक्षण टेम्पलेट विधि डिजाइन पैटर्न

public class Conc : Abs 
    { 
    protected override void DoYourThingInternal() 
    { 
     // Lots of awesome stuff here! 
    } 
    } 

मैं conc.DoYourThing() करने के लिए है, क्योंकि यह माता पिता विधि है, जो पहले से ही अलग से परीक्षण किया गया था लागू करेगा नहीं करना चाहेंगे।

मैं केवल ओवरराइडिंग विधि का परीक्षण करना चाहता हूं।

कोई विचार?

उत्तर

2

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

हालांकि, इसका मतलब यह नहीं है कि आपके पास DoYourThing() के अपेक्षित व्यवहार के लिए अलग-अलग परीक्षण नहीं हो सकते हैं, जो एबीएस के सभी कार्यान्वयन और DoYourThingInternal() के अपेक्षित व्यवहार में समान रहना है।

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

आधार परीक्षण वर्ग से परीक्षण विरासत में मिला दिया जाएगा, और जब आप किसी भी उपवर्ग के परीक्षण चलाने, DoYourThing() के लिए विरासत में मिला परीक्षण भी चलेंगे:

public abstract class AbsBaseTest 
{ 
    public abstract Abs GetAbs(); 

    [Test] 
    public void TestSharedBehavior() 
    { 
    getAbs().DoYourThing(); 

    // Test shared behavior here... 
    } 
} 

[TestFixture] 
public class AbsImplTest : AbsBaseTest 
{ 
    public override Abs GetAbs() 
    { 
    return new AbsImpl(); 
    } 

    [Test] 
    public void TestParticularBehavior() 
    { 
    getAbs().DoYourThing(); 

    // Test specific behavior here 
    } 
} 

देखें http://hotgazpacho.org/2010/09/testing-pattern-factory-method-on-base-test-class/

अगर पता नहीं है अमूर्त टेस्ट क्लास विरासत सभी यूनिट परीक्षण ढांचे द्वारा समर्थित है हालांकि (मुझे लगता है कि न्यूटिट करता है)।

0

एबीएस पर एक इंटरफ़ेस चिपकाने और इसे मजाक करने के बारे में क्या? कॉल को अनदेखा करना, या उन पर अपेक्षाएं निर्धारित करना?

+0

सुनिश्चित नहीं है कि मैं समझता हूं; क्या आप विस्तारित कर सकते हैं? –

3

मुझे लगता है कि 'समस्या' का हिस्सा यह है कि वर्ग के बाहर से संरक्षित विधि को कॉल करने का कोई तरीका नहीं है। कैसे एक नकली वर्ग जो Conc से निकला है और नए सार्वजनिक तरीका प्रदान करता है के बारे में:

public class MockConc: Conc 
    { 
    void MockYourThingInternal() 
    { 
     DoYourThingInternal() 
    } 
    } 
2

आप सवाल "TDD" करार दिया है लेकिन मुझे शक है आप का पालन किया है कि सिद्धांत है जब आप इस "समस्या" का सामना करना पड़ा।

आप वास्तव में अपने काम के प्रवाह TDD का अनुसरण किया है हो गया होता की तरह

  1. कुछ कुछ तर्क अभी तक लागू नहीं
  2. Impl सबसे आसान संभव impl इस परीक्षण को हरा करने के लिए (पर तर्क के लिए एक परीक्षण लिखें उदाहरण के लिए Conc1)
  3. Refactor
  4. ई के लिए Conc2 पर कुछ अन्य तर्क अभी तक लागू नहीं
  5. impl सबसे आसान संभव impl के लिए एक परीक्षण लिखें इस परीक्षण को हरा करने के लिए (तर्क XAMPLE)
  6. Refactor

"6" में आप सोच सकते हैं कि यह एक बहुत अच्छा विचार एक टेम्पलेट विधि लागू करने के लिए, क्योंकि Conc1 और Conc2 कुछ तर्क का हिस्सा होगा। बस इसे करें, और यह देखने के लिए अपने परीक्षण चलाएं कि तर्क अभी भी काम करता है।

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

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

+1

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

+3

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

+1

बहुत अच्छा बिंदु। स्वीकार्य रूप से, मुझे 'टीडीडी' मानसिकता के साथ सोचना मुश्किल लगता है ... –

0

आप इसे कई तरीकों से कर सकते हैं, जिनमें से कई पहले से ही दस्तावेज किए गए हैं। यहां वह दृष्टिकोण है जो मैं आम तौर पर लेता हूं: टेस्ट केस कंक्रीट क्लास से प्राप्त होता है।

public ConcTest : Conc 
{ 
    [Test] 
    public void DoesItsThingRight() 
    { 
     var Result = DoItsThingInternal(); 
     // Assert the response 
    } 
} 

आशा है कि मदद करता है!

ब्रैंडन