क्या यूनिट परीक्षण से समय से पहले सामान्यीकरण होता है (विशेषकर C ++ के संदर्भ में)?


20

प्रारंभिक नोट्स

मैं वहाँ परीक्षण के विभिन्न प्रकारों के भेद में नहीं जाऊंगा, इन साइटों पर पहले से ही कुछ प्रश्न हैं

मैं वहाँ ले जाऊंगा और जो कहता है: "किसी अनुप्रयोग की सबसे छोटी पृथक्करण इकाई का परीक्षण" करने के अर्थ में इकाई परीक्षण, जिससे यह वास्तव में प्रभावित होता है

अलगाव की समस्या

किसी प्रोग्राम की सबसे छोटी वियोज्य इकाई क्या है । ठीक है, जैसा कि मैं इसे देखता हूं, यह (अत्यधिक?) इस पर निर्भर करता है कि आप किस भाषा में कोडिंग कर रहे हैं।

माइकल फेदर्स सीम की अवधारणा के बारे में बात करते हैं : [WEwLC, p31]

सीम एक ऐसी जगह है जहां आप उस स्थान पर संपादन के बिना अपने कार्यक्रम में व्यवहार को बदल सकते हैं।

और विवरण में जाने के बिना, मैं एक सीम को समझता हूं - इकाई परीक्षण के संदर्भ में - एक कार्यक्रम में एक जगह होने के लिए जहां आपका "परीक्षण" आपकी "इकाई" के साथ इंटरफेस कर सकता है।

उदाहरण

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

उदाहरण:

  • एक आभासी इंटरफ़ेस जोड़ना जहां गैर-आभासी कार्यान्वयन पर्याप्त होता
  • बंटवारा - सामान्यीकरण (?) - एक (छोटा) वर्ग आगे "बस" एक परीक्षण जोड़ने की सुविधा के लिए।
  • परीक्षणों के लिए स्वतंत्र रूप से संकलन करने की सुविधा के लिए एकल-निष्पादन योग्य परियोजना को "स्वतंत्र" परिवादों, "बस" में विभाजित करना।

प्रश्न

मैं कुछ संस्करणों की कोशिश करूँगा जो उम्मीद करते हैं कि उसी बिंदु के बारे में पूछें:

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

मुझे अंगूठे का एक नियम याद है, जिसमें कहा गया है कि जब तक आपको जरूरत न हो / तब तक सामान्य न करें जब तक कि कोड का उपयोग करने वाला दूसरा स्थान न हो। यूनिट टेस्ट के साथ, कोड का उपयोग करने वाला हमेशा दूसरा स्थान होता है - अर्थात् यूनिट टेस्ट। तो क्या यह कारण सामान्य करने के लिए पर्याप्त है?


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

@ hotpaw2 ईश निंदा! :)
maple_shaft

जवाबों:


23

यूनिट टेस्ट - विशेष रूप से सी ++ में - अधिक सीम जोड़ने के लिए परीक्षण के तहत कोड की आवश्यकता होती है जो किसी समस्या के लिए कड़ाई से बुलाया जाएगा।

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

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

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

क्या जिस तरह से यूनिट टेस्ट के लिए एक एप्लिकेशन कोड को "केवल" यूनिट टेस्ट के लिए फायदेमंद होना चाहिए, या क्या यह वास्तव में एप्लीकेशन स्ट्रक्चर के लिए फायदेमंद है?

मेरे अनुभव में एक परीक्षण योग्य डिजाइन समग्र रूप से फायदेमंद है, न कि केवल "केवल" यूनिट परीक्षणों के लिए। ये लाभ विभिन्न स्तरों पर आते हैं:

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

मुझे अंगूठे का एक नियम याद है, जिसमें कहा गया है कि जब तक आपको जरूरत न हो / तब तक सामान्य न करें जब तक कि कोड का उपयोग करने वाला दूसरा स्थान न हो। यूनिट टेस्ट के साथ, कोड का उपयोग करने वाला हमेशा एक दूसरा स्थान होता है - अर्थात् यूनिट टेस्ट। तो क्या यह कारण सामान्य करने के लिए पर्याप्त है?

