क्या यह जावा 8 कोड के लिए सशर्त कवरेज को मापने के लिए समझ में आता है?


19

मैं सोच रहा हूं कि क्या जावा के लिए मौजूदा उपकरणों द्वारा सशर्त कोड कवरेज को मापना अप्रचलित नहीं है क्योंकि जावा 8 ऊपर आया था। जावा 8 के साथ Optionalऔर Streamहम अक्सर कोड शाखाओं / छोरों से बच सकते हैं, जिससे सभी संभव विभाजन भागों का परीक्षण किए बिना बहुत अधिक सशर्त कवरेज प्राप्त करना आसान हो जाता है। आइए पुराने जावा कोड की जावा 8 कोड से तुलना करें:

जावा 8 से पहले:

public String getName(User user) {
    if (user != null) {
        if (user.getName() != null) {
            return user.getName();
        }
    }
    return "unknown";
}

उपरोक्त विधि में 3 संभावित निष्पादन पथ हैं। 100% सशर्त कवरेज प्राप्त करने के लिए हमें 3 यूनिट परीक्षण बनाने की आवश्यकता है।

जावा 8:

public String getName(User user) {
    return Optional.ofNullable(user)
                   .map(User::getName)
                   .orElse("unknown");
}

इस मामले में, शाखाएं छिपी हुई हैं और हमें 100% कवरेज प्राप्त करने के लिए केवल 1 परीक्षण की आवश्यकता है और इससे कोई फर्क नहीं पड़ता कि हम किस मामले में परीक्षण करेंगे। हालांकि अभी भी वही 3 तार्किक शाखाएं हैं जिन्हें कवर किया जाना चाहिए मुझे विश्वास है। मुझे लगता है कि यह इन दिनों सशर्त कवरेज के आंकड़ों को पूरी तरह से अविश्वसनीय बनाता है।

क्या यह जावा 8 कोड के लिए सशर्त कवरेज को मापने के लिए समझ में आता है? क्या कोई अन्य उपकरण कोड किए गए हैं?


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

3
बेशक उच्च सशर्त कवरेज का मतलब यह नहीं है कि हमारे पास अच्छे परीक्षण हैं, लेकिन मुझे लगता है कि यह बहुत बड़ा फायदा है कि कौन से निष्पादन मार्गों को उजागर किया जाता है और यही सवाल है। सशर्त कवरेज के बिना अनछुए परिदृश्यों को देखना बहुत कठिन है। रास्तों के बारे में: [उपयोगकर्ता: अशक्त], [उपयोगकर्ता: नोटनल, user.name:null], [उपयोगकर्ता: notnull, user.name:notnull]। मुझे क्या याद आ रहा है?
करोल लेवांडोव्स्की

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

1
फिर से, मैं यह नहीं कह रहा हूं कि कवरेज साबित करता है कि मेरा कोड पूरी तरह से परीक्षण किया गया है, लेकिन यह अत्यधिक मूल्यवान उपकरण था जो मुझे दिखा रहा था कि मैंने निश्चित रूप से परीक्षण नहीं किया है। मुझे लगता है कि परीक्षण अनुबंध निष्पादन पथों से अविभाज्य हैं (आपका उदाहरण असाधारण है क्योंकि इसमें निहित भाषा तंत्र शामिल है)। यदि आपने पथ का परीक्षण नहीं किया है, तो आपने पूरी तरह से अनुबंध का परीक्षण नहीं किया है या अनुबंध पूरी तरह से परिभाषित नहीं है।
करोल लेवांडोव्स्की 21

2
मैं अपने पहले वाले बिंदु को दोहराने जा रहा हूं: यह हमेशा मामला होता है, जब तक कि आप अपने आप को केवल मूल भाषा सुविधाओं तक सीमित नहीं करते हैं और कभी भी किसी भी फ़ंक्शन को कॉल नहीं करते हैं जो साधन नहीं है। जिसका अर्थ है कि कोई भी तृतीय-पक्ष पुस्तकालय नहीं है, और एसडीके का कोई उपयोग नहीं है।
kdgregory

जवाबों:


4

क्या कोई उपकरण हैं जो तार्किक शाखाओं को मापते हैं जो जावा 8 में बनाए जा सकते हैं?

मुझे किसी की जानकारी नहीं है। मैंने यह सुनिश्चित करने के लिए कि आपके पास JaCoCo (उर्फ एक्लेम्मा) के माध्यम से कोड चलाने की कोशिश की है, लेकिन यह Optionalसंस्करण में 0 शाखाएं दिखाता है । मुझे इसे अन्यथा कहने के लिए इसे कॉन्फ़िगर करने की किसी भी विधि का पता नहीं है। यदि आपने इसे JDK फ़ाइलों में शामिल करने के लिए कॉन्फ़िगर किया है, तो यह सैद्धांतिक रूप से शाखाएं दिखाएगा Optional, लेकिन मुझे लगता है कि JDK कोड को सत्यापित करना शुरू करना मूर्खतापूर्ण होगा। आपको बस यह मान लेना है कि यह सही है।

