क्या हम अपने गेटर्स और सेटर के लिए टेस्ट लिखना चाहते हैं या यह ओवरकिल है?
क्या हम अपने गेटर्स और सेटर के लिए टेस्ट लिखना चाहते हैं या यह ओवरकिल है?
जवाबों:
मैं कहूंगा कि नहीं।
@Will ने कहा कि आपको 100% कोड कवरेज के लिए लक्ष्य बनाना चाहिए, लेकिन मेरी राय में यह एक खतरनाक व्याकुलता है। आप इकाई परीक्षण लिख सकते हैं जिसमें 100% कवरेज है, और फिर भी बिल्कुल कुछ भी परीक्षण नहीं किया है।
इकाई परीक्षण आपके कोड के व्यवहार को एक अभिव्यंजक और सार्थक तरीके से जांचने के लिए हैं, और गेटर्स / सेटर केवल एक अंत का साधन हैं। यदि आप परीक्षण "वास्तविक" कार्यक्षमता का परीक्षण करने के अपने लक्ष्य को प्राप्त करने के लिए गेटर्स / सेटर का उपयोग करते हैं, तो यह काफी अच्छा है।
यदि, दूसरी ओर, आपके गेटर्स और सेटर्स सिर्फ पाने और सेट करने से अधिक करते हैं (यानी वे ठीक से जटिल तरीके हैं), तो हाँ, उन्हें परीक्षण किया जाना चाहिए। लेकिन सिर्फ एक गेट्टर या सेटर का परीक्षण करने के लिए एक यूनिट टेस्ट केस न लिखें , यह समय की बर्बादी है।
रॉय ओशेरोव अपनी प्रसिद्ध पुस्तक 'द आर्ट ऑफ़ यूनिट टेस्टिंग' में कहते हैं:
गुण (जावा में गेटर्स / सेटरर्स) कोड के अच्छे उदाहरण हैं जिनमें आमतौर पर कोई तर्क नहीं होता है, और परीक्षण की आवश्यकता नहीं होती है। लेकिन ध्यान रखें: एक बार जब आप संपत्ति के अंदर किसी भी चेक को जोड़ते हैं, तो आप यह सुनिश्चित करना चाहेंगे कि तर्क का परीक्षण किया जा रहा है।
नोट : इस उत्तर से अपवित्रता बनी रहती है, हालांकि यह एक बुरी सलाह है। यह समझने के लिए कि नीचे की छोटी बहन पर एक नज़र क्यों डालें।
विवादास्पद ठीक है, लेकिन मेरा तर्क है कि जो कोई भी इस प्रश्न का उत्तर 'नहीं' दे रहा है, उसे TDD की एक मूल अवधारणा याद आ रही है।
मेरे लिए, यदि आप टीडीडी का अनुसरण करते हैं, तो उत्तर एक शानदार हां है । यदि आप नहीं हैं तो कोई जवाब नहीं है।
TDD को अक्सर आपको मुख्य लाभ के रूप में उद्धृत किया जाता है।
प्रोग्रामर के रूप में, यह बहुत ही महत्वपूर्ण है कि विशेषताओं के बारे में सोचें और कुछ ओवरहेड के रूप में गेटर्स और सेटर।
लेकिन विशेषताएँ एक कार्यान्वयन विवरण हैं, जबकि बसने वाले और गेटर्स एक संविदात्मक इंटरफ़ेस हैं जो वास्तव में कार्यक्रमों को काम करते हैं।
किसी वस्तु पर वर्तनी के लिए यह अधिक महत्वपूर्ण है:
अपने ग्राहकों को इसकी स्थिति बदलने की अनुमति दें
तथा
अपने ग्राहकों को इसकी स्थिति के बारे में बताने की अनुमति दें
फिर यह राज्य वास्तव में कैसे संग्रहीत किया जाता है (जिसके लिए एक विशेषता सबसे आम है, लेकिन एकमात्र तरीका नहीं है)।
एक परीक्षण जैसे
(The Painter class) should store the provided colour
TDD के प्रलेखन भाग के लिए महत्वपूर्ण है ।
तथ्य यह है कि अंतिम कार्यान्वयन तुच्छ (विशेषता) है और जब आप परीक्षण लिखते हैं तो आपके लिए कोई रक्षा लाभ नहीं होना चाहिए।
सिस्टम डेवलपमेंट वर्ल्ड में प्रमुख समस्याओं में से एक राउंड-ट्रिप इंजीनियरिंग 1 की कमी है - एक सिस्टम की डेवलपमेंट प्रक्रिया असंतुष्ट उप-प्रक्रियाओं में खंडित हो जाती है, जिसमें से (प्रलेखन, कोड) अक्सर असंगत होते हैं।
1 ब्रॉडी, माइकल एल। "जॉन मायलोपोलोस: वैचारिक मॉडलिंग के सिलाई बीज।" वैचारिक मॉडलिंग: नींव और अनुप्रयोग। स्प्रिंगर बर्लिन हीडलबर्ग, 2009. 1-9।
यह टीडीडी का प्रलेखन हिस्सा है जो यह सुनिश्चित करता है कि सिस्टम और इसके कोड के विनिर्देश हमेशा सुसंगत हैं।
टीडीडी के भीतर हम पहले असफलता परीक्षण लिखते हैं, उसके बाद ही कोड लिखते हैं जो उन्हें पास करता है।
उच्च-स्तरीय BDD के भीतर, हम पहले परिदृश्य लिखते हैं, फिर उन्हें पास करते हैं।
आपको बसने और पाने वाले को बाहर क्यों करना चाहिए?
सिद्धांत रूप में, टीडीडी के भीतर एक व्यक्ति के लिए परीक्षण लिखना पूरी तरह से संभव है, और दूसरा वह कोड लागू करने के लिए जो इसे पास करता है।
इसलिए खुद से पूछें:
क्या क्लास लिखने वाले व्यक्ति को गेटर्स और सेटर का उल्लेख करना चाहिए।
चूँकि गेटर्स और सेटर एक वर्ग के लिए एक सार्वजनिक इंटरफ़ेस है, इसलिए उत्तर स्पष्ट रूप से हाँ है , या किसी वस्तु की स्थिति को सेट या क्वेरी करने का कोई तरीका नहीं होगा। हालांकि , ऐसा करने का तरीका जरूरी नहीं है कि अलगाव में प्रत्येक विधि का परीक्षण किया जाए, अधिक के लिए मेरा अन्य उत्तर देखें ।
जाहिर है, यदि आप पहले कोड लिखते हैं, तो उत्तर इतना स्पष्ट नहीं हो सकता है।
tl; dr: हाँ आपको चाहिए , और OpenPojo के साथ यह तुच्छ है।
आपको अपने गेटर्स और सेटरों में कुछ सत्यापन करना चाहिए ताकि आपको इसका परीक्षण करना चाहिए। उदाहरण के लिए, setMom(Person p)
किसी को भी अपनी माँ के रूप में अपने से छोटे लोगों को स्थापित करने की अनुमति नहीं देनी चाहिए।
यहां तक कि अगर आप उस में से कोई भी काम नहीं कर रहे हैं, तो आप भविष्य में हैं, तो यह प्रतिगमन विश्लेषण के लिए अच्छा होगा। यदि आप माताओं को स्थापित करने की अनुमति देना चाहते हैं, null
तो इसके लिए एक परीक्षण होना चाहिए कि किसी को बाद में इसे बदलना चाहिए, इससे आपकी धारणाओं को बल मिलेगा।
एक सामान्य बग वह void setFoo( Object foo ){ foo = foo; }
जगह है जहाँ यह होना चाहिए void setFoo( Object foo ){ this.foo = foo; }
। (पहले मामले में foo
है कि करने के लिए लिखा जा रहा है है पैरामीटर नहींfoo
पर क्षेत्र वस्तु )।
यदि आप एक सरणी या संग्रह लौटा रहे हैं, तो आपको परीक्षण करना चाहिए कि क्या गेट्टर लौटने से पहले सेटर में पारित डेटा की रक्षात्मक प्रतियों का प्रदर्शन करने वाला है या नहीं ।
अन्यथा, यदि आपके पास सबसे बुनियादी बसने वाले / गेटर्स हैं, तो यूनिट-परीक्षण उन्हें संभवतः प्रति-ऑब्जेक्ट पर लगभग 10 मिनट जोड़ देगा, तो नुकसान क्या है? यदि आप व्यवहार जोड़ते हैं तो आपके पास पहले से ही एक कंकाल परीक्षण है और आपको यह प्रतिगमन परीक्षण मुफ्त में मिलता है। यदि आप जावा का उपयोग कर रहे हैं, तो आपके पास कोई बहाना नहीं है क्योंकि OpenPojo है । नियमों का एक मौजूदा सेट है जिसे आप सक्षम कर सकते हैं और फिर अपनी पूरी परियोजना को स्कैन करके सुनिश्चित कर सकते हैं कि वे आपके कोड के भीतर लगातार लागू होते हैं।
से उनकी उदाहरणों से :
final PojoValidator pojoValidator = new PojoValidator();
//create rules
pojoValidator.addRule( new NoPublicFieldsRule () );
pojoValidator.addRule( new NoPrimitivesRule () );
pojoValidator.addRule( new GetterMustExistRule () );
pojoValidator.addRule( new SetterMustExistRule () );
//create testers
pojoValidator.addTester( new DefaultValuesNullTester () );
pojoValidator.addTester( new SetterTester () );
pojoValidator.addTester( new GetterTester () );
//test all the classes
for( PojoClass pojoClass : PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() ) )
pojoValidator.runValidation( pojoClass );
मुझे विस्तृत करने की अनुमति दें:
विरासत कोड 1 के साथ प्रभावी ढंग से काम करने से :
शब्द इकाई परीक्षण सॉफ्टवेयर विकास में एक लंबा इतिहास रहा है। यूनिट परीक्षणों की अधिकांश धारणाओं के लिए सामान्य यह विचार है कि वे सॉफ्टवेयर के व्यक्तिगत घटकों के अलगाव में परीक्षण हैं। घटक क्या हैं? परिभाषा बदलती है, लेकिन इकाई परीक्षण में, हम आमतौर पर एक प्रणाली के सबसे परमाणु व्यवहार इकाइयों से चिंतित हैं। प्रक्रियात्मक कोड में, इकाइयां अक्सर फ़ंक्शन होती हैं। ऑब्जेक्ट ओरिएंटेड कोड में, इकाइयां कक्षाएं हैं।
ध्यान दें कि ओओपी के साथ, जहां आपको गेटर्स और सेटर मिलते हैं, यूनिट क्लास है , जरूरी नहीं कि व्यक्तिगत तरीके ।
सभी आवश्यकताएं और परीक्षण होरे तर्क के रूप का अनुसरण करते हैं :
{P} C {Q}
कहाँ पे:
{P}
पूर्व शर्त है ( दी गई है )C
ट्रिगर स्थिति है ( जब ){Q}
पोस्टकंडिशन ( तब )फिर अधिकतम आता है:
परीक्षण व्यवहार, कार्यान्वयन नहीं
इसका मतलब यह है कि आपको परीक्षण नहीं करना चाहिए कि C
पोस्ट-स्थिति कैसे प्राप्त होती है, आपको यह जांचना चाहिए कि {Q}
इसका परिणाम क्या है C
।
जब यह OOP की बात आती है, C
तो एक वर्ग है। इसलिए आपको आंतरिक प्रभावों, केवल बाहरी प्रभावों का परीक्षण नहीं करना चाहिए।
गेटर्स और सेटर्स में कुछ तर्क शामिल हो सकते हैं, लेकिन इतने लंबे समय तक इस तर्क का बाहरी प्रभाव नहीं होता है - जिससे वे बीन एक्सेसर्स 2 बना सकते हैं ) एक परीक्षण को ऑब्जेक्ट के अंदर देखना होगा और इसके द्वारा न केवल एनकैप्सुलेशन का उल्लंघन करना होगा, बल्कि कार्यान्वयन के लिए भी परीक्षण करना होगा।
तो आपको बीन गेटर्स का परीक्षण नहीं करना चाहिए और अलगाव में बसना चाहिए। ये गलत है:
Describe 'LineItem class'
Describe 'setVAT()'
it 'should store the VAT rate'
lineItem = new LineItem()
lineItem.setVAT( 0.5 )
expect( lineItem.vat ).toBe( 0.5 )
यद्यपि यदि setVAT
कोई अपवाद फेंकता है, तो एक बाहरी परीक्षण उचित होगा क्योंकि अब बाहरी प्रभाव है।
किसी वस्तु की आंतरिक स्थिति को बदलने का वस्तुतः कोई मतलब नहीं है यदि इस तरह के परिवर्तन का बाहर पर कोई प्रभाव नहीं पड़ता है, भले ही ऐसा प्रभाव बाद में आए।
तो बसने और पाने वालों के लिए एक परीक्षण इन तरीकों के बाहरी प्रभाव से संबंधित होना चाहिए, आंतरिक लोगों से नहीं।
उदाहरण के लिए:
Describe 'LineItem class'
Describe 'getGross()'
it 'should return the net time the VAT'
lineItem = new LineItem()
lineItem.setNet( 100 )
lineItem.setVAT( 0.5 )
expect( lineItem.getGross() ).toBe( 150 )
आप खुद सोच सकते हैं:
एक क्षण रुकें, हम परीक्षण कर रहे हैं
getGross()
यहाँ नहींsetVAT()
।
लेकिन अगर setVAT()
उस परीक्षण में खराबी सभी समान विफल हो जाना चाहिए।
1 पंख, एम।, 2004। विरासत कोड के साथ प्रभावी ढंग से काम करना। अप्रेंटिस हॉल प्रोफेशनल।
2 मार्टिन, आरसी, 2009. स्वच्छ कोड: फुर्तीली सॉफ्टवेयर शिल्प कौशल की एक पुस्तिका। पियर्सन शिक्षा।
प्रॉपर्टीज के उचित कारण होते हुए भी, एक सामान्य ऑब्जेक्ट ओरिएंटेड डिज़ाइन विश्वास है जो प्रॉपर्टीज़ के माध्यम से सदस्य राज्य को उजागर करना बुरा डिज़ाइन है। ओपन बंद सिद्धांत पर रॉबर्ट मार्टिन का लेख इस पर विस्तार से कहता है कि गुण युग्मन को प्रोत्साहित करते हैं और इसलिए संशोधन से एक वर्ग को बंद करने की क्षमता को सीमित करते हैं - यदि आप संपत्ति को संशोधित करते हैं, तो वर्ग के सभी उपभोक्ताओं को भी बदलना होगा। वह योग्य है कि सदस्य चर को उजागर करना जरूरी नहीं कि खराब डिजाइन है, यह सिर्फ खराब शैली हो सकती है। हालांकि, यदि गुण केवल-पढ़ने के लिए हैं, तो दुरुपयोग और दुष्प्रभावों की संभावना कम है।
यूनिट परीक्षण के लिए मेरे द्वारा प्रदान किया जाने वाला सबसे अच्छा तरीका (और यह अजीब लग सकता है) संभव संरक्षित या आंतरिक के रूप में कई गुण बनाने के लिए है। यह गेटर्स और सेटर के लिए मूर्खतापूर्ण परीक्षण को हतोत्साहित करते हुए युग्मन को रोक देगा।
ऐसे स्पष्ट कारण हैं जहां पढ़ने / लिखने के गुणों का उपयोग किया जाना चाहिए, जैसे कि ViewModel गुण जो इनपुट फ़ील्ड के लिए बाध्य हैं, आदि।
व्यावहारिक रूप से, यूनिट परीक्षणों को सार्वजनिक तरीकों के माध्यम से कार्यक्षमता को चलाना चाहिए। यदि आपके द्वारा परीक्षण किया जा रहा कोड उन गुणों का उपयोग करने के लिए होता है, तो आपको मुफ्त में कोड-कवरेज मिलता है। अगर यह पता चलता है कि इन गुणों को कभी भी कोड-कवरेज से उजागर नहीं किया जाता है, तो इसकी बहुत मजबूत संभावना है:
यदि आप गेटर्स और सेटर के लिए परीक्षण लिखते हैं, तो आपको कवरेज की झूठी भावना मिलती है और यह निर्धारित नहीं कर पाएगा कि क्या गुण वास्तव में कार्यात्मक व्यवहार द्वारा उपयोग किए जाते हैं।
यदि गॉटर और / या सेटर की साइक्लोमैटिक जटिलता 1 है (जो वे आमतौर पर हैं), तो उत्तर नहीं है, आपको नहीं करना चाहिए।
इसलिए जब तक आपके पास एक SLA नहीं है जिसके लिए 100% कोड-कवरेज की आवश्यकता होती है, परेशान न हों और अपने सॉफ़्टवेयर के महत्वपूर्ण पहलू का परीक्षण करने पर ध्यान केंद्रित करें।
PS याद रखें कि गेटर्स और सेटर्स को अलग-अलग करें, यहां तक कि C # जैसी भाषाओं में भी, जहां गुण एक ही चीज की तरह लग सकते हैं। सेटर की जटिलता गेटटर से अधिक हो सकती है, और इस तरह एक इकाई-परीक्षण को मान्य करता है।
एक विनोदी, अभी तक बुद्धिमान ले: टेस्टीवस का रास्ता
"आज आप जो भी परीक्षा लिखें"
यदि आप एक अनुभवी परीक्षक हैं और यह एक छोटा प्रोजेक्ट है, तो परीक्षण गेटर्स / सेटर ओवरकिल हो सकते हैं। हालाँकि, अगर आप अभी सीखना शुरू कर रहे हैं कि यूनिट टेस्ट कैसे होगा या इन गेटर्स / सेटर में लॉजिक हो सकता है (जैसे @ आर्टबी का setMom()
उदाहरण) तो टेस्ट लिखना अच्छा रहेगा।
यह वास्तव में मेरी टीम और आई। के बीच का हालिया विषय रहा है। हमने 80% कोड कवरेज के लिए शूट किया है। मेरी टीम का तर्क है कि गेटर्स और सेटर्स ऑटो कार्यान्वित होते हैं, और कंपाइलर पर्दे के पीछे कुछ बुनियादी कोड उत्पन्न कर रहा है। इस मामले में, दिया गया कोड गैर-घुसपैठ है, यह वास्तव में आपके लिए कंपाइलर बनाता कोड का परीक्षण करने के लिए कोई मतलब नहीं है। हमारे पास async विधियों के बारे में भी यह चर्चा थी और उस मामले में संकलक दृश्यों के पीछे कोड का एक पूरा गुच्छा उत्पन्न करता है। यह एक अलग मामला है और कुछ हम करते हैं परीक्षण। लंबे समय तक उत्तर दें, इसे अपनी टीम के साथ लाएं और अपने आप के लिए तय करें कि क्या इसके परीक्षण के लायक है।
इसके अलावा, यदि आप हमारी तरह कोड कवरेज रिपोर्ट का उपयोग कर रहे हैं, तो एक चीज जो आप कर सकते हैं वह है [ExcludeFromCodeCoverage] विशेषता। हमारा समाधान यह है कि मॉडल के लिए इसका उपयोग किया जाए, जिसमें केवल गेटर्स और सेटर का उपयोग करने या संपत्ति पर ही गुण हों। इस तरह यह कोड कवरेज रिपोर्ट चलने पर कुल कोड कवरेज% को प्रभावित नहीं करेगा, यह मानते हुए कि आप अपने कोड कवरेज कवरेज की गणना करने के लिए क्या उपयोग कर रहे हैं। खुश परीक्षण!
मेरी राय में कोड कवरेज यह देखने का एक अच्छा तरीका है कि क्या आपने कोई कार्यक्षमता याद की है जिसे आपको कवर करना चाहिए।
जब आप मैन्युअल रूप से सुंदर रंग से कवरेज का निरीक्षण करते हैं तो यह तर्क दिया जा सकता है कि सादे गेटर्स और सेटरों को परीक्षण करने की आवश्यकता नहीं है (हालांकि मैं हमेशा करता हूं)।
जब आप केवल अपनी परियोजना पर कोड कवरेज प्रतिशत की जांच करते हैं, तो 80% की तरह एक परीक्षण कवरेज प्रतिशत अर्थहीन होता है। आप सभी तार्किक भागों का परीक्षण कर सकते हैं और कुछ महत्वपूर्ण भागों को भूल सकते हैं। इस मामले में केवल 100% का मतलब है कि आपने सभी महत्वपूर्ण कोड (और साथ ही सभी गैर-तार्किक कोड) का परीक्षण किया है। जैसे ही यह 99.9% है आप जानते हैं कि कुछ भूल गए हैं।
वैसे: कोड कवरेज यह देखने के लिए अंतिम जांच है कि क्या आपने पूरी तरह से (इकाई) एक वर्ग का परीक्षण किया है। लेकिन 100% कोड कवरेज जरूरी नहीं है कि आपने वास्तव में वर्ग की सभी कार्यक्षमता का परीक्षण किया है। इसलिए इकाई परीक्षणों को हमेशा कक्षा के तर्क के बाद लागू किया जाना चाहिए। अंत में आप यह देखने के लिए कवरेज चलाते हैं कि क्या आप कुछ भी भूल गए हैं। जब आपने इसे सही किया, तो आपने पहली बार 100% मारा।
एक और बात: हाल ही में नीदरलैंड में एक बड़े बैंक में काम करते समय मैंने देखा कि सोनार ने 100% कोड कवरेज का संकेत दिया। हालांकि, मुझे पता था कि कुछ गायब था। प्रति फ़ाइल कोड कवरेज प्रतिशतों का निरीक्षण करना यह एक फ़ाइल को कम प्रतिशत पर इंगित करता है। संपूर्ण कोड आधार प्रतिशत इतना बड़ा था कि एक फ़ाइल ने प्रतिशत को 99.9% के रूप में प्रदर्शित नहीं किया। तो आप इसके लिए बाहर देखना चाहते हो सकता है ...
मैंने JUnit कोड में प्राप्त कवरेज का थोड़ा विश्लेषण किया ।
अनलॉक्ड कोड की एक श्रेणी "परीक्षण के लिए बहुत सरल" है । इसमें सरल गेटर्स और सेटर शामिल हैं, जिन्हें JUnit के डेवलपर्स परीक्षण नहीं करते हैं ।
दूसरी ओर, JUnit के पास ऐसी कोई भी (नॉन-डिप्रेक्टेड) विधि नहीं है जो किसी भी परीक्षण द्वारा कवर नहीं की गई 3 पंक्तियों से अधिक लंबी हो।
मैं कहूंगा: गेट्स / सेटर के तरीकों में हाँ त्रुटियां चुपचाप अंदर घुस सकती हैं और कुछ बदसूरत कीड़े पैदा कर सकती हैं।
मैंने इसे और कुछ अन्य परीक्षणों को आसान बनाने के लिए एक परिवाद लिखा है। आपके JUnit परीक्षणों में केवल एक चीज आपको लिखनी है:
assertTrue(executor.execute(Example.class, Arrays.asList( new DefensiveCopyingCheck(),
new EmptyCollectionCheck(), new GetterIsSetterCheck(),
new HashcodeAndEqualsCheck(), new PublicVariableCheck())));
हां, खासकर यदि आइटम प्राप्त करने के लिए एक अमूर्त वर्ग से उपवर्ग की एक वस्तु है। आपकी आईडीई आपको सचेत कर सकती है या नहीं कर सकती है कि एक निश्चित संपत्ति को आरम्भ नहीं किया गया है।
और फिर कुछ स्पष्ट रूप से असंबंधित परीक्षण दुर्घटनाओं के साथ ए NullPointerException
और यह आपको यह पता लगाने में समय लगता है कि एक प्राप्य संपत्ति वास्तव में पहले स्थान पर नहीं है।
हालांकि वह अभी भी उत्पादन में समस्या का पता लगाने के रूप में बुरा नहीं होगा।
यह सुनिश्चित करना एक अच्छा विचार हो सकता है कि आपके सभी अमूर्त वर्गों में कंस्ट्रक्टर हैं। यदि नहीं, तो एक गॉटर का परीक्षण आपको वहां एक समस्या के लिए सचेत कर सकता है।
प्राइमरी के गेटर्स और सेटर के लिए, सवाल यह हो सकता है: क्या मैं अपने प्रोग्राम का परीक्षण कर रहा हूं या क्या मैं जेवीएम या सीएलआर का परीक्षण कर रहा हूं? सामान्यतया, JVM को जांचने की आवश्यकता नहीं है।