2008-09-06 7 views
14

कुछ समय पहले मैं मार्टिन Fowler द्वारा Mocks Aren't Stubs लेख पढ़ सकते हैं और मैं मानता हूं कि मैं जटिलता के संबंध में बाहरी निर्भरता का एक सा डर कर रहा हूँ तो मैं पूछना चाहूँगा:क्या स्टॉक्स से बेहतर मोजे हैं?

जब उपयोग करने के लिए सबसे अच्छा तरीका क्या है इकाई का परीक्षण?

क्या परीक्षण की विधि की निर्भरताओं को स्वचालित रूप से नकल करने के लिए हमेशा नकली ढांचे का उपयोग करना बेहतर होता है, या आप उदाहरण के लिए परीक्षण स्टब्स जैसे सरल तंत्र का उपयोग करना पसंद करेंगे?

उत्तर

12

मंत्र के रूप में 'सबसे सरल चीज के साथ जाओ जो संभवतः काम कर सकता है।'

  1. यदि नकली कक्षाएं काम पूरा कर सकती हैं, तो उनके साथ जाएं।
  2. यदि आपको मॉक करने के लिए कई विधियों के साथ इंटरफ़ेस की आवश्यकता है, तो नकली ढांचे के साथ जाएं।

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

अद्यतन उपसंहार/विवेचना:
(धन्यवाद तोरण Billups करने के लिए एक mockist परीक्षण के उदाहरण के लिए नीचे देखें।)
हाय डौग, अच्छी तरह से मुझे लगता है कि हम एक और पवित्र युद्ध में पार किया है - बनाम Mockist TDDers क्लासिक TDDers । मुझे लगता है कि मैं पूर्व से संबंधित हूं।

  • अगर मैं पर परीक्षण # 101 Test_ExportProductList हूँ और मैं मैं IProductService.GetProducts के लिए एक नया परम जोड़ने की जरूरत है लगता है()। मैं करता हूं कि यह परीक्षण हरा हो। मैं अन्य सभी संदर्भों को अद्यतन करने के लिए एक रिफैक्टरिंग टूल का उपयोग करता हूं। अब मुझे इस सदस्य को बुलाए जाने वाले सभी नकली परीक्षण मिलते हैं। तब मुझे वापस जाना होगा और इन सभी परीक्षणों को अपडेट करना होगा - समय की बर्बादी। क्यों चाहिए PopPopulateProductsListOnViewLoadWhenPostBackIsFalse विफल? क्या ऐसा इसलिए था क्योंकि कोड टूटा हुआ है? बल्कि परीक्षण टूट गए हैं। मैं को ठीक करने के लिए एक परीक्षण विफलता = 1 स्थान का पक्ष लेता हूं। मज़ाकिया freq उस के खिलाफ चला जाता है। क्या स्टब्स बेहतर होगा? अगर मेरे पास एक fake_class.GetProducts() .. सुनिश्चित करें कि एकाधिक उम्मीद कॉल पर शॉटगन शल्य चिकित्सा के बजाय एक स्थान बदलना है। अंत में यह शैली का मामला है .. यदि आपके पास एक सामान्य उपयोगिता विधि है MockHelper.SetupExpectForGetProducts() - जो भी पर्याप्त होगा .. लेकिन आप देखेंगे कि यह असामान्य है।
  • यदि आप परीक्षण नाम पर एक सफेद पट्टी डालते हैं, तो परीक्षण पढ़ने के लिए मुश्किल है। नकली ढांचे के लिए बहुत सारे नलसाजी कोड वास्तविक परीक्षण किए जा रहे हैं।
  • एक मजाक ढांचे के इस विशेष स्वाद
1

this blog post में इस सवाल के बारे में ल्यूक Kanies की चर्चा पढ़ें। वह a post from Jay Fields का संदर्भ देता है जो यह भी बताता है कि [रूबी के/मोचा के बराबर] stub_everything का प्रयोग परीक्षण को और अधिक मजबूत बनाने के लिए प्राथमिक है। फ़ील्ड्स के अंतिम शब्दों को उद्धृत करने के लिए: "मोचा इसे एक मॉक को परिभाषित करना आसान बनाता है क्योंकि यह एक स्टब को परिभाषित करना है, लेकिन इसका मतलब यह नहीं है कि आपको हमेशा मॉक्स पसंद करना चाहिए। असल में, मैं आमतौर पर स्टब्स पसंद करता हूं और आवश्यक होने पर मैक्स का उपयोग करता हूं। "

2

यह सिर्फ आप कर रहे हैं परीक्षण किस प्रकार पर निर्भर करता है जानने के लिए की आवश्यकता है। यदि आप व्यवहार आधारित परीक्षण कर रहे हैं तो आप एक गतिशील नकली चाहते हैं ताकि आप यह सत्यापित कर सकें कि आपकी निर्भरता के साथ कुछ बातचीत होती है। लेकिन यदि आप एक स्टब चाहते हैं तो आप मूल्य/आदि

उदाहरण के लिए, नीचे दिए गए परीक्षण में आप देखते हैं कि मैं दृश्य को रोकता हूं ताकि मैं एक संपत्ति मान निर्धारित कर सकूं (राज्य आधारित परिक्षण)। मैं फिर सेवा कक्षा का एक गतिशील नकली बना देता हूं ताकि मैं सुनिश्चित कर सकूं कि परीक्षण (इंटरैक्शन/व्यवहार आधारित परीक्षण) के दौरान एक विशिष्ट विधि को बुलाया जाता है।

<TestMethod()> _ 
Public Sub Should_Populate_Products_List_OnViewLoad_When_PostBack_Is_False() 
    mMockery = New MockRepository() 
    mView = DirectCast(mMockery.Stub(Of IProductView)(), IProductView) 
    mProductService = DirectCast(mMockery.DynamicMock(Of IProductService)(), IProductService) 
    mPresenter = New ProductPresenter(mView, mProductService) 
    Dim ProductList As New List(Of Product)() 
    ProductList.Add(New Product()) 
    Using mMockery.Record() 
     SetupResult.For(mView.PageIsPostBack).Return(False) 
     Expect.Call(mProductService.GetProducts()).Return(ProductList).Repeat.Once() 
    End Using 
    Using mMockery.Playback() 
     mPresenter.OnViewLoad() 
    End Using 
    'Verify that we hit the service dependency during the method when postback is false 
    Assert.AreEqual(1, mView.Products.Count) 
    mMockery.VerifyAll() 
End Sub 
2

संयोजन का उपयोग करना सबसे अच्छा है, और आपको अपने निर्णय का उपयोग करना होगा। यहां दिशानिर्देश दिए गए हैं:

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

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

और फिर, यह एक कोड गंध और अंतिम उपाय है। यदि आपको लगता है कि आपको अक्सर ऐसा करने की ज़रूरत है, तो आप अपने परीक्षण लिखने के तरीके पर पुनर्विचार करने का प्रयास करें।

7

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

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

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

और इसके लिए ...

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

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

2

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

एक लंबी चर्चा के लिए, http://www.mockobjects.com/book

पर एक नज़र डालने पर विचार करें
संबंधित मुद्दे