5

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

class Car 
{ 
    //Constructor 
    public Car(Door door, Engine engine, Wheel wheel) 
    { 
     Contract.Requires(door).IsNotNull("Door is required"); 
     Contract.Requires(engine).IsNotNull("Engine is required"); 
     Contract.Requires(wheel).IsNotNull("Wheel is required"); 
     .... 
    } 
    ... 
    public void StartEngine() 
    { 
     this.engine.Start(); 
    } 
} 

अच्छा यह पहली नजर में अच्छा दिखता है? ऐसा लगता है कि हम एक सुरक्षित वर्ग का निर्माण कर रहे अनुबंध को उजागर कर रहे हैं ताकि प्रत्येक बार Car ऑब्जेक्ट बनाया गया हो, हम यह सुनिश्चित करने के लिए जान सकते हैं कि ऑब्जेक्ट "मान्य" है।

अब देखते हैं कि यह उदाहरण परीक्षण-संचालित बिंदु से देखें।

मैं परीक्षण के अनुकूल कोड का निर्माण करना चाहते हैं, लेकिन आदेश जब शायद अलगाव में परीक्षण करने के लिए मेरी Car वस्तु मैं सिर्फ अपनी वस्तु बनाने के लिए या तो एक नकली एक ठूंठ या प्रत्येक निर्भरता के लिए एक डमी वस्तु बनाने के लिए की जरूरत है, यहां तक ​​कि सक्षम होने के लिए में मैं सिर्फ एक विधि का परीक्षण करना चाहता हूं जो केवल StartEngine विधि जैसी इन निर्भरताओं में से एक का उपयोग करता है। परीक्षण के मिस्को हेवरी दर्शन के बाद मैं अपने परीक्षण को स्पष्ट रूप से निर्दिष्ट करना चाहता हूं कि मुझे दरवाजा या व्हील ऑब्जेक्ट्स की परवाह नहीं है, बस कन्स्ट्रक्टर के नल संदर्भ को पास कर रहा है, लेकिन चूंकि मैं नल की जांच कर रहा हूं, इसलिए मैं इसे नहीं कर सकता

यह सिर्फ कोड का एक छोटा सा टुकड़ा है, लेकिन क्योंकि आप अपने विषय के लिए निर्भरता को हल करने के लिए है जब आप एक असली आवेदन लेखन परीक्षण का सामना कर रहे कठिन है और कठिन हो जाता है

Misko का प्रस्ताव है कि हम चाहिए अशक्त-चेक की नहीं दुरुपयोग कोड (जो अनुबंध द्वारा डिज़ाइन द्वारा विरोधाभासी है) में, लेखन परीक्षण एक दर्द हो जाता है, एक विकल्प के रूप में वह कहता है कि "हमारे कोड सुरक्षित है क्योंकि हमारे पास सिर्फ इतना है कि हमारे कोड सुरक्षित हैं क्योंकि हमारे पास शून्य है हर जगह "

इस पर आपके विचार क्या हैं? आप यह कैसे करेंगे? सबसे अच्छा अभ्यास क्या होना चाहिए?

उत्तर

4

test data builders की अवधारणा पर एक नज़र डालें।

आप पहले से कॉन्फ़िगर किए गए डेटा के साथ निर्माता बनाते हैं, यदि संपत्ति के तहत अपने सिस्टम का एक नया उदाहरण प्राप्त करने के लिए Build() पर पहुंचने पर संपत्ति को ओवरराइड करें और कॉल करें।

या आप Enterprise Library के स्रोतों पर एक नज़र डाल सकते हैं। परीक्षणों में ArrangeActAssert नामक बेस क्लास होता है जो बीडीडी-आईएसएच परीक्षणों के लिए अच्छा समर्थन प्रदान करता है। आप एएए से प्राप्त कक्षा के Arrange विधि में अपना परीक्षण सेटअप लागू करते हैं और जब भी आप कोई विशिष्ट परीक्षण चलाते हैं तो इसे कॉल किया जाएगा।

+0

परीक्षण बिल्डरों, वास्तव में क्या मैं – Jupaol

+0

लिए देख रहा था यह पैटर्न 'वस्तु माँ का नाम है होना करने के लिए हालांकि' परीक्षण डाटा बिल्डर 'थोड़ा अधिक सहज है :-) – Steven

1

मैं इकाई परीक्षण में इस समस्या का समाधान:

कार के लिए मेरा परीक्षण वर्ग देखने की तरह होगा:

public sealed class CarTest 
{ 
    public Door Door { get; set; } 
    public Engine Engine { get; set; } 
    public Wheel Wheel { get; set; } 

    //... 

    [SetUp] 
    public void Setup() 
    { 
     this.Door = MockRepository.GenerateStub<Door>(); 
     //... 
    } 

    private Car Create() 
    { 
     return new Car(this.Door, this.Engine, this.Wheel); 
    } 
} 

अब, परीक्षण तरीकों में, मैं सिर्फ "रोचक" निर्दिष्ट करने की आवश्यकता ऑब्जेक्ट्स:

public void SomeTestUsingDoors() 
{ 
    this.Door = MockRepository.GenerateMock<Door>(); 
    //... - setup door 

    var car = this.Create(); 
    //... - do testing 
} 
+0

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

+0

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

1

आपको अपने लिए इस तरह की नौकरी करने के लिए टूल पर विचार करना चाहिए। AutoFixture की तरह। अनिवार्य रूप से, यह वस्तुओं को बनाता है।के रूप में सरल रूप में यह लग सकता है, AutoFixture वास्तव में आप यहाँ क्या जरूरत है क्या कर सकते हैं - कुछ मानकों के साथ instantiate object है कि आप के बारे में परवाह नहीं है:

MyClass sut = fixture.CreateAnnonymous<MyClass>(); 

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

