2012-03-25 20 views
15

यूनिट परीक्षण के निम्नलिखित उदाहरण पर विचार करें। टिप्पणियां मेरी समस्या को काफी समझाती हैं।हमेशा परीक्षण के बाद साफ करें?

[TestMethod] 
public void MyTestMethod() 
{ 

    //generate some objects in the database 
    ... 

    //make an assert that fails sometimes (for example purposes, this fails always) 
    Assert.IsTrue(false); 

    //TODO: how do we clean up the data generated in the database now that the test has ended here? 

} 
+0

आपको साफ करने के लिए 'टायरडाउन' (या अपने सूट में इसके बराबर) का उपयोग करना चाहिए क्योंकि यदि आपका परीक्षण विफल रहता है, तो क्लीन अप कोड निष्पादित नहीं होगा। –

+0

अपवाद को पकड़ने के बारे में, फिर सफाई के बाद इसे फिर से फेंकना? –

+0

जिमी बोगर्ड (* ऑटोमैपर * के लेखक) के पास एक महान लेख और टूल है: [Respawn के साथ विश्वसनीय डेटाबेस परीक्षण] (https://lostechies.com/jimmybogard/2015/02/19/reliable-database-tests-with-respawn /) –

उत्तर

24

जैसी चीजों को देखें। ऐसा करने के दो तरीके हैं। One TestInitialize उपयोग कर रहा है और TestCleanup परीक्षण कक्षा में तरीकों पर जिम्मेदार बताते हैं। वे क्रमशः परीक्षण के पहले और बाद में दौड़ेंगे।

एक और तरीका है तथ्य यह है कि परीक्षण विफलताओं अपवाद के माध्यम से परीक्षण धावक के लिए उगाया जाता है उपयोग करने के लिए है। इसका मतलब यह है कि आपके परीक्षण में {} अंततः {} ब्लॉक को आज़माएं विफल होने के बाद कुछ भी साफ कर सकते हैं।

[TestMethod] 
public void FooTest() 
{ 
    try 
    { 
    // setup some database objects 
    Foo foo = new Foo(); 
    Bar bar = new Bar(foo); 
    Assert.Fail(); 
    } 
    finally 
    { 
    // remove database objects. 
    } 
} 

ट्राई/अंत में सफाई वास्तव में गन्दा प्राप्त कर सकते हैं सफाई के लिए वस्तुओं का एक बहुत देखते हैं है। मेरी टीम ने जो हद तक झुकाया है वह एक सहायक वर्ग है जो IDISposable लागू करता है। यह ट्रैक करता है कि कौन सी वस्तुएं बनाई गई हैं और उन्हें एक ढेर पर धक्का देती है। जब निपटान किया जाता है तो आइटम को स्टैक से पॉप किया जाता है और डेटाबेस से निकाल दिया जाता है।

[TestMethod] 
public void FooTest() 
{ 
    using (FooBarDatabaseContext context = new FooBarDatabaseContext()) 
    { 
    // setup some db objects. 
    Foo foo = context.NewFoo(); 
    Bar bar = context.NewBar(foo); 
    Assert.Fail(); 
    } // calls dispose. deletes bar, then foo. 
} 

इसमें विधि कॉल में रचनाकारों को लपेटने का अतिरिक्त लाभ है। यदि निर्माता हस्ताक्षर बदलते हैं तो हम आसानी से परीक्षण कोड को संशोधित कर सकते हैं।

+9

मुझे नाइटपिक करना अच्छा लगता है; TestCleanup तब नहीं चलता है जब TestInitialize ने अपवाद फेंक दिया हो। –

+4

@ carlin.scott आपका नाइटपिकिंग अभी मेरा दिन बचा है –

6

प्रतिक्रियाओं के एक जोड़े:

  1. यह एक वास्तविक डेटाबेस का उपयोग कर रहा है, तो मैं बहस चाहते हैं कि यह एक "इकाई परीक्षण" शब्द के सख्त अर्थ में नहीं है। यह एकीकरण परीक्षण है। एक इकाई परीक्षण में ऐसे दुष्प्रभाव नहीं होने चाहिए। वास्तविक डेटाबेस अनुकरण करने के लिए एक मॉकिंग लाइब्रेरी का उपयोग करने पर विचार करें। Rhino Mocks एक है, लेकिन बहुत सारे लोग हैं।

  2. यदि, हालांकि, इस परीक्षण के पूरे बिंदु वास्तव में डेटाबेस के साथ बातचीत करना है, तो आप एक क्षणिक परीक्षण-केवल डेटाबेस से बातचीत करना चाहेंगे। उस स्थिति में आपके स्वचालित परीक्षण के हिस्से में स्क्रैच से परीक्षण डेटाबेस बनाने के लिए कोड शामिल होगा, फिर परीक्षण चलाएं, फिर परीक्षण डेटाबेस को नष्ट करें। फिर, विचार बाहरी दुष्प्रभाव नहीं है। इसके बारे में जाने के लिए शायद कई तरीके हैं, और मैं वास्तव में एक ठोस सुझाव देने के लिए इकाई परीक्षण ढांचे के साथ पर्याप्त परिचित नहीं हूं। लेकिन यदि आप विजुअल स्टूडियो में बनाए गए परीक्षण का उपयोग कर रहे हैं तो शायद Visual Studio Database Project का उपयोग किया जाएगा।

1

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

मैं डेविड से सहमत हूं। आपके परीक्षणों का आमतौर पर कोई साइड इफेक्ट नहीं होना चाहिए। आपको प्रत्येक एकल परीक्षण के लिए एक नया डेटाबेस स्थापित करना चाहिए।

0

आपको इस परिस्थिति में मैन्युअल सफाई करना होगा। हां, डीबी में कुछ वस्तुओं को उत्पन्न करने के विपरीत।

विकल्प है, ताकि डेटाबेस है सिर्फ एक स्मृति डेटाबेस

0

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

10

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

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

तो जब आप व्यवसाय तर्क का परीक्षण कर रहे हैं जो डेटाबेस से डेटा पर निर्भर करता है, तो आप आमतौर पर Repository Pattern जैसे कुछ का उपयोग करेंगे और यूनिट परीक्षण के लिए fake/stub/mock IXXXRepository इंजेक्ट करेंगे। आप ठोस भंडार का परीक्षण करते समय, आप या तो डेटाबेस सफाई की तरह आप के बारे में पूछ रहे हैं क्या करने की जरूरत है या आप शिम/अंतर्निहित डेटाबेस कॉल ठूंठ की जरूरत है। यह वास्तव में आप पर निर्भर है।

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

MS-टेस्ट में विशेषताओं का उपयोग होगा घोषित करने के लिए सेटअप/टियरडाउन ClassInitialize, ClassCleanUp, TestInitialize, TestCleanUp हैं। अन्य ढांचे के समान नामों का नाम है। Moq, Rhino Mocks, NMock, TypeMock, Moles and Stubs (VS2010), VS11 Fakes (VS11 बीटा), आदि, आप देख रहे हैं निर्भरता इंजेक्शन चौखटे के लिए:

वहाँ चौखटे है कि आप मजाक/छोटा करते के साथ मदद कर सकते हैं की एक संख्या हैं Ninject, Unity, Castle Windsor, आदि

0

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

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

0

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

0

मुझे एक तुलनात्मक मुद्दा था जहां एक परीक्षण का दावा सफाई को रोक रहा था और अन्य परीक्षणों को विफल कर रहा था।

उम्मीद है कि यह किसी के लिए कभी-कभी उपयोग में है।

[Test] 
    public void Collates_Blah_As_Blah() 
    { 
     Assert.False(SINGLETON.Collection.Any()); 

     for (int i = 0; i < 2; i++) 
      Assert.That(PROCESS(ValidRequest) == Status.Success); 

     try 
     { 
      Assert.AreEqual(1, SINGLETON.Collection.Count); 
     } 
     finally 
     { 
      SINGLETON.Collection.Clear(); 
     } 
    } 

अंत में ब्लॉक निष्पादित करेंगे अभिकथन गुजरता है या विफल रहता है कि क्या है, यह भी झूठी गुजरता के जोखिम को लागू नहीं करता है - जो पकड़ का कारण होगा!

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