unit testing - क्या मुझे निजी तरीकों या केवल सार्वजनिक लोगों का परीक्षण करना चाहिए?




unit-testing language-agnostic (18)

जैसा कि ऊपर उद्धृत किया गया है, "यदि आप अपने निजी तरीकों का परीक्षण नहीं करते हैं, तो आप कैसे जानते हैं कि वे तोड़ नहीं पाएंगे?"

यह एक बड़ा मुद्दा है। यूनिट परीक्षणों के बड़े बिंदुओं में से एक यह जानना है कि कहां, कब, और कैसे कुछ ASAP तोड़ दिया। इस प्रकार विकास और क्यूए प्रयास की एक महत्वपूर्ण मात्रा में कमी आई है। यदि परीक्षण किया गया सब कुछ जनता है, तो आपके पास कक्षा के आंतरिक लोगों का ईमानदार कवरेज और चित्रण नहीं है।

मैंने पाया है कि ऐसा करने के सर्वोत्तम तरीकों में से एक बस परियोजना के परीक्षण संदर्भ को जोड़ता है और परीक्षणों को निजी तरीकों से समानांतर कक्षा में डाल देता है। उचित निर्माण तर्क में रखें ताकि परीक्षण अंतिम परियोजना में नहीं बन सकें।

फिर आपके पास इन तरीकों का परीक्षण करने के सभी लाभ हैं और आप मिनटों या घंटों के विपरीत सेकंड में समस्याएं पा सकते हैं।

तो संक्षेप में, हाँ, यूनिट आपके निजी तरीकों का परीक्षण करें।

मैंने इस पोस्ट को निजी तरीकों का परीक्षण करने के तरीके के बारे में पढ़ा है। मैं आमतौर पर उनका परीक्षण नहीं करता, क्योंकि मैंने हमेशा सोचा था कि केवल सार्वजनिक विधियों का परीक्षण करना तेज़ है जिसे ऑब्जेक्ट के बाहर से बुलाया जाएगा। क्या आप निजी तरीकों का परीक्षण करते हैं? क्या मुझे हमेशा उनका परीक्षण करना चाहिए?


परीक्षण का उद्देश्य क्या है?

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

व्यक्तिगत रूप से, कोड परीक्षणों के लिए मेरा प्राथमिक उपयोग यह सुनिश्चित करना है कि भविष्य में कोड परिवर्तन समस्याएं पैदा न करें और यदि वे ऐसा करते हैं तो मेरे डीबगिंग प्रयासों की सहायता करें। मुझे लगता है कि सार्वजनिक तरीकों के रूप में पूरी तरह से निजी तरीकों का परीक्षण (यदि ऐसा नहीं है!) उस उद्देश्य को आगे बढ़ाता है।

विचार करें: आपके पास सार्वजनिक विधि ए है जो निजी विधि बी को कॉल करता है बी और बी दोनों विधि सी का उपयोग करते हैं। सी बदल जाता है (शायद आपके द्वारा, एक विक्रेता द्वारा), जिससे ए को अपने परीक्षणों में विफल होना शुरू हो जाता है। बी के लिए भी परीक्षण करना उपयोगी नहीं होगा, भले ही यह निजी हो, ताकि आप जान सकें कि समस्या ए, सी के उपयोग के सी, या दोनों के उपयोग में है या नहीं?

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


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

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


मैं अपनी पुस्तक प्रोगैटिक यूनिट परीक्षण में डेव थॉमस और एंडी हंट की सलाह का पालन करता हूं:

आम तौर पर, आप परीक्षण के लिए किसी भी encapsulation तोड़ना नहीं चाहते हैं (या जैसे माँ कहती थी, "अपने निजी लोगों का पर्दाफाश न करें!")। अधिकांश समय, आप अपनी सार्वजनिक विधियों का उपयोग करके कक्षा का परीक्षण करने में सक्षम होना चाहिए। यदि निजी या संरक्षित पहुंच के पीछे छिपी हुई महत्वपूर्ण कार्यक्षमता है, तो यह एक चेतावनी संकेत हो सकता है कि बाहर निकलने के लिए संघर्ष करने वाली एक और कक्षा है।

लेकिन कभी-कभी मैं खुद को निजी तरीकों का परीक्षण करने से नहीं रोक सकता क्योंकि यह मुझे आश्वस्तता की भावना देता है कि मैं एक पूरी तरह से मजबूत कार्यक्रम बना रहा हूं।


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

मुझे पता है कि कुछ लोग जवाब दे सकते हैं कि यदि हम उस वस्तु में एक और सार्वजनिक विधि विकसित कर रहे हैं तो इसका परीक्षण किया जाना चाहिए और यह है (निजी विधि परीक्षण के बिना रह सकती है)। लेकिन यह किसी ऑब्जेक्ट के किसी भी सार्वजनिक तरीके के लिए भी सच है: वेब ऐप विकसित करते समय, ऑब्जेक्ट के सभी सार्वजनिक तरीकों को नियंत्रकों के तरीकों से बुलाया जाता है और इसलिए नियंत्रकों के लिए कार्यान्वयन विवरण के रूप में माना जा सकता है।

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

To me the frontier between private and public methods is a psychologic criteria when it comes to tests. Criteria which matters more to me are:

  • is the method called more than once from different places?
  • is the method sophisticated enough to require tests?

