सी # और राइनोमोक्स का उपयोग कर टेस्ट संचालित विकास के सर्वोत्तम अभ्यास


86

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

कोड की testability बढ़ाने के लिए, इन नियमों का पालन:

  1. परीक्षण लिखें पहले, तो कोड। कारण: यह सुनिश्चित करता है कि आप टेस्टेबल कोड लिखें और कोड की प्रत्येक पंक्ति को इसके लिए लिखे गए परीक्षण मिलते हैं।

  2. निर्भरता इंजेक्शन का उपयोग कर डिज़ाइन कक्षाएं। कारण: आप नकली या परीक्षण नहीं कर सकते कि क्या देखा जा सकता है।

  3. मॉडल-व्यू-कंट्रोलर या मॉडल-व्यू-प्रेजेंटर का उपयोग करके अपने व्यवहार से पृथक यूआई कोड। कारण: व्यवसाय तर्क की जांच करने की अनुमति देता है जबकि जिन हिस्सों का परीक्षण नहीं किया जा सकता है (यूआई) कम किया जाता है।

  4. स्थिर विधियों या कक्षाएं न लिखें। कारण: स्टेटिक विधियों को अलग करना मुश्किल या असंभव है और राइनो मोक्स उन्हें नकल करने में असमर्थ हैं।

  5. इंटरफेस से प्रोग्राम, कक्षाओं में प्रोग्राम। कारण: इंटरफेस का उपयोग वस्तुओं के बीच संबंधों को स्पष्ट करता है। एक इंटरफेस को उस सेवा को परिभाषित करना चाहिए जिसे ऑब्जेक्ट को अपने पर्यावरण से चाहिए। इसके अलावा, इंटरफेस आसानी से राइनो मोक्स और अन्य मॉकिंग फ्रेमवर्क का उपयोग करके मजाक किया जा सकता है।

  6. बाहरी निर्भरताओं को अलग करें। कारण: अनसुलझा बाहरी निर्भरताओं का परीक्षण नहीं किया जा सकता है।

  7. वर्चुअल तरीके के रूप में चिह्नित करें जिन्हें आप नकल करना चाहते हैं। कारण: राइनो मोक्स गैर-आभासी तरीकों का नकल करने में असमर्थ है।

  0

यह एक उपयोगी सूची है। वर्तमान में हम न्यूटिट और राइनो.मोक्स का उपयोग कर रहे हैं, और टीम के सदस्यों के लिए इन मानदंडों को स्पेल करना अच्छा होता है जो यूनिट परीक्षण के इस पक्ष से कम परिचित हैं। 24 sep. 082008-09-24 13:38:02

56

निश्चित रूप से एक अच्छी सूची। यहां कुछ विचार दिए गए हैं:

पहले परीक्षण लिखें, फिर कोड।

मैं उच्च स्तर पर सहमत हूं।लेकिन, मैं और अधिक विशिष्ट होगा: "पहले एक परीक्षण लिखें, फिर लिखें, परीक्षा पास करने के लिए पर्याप्त कोड लिखें और दोहराएं।" अन्यथा, मुझे डर होगा कि मेरे यूनिट परीक्षण एकीकरण या स्वीकृति परीक्षण की तरह दिखेंगे।

निर्भरता इंजेक्शन का उपयोग कर डिज़ाइन कक्षाएं।

सहमत हुए। जब कोई ऑब्जेक्ट अपनी निर्भरता बनाता है, तो आपके ऊपर उनका कोई नियंत्रण नहीं होता है। नियंत्रण/निर्भरता इंजेक्शन का उलटा आपको उस नियंत्रण को देता है, जिससे आप वस्तु को मॉक्स/स्टब्स/आदि के साथ परीक्षण के तहत अलग कर सकते हैं। इस प्रकार आप अलगाव में वस्तुओं का परीक्षण करते हैं।

मॉडल-व्यू-कंट्रोलर या मॉडल-व्यू-प्रेजेंटर का उपयोग करके अपने व्यवहार से पृथक यूआई कोड।

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

स्थिर विधियों या कक्षाएं न लिखें।

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

इंटरफेस से प्रोग्राम, कक्षाओं में प्रोग्राम।

मैं सहमत हूं, लेकिन थोड़ा अलग कारण के लिए। इंटरफेस सॉफ़्टवेयर डेवलपर को लचीलापन प्रदान करता है - विभिन्न मॉक ऑब्जेक्ट फ्रेमवर्क के लिए केवल समर्थन से परे। उदाहरण के लिए, बिना इंटरफ़ेस के DI को ठीक से समर्थन करना संभव नहीं है।

बाहरी निर्भरताओं को अलग करें।

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

वर्चुअल विधियों के रूप में चिह्नित करें जिन्हें आप नकल करना चाहते हैं।

यह राइनो मोक्स की एक सीमा है। एक ऐसे माहौल में जो नकली ऑब्जेक्ट ढांचे पर हाथ कोडित स्टब्स पसंद करता है, वह आवश्यक नहीं होगा।

और, नए अंक के एक जोड़े पर विचार करना: creational डिजाइन पैटर्न

