2012-08-17 21 views
16

यह कोडक्या हमें यूनिट परीक्षण लॉगिंग करना चाहिए?

public class A { 

private static final Log LOG = LogFactory.getLog(A.class); 

और उपयोग

 } catch (Exception e) { 
      LOG.error(e.getMessage(), e); 
      throw e; 
     } 

में प्रवेश कार्यक्षमता को देखने के लिए हमेशा की तरह है, लेकिन मैं इस तरह के कोड के लिए भी एक इकाई परीक्षण कभी नहीं देखा था।

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

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

उत्तर

9

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

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

+0

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

+0

यदि आपके पास लॉग ऑब्जेक्ट को तुरंत चालू करने वाले कोड पर कोई नियंत्रण नहीं है, तो व्यवहार का परीक्षण करना मुश्किल है, क्योंकि आप नकली लॉग का उपयोग नहीं कर सकते हैं। आप इसे वास्तविक लॉग ऑब्जेक्ट से लॉग इन कर सकते हैं, फिर जांचें कि एक संदेश लॉग किया गया था। हालांकि, स्वचालित करना मुश्किल है! –

+0

नहीं, मैं आपसे सहमत हूं कि लॉगिंग कोड का परीक्षण किया जाना चाहिए। इसका मतलब है कि हमारे पास LOG के लिए सेटटर होना चाहिए, इसलिए परीक्षणों में नकली लॉग पास करना संभव होगा, लेकिन वसंत सेवाओं के मामले में क्या करना है। मैं 2 संभावित तरीकों के बारे में सोच रहा हूं: 1) एक सेटटर है लेकिन केवल परीक्षणों में कॉल करें (वसंत के माध्यम से लॉगजर इंजेक्शन के बाद से इस तरह की दृश्यता को सीमित करना मुश्किल हो सकता है), लेकिन इस मामले में मुश्किल है उचित लॉगर तुरंत चालू करें। –

2

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

+14

मैं परीक्षण नहीं कर रहा हूं कि लॉगिंग लाइब्रेरी कैसे काम करती है, मेरा इरादा यह जांचना है कि मेरा कोड लॉगिंग कर रहा है। –

1

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

बेशक आप हर loging घटना का परीक्षण नहीं करना चाहती है, और मुझे लगता है कि ज्यादातर केवल त्रुटि (और उन सभी नहीं) परीक्षण किया जाना चाहिए लगता होगा।

ऐसे SLF4j के रूप में आधुनिक प्रवेश चौखटे आप बस उस स्मृति में के लिए घटनाओं को संग्रहीत करता है और कहा कि बाद में के खिलाफ कहा जा सकता एक कस्टम हैंडलर इंजेक्षन कर सकते हैं

SLF4JTesting: लॉगिंग विन्यास का कोई संशोधन की आवश्यकता है, लेकिन एक प्रवेश कारखाने जो संशोधित कोड को जन्म दे सकता इंजेक्षन करने की आवश्यकता है

वहाँ उनमें से दो कि मेरे दिमाग में अभी आ रहे हैं।

SLF4J Test: slf4jtesting के रूप में के रूप में शक्तिशाली नहीं है और विकसित करने के लिए नहीं है, लेकिन मौजूदा कोड के साथ अच्छी तरह से काम लगता है। परीक्षण के लिए लॉगर कॉन्फ़िगरेशन के अलावा कोई संशोधन नहीं।

एसएलएफ 4 जे टेस्ट का उपयोग करते समय, दावे काफी सख्त हैं और समानता के लिए पूरी घटना की जांच करें। एक कस्टम मिलान शायद इस तरह के एक मामले में दिलचस्प बात यह है:

public static Matcher<LoggingEvent> errorMessageContains(final String s) { 
    return new TypeSafeMatcher<LoggingEvent>() { 
     @Override 
     public void describeTo(final Description description) { 
      description.appendText(" type " + Level.ERROR + " should contain ") 
        .appendValue(s); 
     } 

     @Override 
     protected void describeMismatchSafely(final LoggingEvent item, final Description mismatchDescription) { 
      mismatchDescription.appendText(" was type ").appendValue(l) 
        .appendText(" message ").appendValue(item.getMessage()); 
     } 

     @Override 
     protected boolean matchesSafely(final LoggingEvent item) { 
      return item.getLevel().equals(Level.ERROR) 
        && item.getMessage().contains(s); 
     } 
    }; 
} 

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

0

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

अधिक: https://ardalis.com/logging-and-monitoring-are-requirements

0
वहाँ

एक और तरीका है: आप LogFactory नकली कर सकते हैं! उदाहरण के लिए:

import junit.framework.Assert; 
import mockit.Mock; 
import mockit.MockUp; 
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.junit.Test; 

public class XXXTest { 
    class MyLog implements Log { 
     public static final String INFO = "info"; 

     private String logLevel; 
     private Object logContent; 

     public String getLogLevel() { 
      return logLevel; 
     } 

     public Object getLogContent() { 
      return logContent; 
     } 

     @Override 
     public void info(Object o) { 
      logLevel = "info"; 
      logContent = o; 
     } 

     //Implement other methods 
    } 

    @Test 
    public void testXXXFunction() { 
     final MyLog log = new MyLog(); 
     new MockUp<LogFactory>() { 
      @Mock 
      public Log getLog(String name) { 
       return log; 
      } 
     }; 

     //invoke function and log by MyLog 
     FunctionToBeTest.invoke(); 
     Assert.assertEquals("expected log text", log.getLogContent()); 
    } 
} 

शुभकामनाएँ!

संबंधित मुद्दे