मैं थोड़ी देर के लिए इस मुद्दे पर विशेष रूप से टीडीडी में अपना हाथ लगाने की कोशिश कर रहा हूं।

मैं दो पदों पर आया हूं जो मुझे लगता है कि इस समस्या को टीडीडी के मामले में काफी हद तक पर्याप्त है।

  1. agiletips.blogspot.com/2008/11/…
  2. टेस्ट-संचालित विकास परीक्षण नहीं कर रहा है

संक्षेप में:

  • परीक्षण संचालित विकास (डिजाइन) तकनीकों का उपयोग करते समय, निजी विधियों को केवल पहले से ही काम कर रहे और परीक्षण कोड की पुन: फैक्टरिंग प्रक्रिया के दौरान उत्पन्न होना चाहिए।

  • प्रक्रिया की प्रकृति से, पूरी तरह से परीक्षण किए गए फ़ंक्शन से निकाली गई सरल कार्यान्वयन कार्यक्षमता का कोई भी बिट स्वयं परीक्षण (यानी अप्रत्यक्ष परीक्षण कवरेज) होगा।

मेरे लिए यह पर्याप्त स्पष्ट लगता है कि अधिकांश तरीकों को कोडिंग के शुरुआती हिस्से में उच्च स्तर के कार्य होंगे क्योंकि वे डिजाइन को encapsulating / वर्णन कर रहे हैं।

इसलिए, ये विधियां सार्वजनिक होंगी और उनका परीक्षण करना काफी आसान होगा।

एक बार सबकुछ अच्छी तरह से काम कर रहा है और निजीकरण के बाद निजी तरीके आ जाएंगे और हम पठनीयता और सफाई के लिए फैक्टरिंग कर रहे हैं।


मैं व्यक्तिगत तरीकों का परीक्षण नहीं करता हूं। एक निजी विधि एक कार्यान्वयन विवरण है जिसे कक्षा के उपयोगकर्ताओं को छिपाया जाना चाहिए। निजी तरीकों का परीक्षण encapsulation तोड़ता है।

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


यदि आप अपने निजी तरीकों का परीक्षण नहीं करते हैं, तो आप कैसे जानते हैं कि वे तोड़ नहीं पाएंगे?


यदि आपकी निजी विधि को आपकी सार्वजनिक विधियों को कॉल करके परीक्षण नहीं किया जाता है तो यह क्या कर रहा है? मैं निजी तौर पर सुरक्षित या दोस्त से बात नहीं कर रहा हूं।


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

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

यह बाद में डीबगिंग गति करता है।

-Adam


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


हम अनुमान के अनुसार निजी तरीकों का परीक्षण करते हैं, जिसके माध्यम से मेरा मतलब है कि हम कम से कम 95% की कुल श्रेणी परीक्षण कवरेज की तलाश करते हैं, लेकिन केवल हमारे परीक्षण सार्वजनिक या आंतरिक तरीकों में कॉल करते हैं। कवरेज प्राप्त करने के लिए, हमें होने वाले विभिन्न परिदृश्यों के आधार पर सार्वजनिक / आंतरिक लोगों को कई कॉल करने की आवश्यकता है। यह हमारे परीक्षणों के परीक्षण के उद्देश्य से हमारे परीक्षणों को अधिक गहन बनाता है।

आपके द्वारा लिंक की गई पोस्ट के ट्रम्पी का जवाब सबसे अच्छा है।


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


Absolutely YES. That is the point of Unit testing, you test Units. Private method is a Unit. Without testing private methods TDD (Test Driven Development) would be impossible,


If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously private but now public method that now lives on its own class.


If the method is significant enough/complex enough , I'll usually make it "protected" and test it. Some methods will be left private and tested implicitly as part of unit tests for the public/protected methods.


No You shouldn't test the Private Methods why? and moreover the popular mocking framework such as Mockito doesn't provide support for testing private methods.


The answer to "Should I test private methods?" is ".......sometimes". Typically you should be testing against the interface of your classes.

  • One of the reasons is because you do not need double coverage for a feature.
  • Another reason is that if you change private methods, you will have to update each test for them, even if the interface of your object hasn't changed at all.

Here is an example:

class Thing
  def some_string
    one + two
  end

  private 

  def one
    'aaaa'
  end

  def two
    'bbbb'
  end

end


class RefactoredThing
def some_string
    one + one_a + two + two_b
  end

  private 

  def one
    'aa'
  end

  def one_a
    'aa'
  end

  def two
    'bb'
  end

  def two_b
    'bb'
  end
end

In RefactoredThing you now have 5 tests, 2 of which you had to update for refactoring, but your object's functionality really hasn't changed. So let's say that things are more complex than that and you have some method that defines the order of the output such as:

def some_string_positioner
  if some case
  elsif other case
  elsif other case
  elsif other case
  else one more case
  end
end

This shouldn't be run by an outside user, but your encapsulating class may be to heavy to run that much logic through it over and over again. In this case maybe you would rather extract this into a seperate class, give that class an interface and test against it.

And finally, let's say that your main object is super heavy, and the method is quite small and you really need to ensure that the output is correct. You are thinking, "I have to test this private method!". Have you that maybe you can make your object lighter by passing in some of the heavy work as an initialization parameter? Then you can pass something lighter in and test against that.





language-agnostic