का प्रयोग करें। यह DI के साथ सहायता करेगा, लेकिन यह आपको उस कोड को अलग करने और अन्य तर्कों से स्वतंत्र रूप से परीक्षण करने की अनुमति देता है।

Bill Wake's Arrange/Act/Assert technique का उपयोग करके परीक्षण लिखें। यह तकनीक यह स्पष्ट करती है कि कॉन्फ़िगरेशन आवश्यक है, वास्तव में परीक्षण किया जा रहा है, और क्या अपेक्षित है।

अपने स्वयं के मोजे/स्टब्स रोल करने से डरो मत। अक्सर, आप पाएंगे कि मॉक ऑब्जेक्ट फ्रेमवर्क का उपयोग करके आपके परीक्षणों को पढ़ने के लिए अविश्वसनीय रूप से कठिन बना दिया जाता है। अपना खुद का रोल करके, आप अपने मोजे/स्टब्स पर पूरा नियंत्रण रखेंगे, और आप अपने परीक्षणों को पठनीय रखने में सक्षम होंगे। (पिछली बिंदु पर वापस देखें।)

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

सतत एकीकरण लागू करें। प्रत्येक "ग्रीन बार" पर अपना कोड चेक-इन करें। अपने सॉफ़्टवेयर का निर्माण करें और प्रत्येक चेक-इन पर यूनिट परीक्षणों का पूरा सूट चलाएं। (निश्चित रूप से, यह कोडिंग अभ्यास नहीं है, लेकिन यह आपके सॉफ़्टवेयर को साफ और पूरी तरह से एकीकृत रखने के लिए एक अविश्वसनीय टूल है।)

+2

मुझे आमतौर पर पता चलता है कि यदि कोई परीक्षण पढ़ना मुश्किल होता है, तो यह ढांचे की गलती नहीं है बल्कि कोड का परीक्षण है। यदि सेट स्थापित करने के लिए जटिल है, तो शायद इसे और अवधारणाओं में विभाजित किया जाना चाहिए। 06 sep. 092009-09-06 19:42:58


1

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

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

  0

मैं एक निजी परियोजना में एक समान बीडीडी शैली परीक्षण अनुभाग (यूनिट परीक्षण कोड के अतिरिक्त) भी करता हूं। 24 sep. 082008-09-24 00:11:03


6

fakes, mocks and stubs और प्रत्येक का उपयोग कब करें के बीच अंतर जानें।

मैक्स का उपयोग करके इंटरैक्शन निर्दिष्ट करने से बचें। यह परीक्षण brittle बनाता है।


10

यदि आप .NET 3.5 के साथ काम कर रहे हैं, तो आप Moq मॉकिंग लाइब्रेरी में देखना चाहेंगे - यह अभिव्यक्ति पेड़ और लैम्बडा का उपयोग करता है ताकि अधिकांश अन्य मॉकिंग लाइब्रेरीज़ के गैर-सहज रिकॉर्ड-उत्तर मुहावरे को हटाया जा सके।

// ShouldExpectMethodCallWithVariable 
int value = 5; 
var mock = new Mock<IFoo>(); 

mock.Expect(x => x.Duplicate(value)).Returns(() => value * 2); 

Assert.AreEqual(value * 2, mock.Object.Duplicate(value)); 
+5

मुझे लगता है कि राइनो मोक्स का नया संस्करण इस तरह काम करता है 24 sep. 082008-09-24 13:21:06


0

यहाँ एक एक और एक है कि मैं मैं करना चाहता हूँ कि के बारे में सोचा है: कितना अधिक सहज ज्ञान युक्त अपने परीक्षण मामलों बन देखने के लिए इस quickstart

चेक बाहर, यहाँ एक सरल उदाहरण है।

यदि आप टेस्टड्रिवेन.Net या NANT से विरोध के रूप में इकाई परीक्षण गुई से परीक्षण चलाने की योजना बनाते हैं तो मुझे यूनिट परीक्षण प्रोजेक्ट प्रकार को लाइब्रेरी के बजाय कंसोल एप्लिकेशन में सेट करना आसान हो गया है। यह आपको मैन्युअल रूप से परीक्षण चलाने और डीबग मोड में उनके माध्यम से कदम उठाने की अनुमति देता है (जो उपर्युक्त TestDriven.Net वास्तव में आपके लिए कर सकता है)।

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


3

यह एक बहुत ही उपयोगी पोस्ट है!

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

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

टीडीडी Diminishing Marginal Return के कानून के अधीन है। संक्षेप में, टीडीडी की ओर आपके प्रयास तेजी से मूल्यवान होते हैं जब तक आप अधिकतम रिटर्न के बिंदु पर नहीं पहुंच जाते हैं, जिसके बाद, बाद में टीडीडी में निवेश किए गए समय में कम और कम मूल्य होता है।

मुझे विश्वास है कि टीडीडी का प्राथमिक मूल्य सीमा (ब्लैकबॉक्स) के साथ-साथ सिस्टम के मिशन-महत्वपूर्ण क्षेत्रों के कभी-कभी व्हाइटबॉक्स परीक्षण में है।


2

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

  0

सहमत ... मैं इसे प्रतिबिंबित करने के लिए अपना प्रश्न अपडेट करने जा रहा हूं। 09 sep. 092009-09-09 23:29:56