2012-02-20 13 views
7

मैं सी # में संग्रह कक्षाओं की एक श्रृंखला लिख ​​रहा हूं, जिनमें से प्रत्येक समान कस्टम इंटरफेस लागू करता है। क्या इंटरफ़ेस के लिए यूनिट परीक्षणों का एक संग्रह लिखना संभव है, और स्वचालित रूप से उन्हें कई अलग-अलग कार्यान्वयन पर चलाएं? मैं प्रत्येक कार्यान्वयन के लिए किसी भी डुप्लीकेट परीक्षण कोड से बचना चाहता हूं।क्या मैं इंटरफ़ेस के कार्यान्वयन का परीक्षण करने के लिए पुन: प्रयोज्य परीक्षणों की श्रृंखला लागू कर सकता हूं?

मैं इसे पूरा करने के लिए किसी भी ढांचे (एनयूनीट, आदि) या विजुअल स्टूडियो एक्सटेंशन को देखने के लिए तैयार हूं।


भी ऐसा ही करने के लिए देख रहे लोगों के लिए, मैं avandeursen's accepted solution के बंद मेरी ठोस समाधान, आधारित पोस्ट, an answer के रूप में।

+1

टैग के रूप में [lsp] (http://stackoverflow.com/questions/tagged/lsp) जोड़ा गया, क्योंकि प्रश्न और उत्तर एलएसपी का पालन करने वाले किसी भी श्रेणी पदानुक्रम पर लागू होता है। – avandeursen

उत्तर

6

हां, यह संभव है। यह चाल है कि आपके यूनिट क्लास टेस्ट पदानुक्रम को आपके कोड के वर्ग पदानुक्रम का पालन करें।

मान लीजिए कि आपके पास कक्षा C1 और C2 लागू करने के साथ इंटरफ़ेस Itf है।

आप पहले Itf (ItfTest) के लिए एक टेस्ट क्लास बनाते हैं। वास्तव में परीक्षण का प्रयोग करने के लिए, आपको अपने Itf इंटरफ़ेस का नकली कार्यान्वयन बनाना होगा।

इस ItfTest में सभी परीक्षण Itf (!) के किसी भी कार्यान्वयन पर गुजरना चाहिए। यदि नहीं, तो अपने कार्यान्वयन C1 के लिए एक परीक्षण का मामला बनाने के लिए Liskov Substitution Principle ("L" मार्टिन OO डिजाइन के SOLID सिद्धांतों में)

इस प्रकार के अनुरूप नहीं है, अपने C1Test वर्ग ItfTest विस्तार कर सकते हैं। आपके एक्सटेंशन को C1 ऑब्जेक्ट (इसे इंजेक्शन करने, या GoF factory method का उपयोग करके) के निर्माण के साथ नकली ऑब्जेक्ट सृजन को प्रतिस्थापित करना चाहिए। इस तरह, सभी ItfTest मामले C1 के उदाहरणों पर लागू होते हैं। इसके अलावा, आपके C1Test कक्षा में C1 के लिए विशिष्ट परीक्षण केस हो सकते हैं।

इसी तरह C2 के लिए। और आप गहरे घोंसले वाले वर्गों और इंटरफेस के लिए चाल दोहरा सकते हैं।

संदर्भ: बाइंडर Polymorphic Server Test पैटर्न, और मैकग्रेगर का PACT - घटक परीक्षण के लिए समांतर वास्तुकला।

+1

नकली कार्यान्वयन से बचने के लिए, मैंने बस अपनी 'इटफटेस्ट' कक्षा को सार के रूप में घोषित किया और 'संरक्षित सार इटफ CreateInstance();' फ़ंक्शन स्टब घोषित किया। (ध्यान दें कि 'ItfTest' और' C1Test 'दोनों में '[TestClass]' विशेषता होना आवश्यक है।) – dlras2

+1

हां, मैंने इसके लिए फैक्ट्री विधि का भी उपयोग किया क्योंकि यह आसान है। मैंने जुनीट में इस परीक्षण दृष्टिकोण का उपयोग किया, जहां कोई '[टेस्ट क्लास]' विशेषता नहीं है, लेकिन जहां सुपरक्लास में 'टेस्ट' एनोटेशन विरासत में हैं, जिसके कारण सुपरक्लास परीक्षण मामलों को उप-वर्गों में फिर से चलाने के लिए किया जाता है। और: संपादन के लिए धन्यवाद। – avandeursen

2

ऐसा करने के लिए आप MBUnit में [रोटेस्ट] विशेषताओं का उपयोग कर सकते हैं। शो जहां विधि एक स्ट्रिंग से संकेत मिलता है जो इंटरफेस कार्यान्वयन वर्ग आप का दृष्टांत, और फिर चाहते हैं पारित नीचे दिए गए उदाहरण प्रतिबिंब के माध्यम से इस वर्ग बनाता है:

[RowTest] 
[Row("Class1")] 
[Row("Class2")] 
[Row("Class3")] 
public void TestMethod(string type) 
{ 
    IMyInterface foo = Activator.CreateInstance(Type.GetType(type)) as IMyInterface; 

    //Do tests on foo: 
} 

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

+0

क्या आप यह समझाने के लिए अपना जवाब संपादित कर सकते हैं कि मैं इस तरह कार्यान्वयन का परीक्षण कैसे करूं? आप कह रहे हैं कि प्रत्येक इकाई परीक्षण को सभी कार्यान्वयन के लिए एक स्विच स्टेटमेंट की आवश्यकता होती है, जो मैं नहीं चाहता हूं। – dlras2

+0

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

+0

मैं शायद इसे सिर्फ नाम के बजाय 'IMyInterface' के उदाहरण लेने के लिए लिखूंगा, लेकिन फिर भी +1। विचार के लिए – dlras2

2

Joe's उत्तर पर विस्तारित, आप एमबीयूनीट के रोटेस्ट के समान तरीके से न्यूटिट में [टेस्टकेससोर्स] विशेषता का उपयोग कर सकते हैं। आप वहां अपने वर्ग के नामों के साथ एक परीक्षण केस स्रोत बना सकते हैं। फिर आप टेस्टकेस स्रोत विशेषता वाले प्रत्येक परीक्षण को सजाने के लिए तैयार कर सकते हैं। फिर Activator.CreateInstance का उपयोग करके आप इंटरफ़ेस पर जा सकते हैं और आप सेट हो जाएंगे।

कुछ इस तरह (ध्यान दें - सिर संकलित)

string[] MyClassNameList = { "Class1", "Class2" }; 

[TestCaseSource(MyClassNameList)] 
public void Test1(string className) 
{ 
    var instance = Activator.CreateInstance(Type.FromName(className)) as IMyInterface; 

    ... 
} 
1

यह avandeursen's answer के आधार पर मेरी ठोस कार्यान्वयन है:

:

[TestClass] 
public abstract class IMyInterfaceTests 
{ 
    protected abstract IMyInterface CreateInstance(); 

    [TestMethod] 
    public void SomeTest() 
    { 
     IMyInterface instance = CreateInstance(); 
     // Run the test 
    } 
} 

प्रत्येक इंटरफेस कार्यान्वयन उसके बाद निम्न परीक्षण वर्ग को परिभाषित करता

[TestClass] 
public class MyImplementationTests : IMyInterfaceTests 
{ 
    protected override IMyInterface CreateInstance() 
    { 
     return new MyImplementation(); 
    } 
} 

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

+0

क्या आप एक विशेष परीक्षण ढांचे का उपयोग कर रहे हैं? मैं वीएस2012 में शामिल यूनिट परीक्षणों का उपयोग कर रहा हूं, और किसी अन्य "साझा" परीक्षण परियोजना (नामस्थान) से विरासत में परीक्षण प्राप्त नहीं किया जाता है। – drzaus

+0

अजीब - एक ही परियोजना के भीतर विरासत में परीक्षण, अलग-अलग नामस्थान ठीक दिखते हैं। यह केवल तब होता है जब वे एक अलग परियोजना में होते हैं कि वे पंजीकरण नहीं कर रहे हैं। मैं क्या खो रहा हूँ? – drzaus

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

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