संपादित करें: परिचय एक छोटा सा विस्तार करने के लिए ...

AutoFixure भी पूर्ण विकसित auto-mocking container बनने के लिए AutoMoq विस्तार के साथ आता है। जब ऑटोफिक्चर एक ऑब्जेक्ट (अर्थात्, इंटरफेस या अमूर्त वर्ग) बनाने में विफल रहता है, तो यह सृजन को मक में प्रस्तुत करता है - जो इसके बजाय मैक्स बना देगा।

तो, अगर आप इस तरह निर्माता हस्ताक्षर के साथ वर्ग था:

public ComplexType(IDependency d, ICollaborator c, IProvider p) 

आपका परिदृश्य में परीक्षण सेटअप है जब आप किसी भी निर्भरता के बारे में परवाह नहीं है और चाहते हैं तो बस nulls, 2 लाइनों से बना हुआ है होगा कोड:

var fixture = new Fixture().Customize(new AutoMoqCustomization()); 
var testedClass = fixture.CreateAnonymous<ComplexType>(); 

यह सब कुछ है। testedClass हुड के तहत मोक द्वारा उत्पन्न मोक्स के साथ बनाया जाएगा। ध्यान दें कि testedClassएक नकली नहीं है - यह वास्तविक वस्तु है जिसे आप परीक्षण कर सकते हैं जैसे कि आपने इसे निर्माता के साथ बनाया है।

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

var fixture = new Fixture().Customize(new AutoMoqCustomization()); 
var collaboratorMock = fixture.Freeze<Mock<ICollaborator>>(); 
var testedClass = fixture.CreateAnonymous<ComplexType>(); 

ICollaborator नकली आप के लिए पूर्ण पहुँच गया, .Setup, .Verify और सभी संबंधित सामान कर सकते हैं होगा: आप सभी की जरूरत कोड की एक अतिरिक्त लाइन है। मैं वास्तव में ऑटोफिक्चर को एक नज़र देने का सुझाव देता हूं - यह महान पुस्तकालय है।

+0

लगते Moq मेरी choise (मैं इसे btw प्यार), लेकिन अभी भी मैं है इसे – Jupaol

+0

@ जुपाओल करने के लिए एक क्लीनर तरीका ढूंढना पसंद है: मैंने ऑटोफिक्शन को ठीक से पेश नहीं किया हो सकता है। यह ** ** एक मॉकिंग फ्रेमवर्क नहीं है। आप इसे मक के साथ * ऑटो-मॉकिंग कंटेनर * के रूप में उपयोग करने के लिए एक साथ उपयोग कर सकते हैं। मेरा संपादन देखें। –

+0

कूलर लग रहा है की तुलना में मैंने सोचा कि मैं इसे आजमाइए करेंगे धन्यवाद – Jupaol

0

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

बेशक आप तर्क दे सकते हैं क्योंकि मैं अपने सेवा प्रकारों के लिए शून्य जांच छोड़ देता हूं, उन प्रकारों को अब डीआई कंटेनर के अस्तित्व के बारे में पता है, लेकिन यह कुछ है जो मैं अपने अनुप्रयोगों के साथ रह सकता हूं। एक पुन: प्रयोज्य ढांचे को डिजाइन करते समय, चीजें बिल्कुल अलग होती हैं। उस स्थिति में आपको शायद सभी शून्य जांच की आवश्यकता होगी।

+0

हाँ ... लेकिन निर्भरता इंजेक्शन एक अवधारणा है कि न केवल सेवाएं (इंजेक्शन) पर लागू होते हैं एक आईओसी कंटेनर जिसका अर्थ है कि आप एक में डि उपयोग कर सकते हैं के द्वारा हल किया जा रहा है अन्य नए सामानों की आवश्यकता के द्वारा नई (इकाई या मूल्य वस्तु) तो क्या आप इन वस्तुओं को या तो नहीं देख पाएंगे ?? – Jupaol

+0

मेरे सिस्टम में मेरे पास मूल रूप से दो प्रकार के वर्ग हैं। 1. कमांड और इकाइयों जैसे डेटा ऑब्जेक्ट्स, जिनमें केवल डेटा होता है, और कोई व्यवहार नहीं होता है, और सेवाओं में कोई निर्भरता नहीं होती है। 2. ऐसी सेवाएं जिनमें व्यापार तर्क शामिल है और अक्सर अन्य सेवाओं में अन्य depedencencies शामिल हैं और संभवतः उन डेटा ऑब्जेक्ट्स (अक्सर 'नए' ऑपरेटर का उपयोग करके) बनाते हैं। तो मैं अपनी संस्थाओं में निर्भरता इंजेक्ट नहीं करता हूं। – Steven

+0

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

6

मैं हर निर्भरता

यह आमतौर पर कहा गया है के लिए या तो एक नकली एक ठूंठ या एक डमी वस्तु बनाने के लिए की जरूरत है। लेकिन मुझे लगता है कि यह गलत है।यदि CarEngine ऑब्जेक्ट से जुड़ा हुआ है, तो वास्तविकEngine ऑब्जेक्ट का उपयोग क्यों न करें जब इकाई Car कक्षा का परीक्षण करती है?

लेकिन, अगर आप ऐसा करते हैं तो इकाई आपके कोड का परीक्षण नहीं कर रहा है; दो इकाइयों, इसलिए एक इकाई परीक्षण एकीकरण परीक्षण के बजाय: अपने परीक्षण दोनों Car वर्ग और Engine वर्ग पर निर्भर करता है। लेकिन क्या वे लोग String कक्षा का भी नकल करते हैं? या HashSet<String>? बिलकूल नही। इकाई और एकीकरण परीक्षण के बीच की रेखा इतनी स्पष्ट नहीं है।

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