यदि आप यह साबित कर सकते हैं कि आपका सॉफ़्टवेयर ठीक वही करता है जो वह करना चाहता है - और इसे अपने ग्राहकों को संतुष्ट करने के लिए एक तेज़, बार-बार, सस्ते और निर्धारक तरीके से साबित करें - यूनिट परीक्षणों द्वारा "अतिरिक्त" सामान्यीकरण या सीम के बिना, इसके लिए जाएं। (और हमें बताएं कि आप इसे कैसे करते हैं, क्योंकि मुझे यकीन है कि इस मंच पर बहुत सारे लोग मेरे जैसे ही होंगे :-)

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


महोदय, मैं आपको प्रणाम करता हूं।
गॉर्डन

एक संक्षिप्त, लेकिन पांडित्यपूर्ण नोट: "डायग्नोस्टिक पोर्ट" ज्यादातर वहां है क्योंकि सरकारों ने उन्हें उत्सर्जन नियंत्रण योजना के हिस्से के रूप में अनिवार्य किया है। नतीजतन, इसकी गंभीर सीमाएं हैं; कई चीजें हैं जो संभावित रूप से इस बंदरगाह के साथ निदान की जा सकती हैं जो (उत्सर्जन नियंत्रण के साथ कुछ भी नहीं करने वाली) हैं।
रॉबर्ट हार्वे

4

मैं आप पर टेस्टीवस का रास्ता फेंकने जा रहा हूं , लेकिन संक्षेप में:

यदि आप सिस्टम के एक हिस्से का परीक्षण करने के लिए अपने कोड को अधिक जटिल बनाने में बहुत समय और ऊर्जा खर्च कर रहे हैं, तो यह हो सकता है कि आपकी संरचना गलत है, या यह कि आपका परीक्षण दृष्टिकोण गलत है।

सबसे सरल मार्गदर्शिका यह है: आप जो परीक्षण कर रहे हैं वह आपके कोड का सार्वजनिक इंटरफ़ेस है जिस तरह से सिस्टम के अन्य भागों द्वारा इसका उपयोग करने का इरादा है।

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

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

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


मैं वही जोड़ने जा रहा था: आपी बनाइए, आपी को परखिए, बाहर से।
क्रिस्टोफर महान

2

टीडीडी और यूनिट परीक्षण, एक पूरे के रूप में कार्यक्रम के लिए अच्छा है, और न केवल इकाई परीक्षणों के लिए। इसका कारण यह है क्योंकि यह मस्तिष्क के लिए अच्छा है।

यह एक विशिष्ट ActionScript फ्रेमवर्क के बारे में एक प्रस्तुति है जिसका नाम RobotLegs है। हालाँकि यदि आप पहले 10 स्लाइड्स के माध्यम से फ्लिप करते हैं, तो यह मस्तिष्क के बारे में अच्छे हिस्सों को प्राप्त करना शुरू कर देता है।

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


1

किसी अनुप्रयोग की सबसे छोटी पृथक्करण इकाई का परीक्षण करना

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

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

अंततः परीक्षण करने के लिए कोई जादू की गोली नहीं है, आपको अपने सीमित संसाधनों के संसाधनों को लागू करने के लिए कितना और किस दाने के बारे में समझदार निर्णय लेना है। उपकरण-आधारित दृष्टिकोण जो ऑटो - आपके लिए स्टब्स बनाता है, ऐसा नहीं करता है, यह एक कुंद बल दृष्टिकोण है।

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

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


0

आप भाषा डिजाइन में ट्रेडऑफ़ के बारे में अच्छे अहसास तक पहुँच चुके हैं। C ++ में कुछ मुख्य डिज़ाइन निर्णय (स्थिर फ़ंक्शन कॉल तंत्र के साथ मिश्रित वर्चुअल फ़ंक्शन तंत्र) TDD को कठिन बनाते हैं। भाषा वास्तव में समर्थन नहीं करती है जो आपको इसे आसान बनाने की आवश्यकता है। C ++ लिखना आसान है जो इकाई परीक्षण के लिए असंभव है।

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.