मुझे लगता है कि मुख्य मुद्दा, हालांकि, यह महसूस कर रहा है कि जावा 8 से पहले आपके पास जो अतिरिक्त शाखाएं थीं, वे एक अर्थ में कृत्रिम रूप से निर्मित शाखाएं थीं। वे अब जावा 8 में मौजूद नहीं हैं, इसका मतलब है कि अब आपके पास नौकरी के लिए सही उपकरण है (इस मामले में Optional)। प्री-जावा 8 कोड में आपको अतिरिक्त यूनिट टेस्ट लिखना पड़ता था ताकि आपको विश्वास हो सके कि कोड की प्रत्येक शाखा स्वीकार्य तरीके से व्यवहार करती है - और यह कोड के वर्गों में थोड़ा अधिक महत्वपूर्ण हो जाता है जो User/ की तरह तुच्छ नहीं हैं। getNameउदाहरण।

जावा 8 कोड में, आप बजाय JDK में अपना विश्वास रख रहे हैं कि कोड ठीक से काम करता है। जैसा कि, आपको उस Optionalलाइन का इलाज करना चाहिए जैसे कि कोड कवरेज टूल इसका इलाज करते हैं: 0 शाखाओं के साथ 3 लाइनें। वहाँ कोड में अन्य लाइनों और शाखाएं हैं यही कारण है कि नीचे कुछ आप बस से पहले की ओर ध्यान भुगतान नहीं किया है है, लेकिन हर बार जब आप इस्तेमाल किया कुछ एक जैसे है ही अस्तित्व में है ArrayListया HashMap


2
"यही तो वे अब जावा 8 में मौजूद ..." - मैं इसके साथ सहमत नहीं हो सकते, जावा 8 पिछड़े संगत है और ifऔर nullअभी भी भाषा के हिस्से हैं ;-) यह अभी भी पुराने तरीके में और पारित करने के लिए लिखने के कोड के लिए संभव है nullउपयोगकर्ता या उपयोगकर्ता nullनाम के साथ । आपके परीक्षणों को सिर्फ यह साबित करना चाहिए कि अनुबंध कैसे पूरा किया जाता है, भले ही यह विधि लागू क्यों न हो। मुद्दा यह है कि आपके पास पूरी तरह से परीक्षण किए गए अनुबंध को बताने के लिए कोई उपकरण नहीं है।
करोल लेवांडोव्स्की

1
@KarolLewandowski मुझे लगता है कि शाज़ जो कह रहा है वह यह है कि अगर आपको भरोसा है कि Optional(और संबंधित तरीके) कैसे काम करते हैं, तो आपको अब उनका परीक्षण नहीं करना होगा। उसी तरह से नहीं जैसे आपने परीक्षण किया है if-else: हर ifएक संभावित खदान था। Optionalऔर इसी तरह के कार्यात्मक मुहावरे पहले से ही कोडित हैं और आपको यात्रा न करने की गारंटी देते हैं, इसलिए अनिवार्य रूप से एक "शाखा" है जो गायब हो गई।
एंड्रेस एफ।

1
@AndresF। मुझे नहीं लगता कि करोल सुझाव दे रहा है कि हम परीक्षण करें Optional। जैसा उन्होंने कहा, तार्किक रूप से हमें अभी भी परीक्षण करना चाहिए कि getName()जिस तरह से हम इसके कार्यान्वयन की परवाह किए बिना विभिन्न संभावित आदानों को संभालते हैं। यह पूर्व-JDK8 के तरीके में मदद करने वाले कोड कवरेज टूलींग के बिना इसे निर्धारित करना कठिन है।
माइक पार्टरिज

1
@ माइकपार्ट्रिज हां, लेकिन मुद्दा यह है कि यह शाखा कवरेज के माध्यम से नहीं किया गया है। लिखते समय शाखा कवरेज की आवश्यकता होती है if-elseक्योंकि उनमें से प्रत्येक निर्माण पूरी तरह से तदर्थ है। इसके विपरीत, Optional, orElse, map, आदि, सब पहले से ही जांच की जाती है। जब आप अधिक शक्तिशाली मुहावरों का उपयोग करते हैं, तो शाखाएं "गायब" हो जाती हैं।
एंड्रेस एफ।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.