यूनिट परीक्षण निजी तरीकों को बुरा अभ्यास क्यों माना जाता है?


18

प्रसंग:

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

मुझे पता है कि कोड में आत्मविश्वास देने और यह सुनिश्चित करने के लिए परीक्षण आवश्यक हैं कि किसी भी बाद के संशोधन ने पिछले व्यवहार को नहीं तोड़ा है।

मुसीबत:

एक विश्वसनीय आधार पर उच्च स्तर के सार्वजनिक तरीकों का निर्माण करने के लिए, मैं आमतौर पर निजी तरीकों का परीक्षण करता हूं। मुझे यह पता लगाना आसान है कि क्या एक कोड संशोधन ने प्रतिगमन और कहां पेश किया है। इसका मतलब है कि वे आंतरिक परीक्षण मामूली संशोधन पर टूट सकते हैं और उन्हें ठीक करने / बदलने की आवश्यकता होगी

लेकिन मुझे यह भी पता है कि निजी पद्धति का परीक्षण करने वाली इकाई कम से कम एक विवादित अवधारणा या अधिक बार खराब अभ्यास के रूप में मानी जाती है। इसका कारण: केवल सार्वजनिक व्यवहार का परीक्षण ( रेफरी ) होना चाहिए

सवाल:

मैं निम्नलिखित सर्वोत्तम प्रथाओं का ध्यान रखता हूं और समझना चाहूंगा:

  • निजी / गुप्त तरीकों पर यूनिट परीक्षणों का उपयोग क्यों बुरा है (जोखिम क्या है)?
  • जब सार्वजनिक तरीके निम्न स्तर और / या जटिल प्रसंस्करण का उपयोग कर सकते हैं तो सबसे अच्छी प्रथाएं क्या हैं?

precisions:

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


2
ओपी, आपने कहां सुना या पढ़ा कि निजी तरीकों का परीक्षण "बुरा" माना जाता था? इकाई परीक्षण के विभिन्न तरीके हैं। देखें इकाई परीक्षण, काले बॉक्स टेस्टिंग और सफेद बॉक्स टेस्टिंग
जॉन वू

@ जॉनवु: मुझे व्हाइट-बॉक्स और ब्लैक-बॉक्स परीक्षण के बीच का अंतर पता है। लेकिन व्हाइट-बॉक्स परीक्षण में भी ऐसा लगता है कि निजी तरीकों का परीक्षण करने की आवश्यकता एक डिजाइन समस्या के लिए संकेत है। मेरा सवाल यह समझने की कोशिश है कि जब मैं वहां गिरता हूं तो सबसे अच्छे रास्ते क्या होते हैं ...
सर्ज बलास्टा

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

@SergeBallesta दूसरे शब्दों में, उन लेखों के लिए कुछ संदर्भ डालते हैं जिन्होंने आपको विश्वास दिलाया कि निजी तरीकों का परीक्षण करना एक बुरा अभ्यास है। फिर हमें समझाएं कि आपने उन पर विश्वास क्यों किया।
लैव

जवाबों:


18

कारणों की एक जोड़ी:

  1. आमतौर पर जब आप किसी कक्षा की निजी पद्धति का परीक्षण करने के लिए ललचाते हैं, तो यह एक डिजाइन गंध (हिमशैल वर्ग, पर्याप्त पुन: प्रयोज्य सार्वजनिक घटक, आदि) नहीं है। खेलने में लगभग हमेशा कुछ "बड़ा" मुद्दा होता है।

  2. आप उन्हें सार्वजनिक इंटरफ़ेस के माध्यम से परीक्षण कर सकते हैं (जो कि आप उन्हें कैसे परीक्षण करना चाहते हैं, क्योंकि यही क्लाइंट उन्हें कॉल / उपयोग करेगा)। आप अपने निजी तरीकों के लिए सभी पासिंग टेस्ट पर हरी बत्ती देखकर सुरक्षा का गलत अर्थ निकाल सकते हैं। अपने सार्वजनिक इंटरफ़ेस के माध्यम से अपने निजी कार्यों पर किनारे के मामलों का परीक्षण करना बेहतर / सुरक्षित है।

  3. निजी तरीकों का परीक्षण करके आप गंभीर परीक्षण दोहराव (बहुत समान दिखने वाले परीक्षण) का जोखिम उठाते हैं। जब आवश्यकताएं बदलती हैं तो इसके बड़े परिणाम होते हैं, क्योंकि आवश्यकता से अधिक परीक्षण टूटेंगे। यह आपको ऐसी स्थिति में भी डाल सकता है जहां आपके टेस्ट सूट के कारण रिफ्लेक्टर करना मुश्किल है ... जो कि अंतिम विडंबना है, क्योंकि टेस्ट सूट आपको सुरक्षित रूप से रीडिजाइन और रिफलेक्टर करने में मदद करने के लिए है!

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

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

मेरे पास एक उत्तर है जो एसओ पर इस पर विस्तार से जाता है जिसे मैं यहां नहीं दोहराऊंगा: /programming/105007/should-i-test-private-methods-or-only-public-ones/ 47401015 # 47401015


4
कारण 1: नेबुला। कारण 2: क्या होगा यदि आपकी निजी सहायक विधि सार्वजनिक एपीआई का हिस्सा नहीं होनी चाहिए? कारण 3: यदि आप अपनी कक्षा को ठीक से डिज़ाइन नहीं करते हैं। आपकी आखिरी टिप: मैं एक पूरी तरह से अच्छा परीक्षण क्यों हटाऊंगा जो यह साबित करता है कि एक विधि मैंने लिखी है?
रॉबर्ट हार्वे

4
@RobertHarvey कारण 2: सार्वजनिक एपीआई के माध्यम से अप्रत्यक्ष रूप से सुलभ होना! = सार्वजनिक एपीआई का हिस्सा होना। यदि आपका निजी फ़ंक्शन सार्वजनिक API के माध्यम से परीक्षण योग्य नहीं है, तो शायद यह एक मृत कोड है और इसे हटा दिया जाना चाहिए? या आपकी कक्षा वास्तव में एक हिमशैल (कारण 1) है और इसे फिर से बनाया जाना चाहिए।
फ्राक

5
@RobertHarvey यदि आप एक सार्वजनिक एपीआई के माध्यम से एक निजी फ़ंक्शन का परीक्षण नहीं कर सकते हैं, तो इसे हटा दें क्योंकि यह कोई उपयोगी उद्देश्य नहीं है।
डेविड अरनो

1
@ रोबर्टहवे 1: डिज़ाइन की गंध हमेशा कुछ व्यक्तिपरक / अस्पष्ट होती है, इसलिए निश्चित है। लेकिन मैंने एंटी-पैटर्न के कुछ ठोस उदाहरण सूचीबद्ध किए हैं, और मेरे एसओ उत्तर में अधिक विवरण है। 2: निजी तरीके सार्वजनिक API का हिस्सा नहीं हो सकते हैं (परिभाषा के अनुसार: वे निजी हैं) ... इसलिए मुझे नहीं लगता कि आपका प्रश्न बहुत मायने रखता है। मैं इस बिंदु पर जाने की कोशिश कर रहा हूं कि अगर आपके पास bin_search(arr, item)(सार्वजनिक) और bin_search(arr, item, low, hi)(निजी, बिन खोज करने के कई तरीके हैं), तो आपको सभी का परीक्षण करने की आवश्यकता है सार्वजनिक सामना करना पड़ रहा है ( bin_search(arr, item))
मैट मेस्मिथिथ

1
@ रोबर्टहवे 3: सबसे पहले, मैंने कहा कि जोखिम , गारंटी नहीं । दूसरे, यह दावा करना कि "यह काम करता है यदि आप इसे ठीक से करते हैं" आत्म-पूर्ति है। उदाहरण के लिए, " यदि आप इसे ठीक से करते हैं, तो आप किसी एकल फ़ंक्शन में एक ऑपरेटिंग सिस्टम लिख सकते हैं "। यह गलत नहीं है: लेकिन यह भी उपयोगी नहीं है। टिप के बारे में: आप इसे हटा देंगे क्योंकि यदि आपका कार्यान्वयन बदल जाता है (यानी आप एक निजी इम्प्लांट को स्वैप करना चाहते हैं), तो आपका टेस्ट सूट आपके रास्ते में आ जाएगा (आपके पास एक असफल परीक्षा होगी जहां आपको नहीं करना चाहिए)।
मैट मेसमिथिथ

14

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


निश्चित नहीं है कि आपके उत्तर को अस्वीकृत क्यों किया गया है। यह छोटा है, बिंदु तक है और उत्तर 100% सही है।
डेविड अर्नो

3
: कार्यान्वयन विवरण के लिए युग्मन के साथ यह सब कुछ है।
रॉबर्ट हार्वे

11

निजी तरीकों के लिए इकाई परीक्षण लिखना विवरणों को लागू करने के लिए आपकी इकाई परीक्षणों को जोड़ता है।

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

जैसा कि कहा गया है, क्यों हो सकता है आप अपने निजी तरीकों के लिए इकाई परीक्षण लिखने के लिए करना चाहते हैं?

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

कुछ पारिस्थितिकी प्रणालियों जैसे C # और .NET में REPL- जैसा वातावरण (Linqpad जैसे उपकरण ऐसा करने के लिए) बनाने के तरीके हैं, लेकिन उनकी उपयोगिता सीमित है क्योंकि आपके पास अपनी परियोजना तक पहुंच नहीं है। विजुअल स्टूडियो में तत्काल विंडो असुविधाजनक है; इसमें अभी भी पूर्ण Intellisense नहीं है, आपको इसमें पूरी तरह से योग्य नामों का उपयोग करना होगा, और जब भी आप इसका उपयोग करते हैं, यह एक बिल्ड को ट्रिगर करता है।


4
@ user949300 इस बात पर बहस करना थोड़ा मुश्किल है कि बिना किसी सच्चे स्कॉट्समैन के पतन में पड़ें , लेकिन सभी प्रकार के बुरी तरह से लिखित परीक्षण हैं। एक इकाई परीक्षण के नजरिए से, आपको आंतरिक कार्यान्वयन विवरण जानने के बिना अपने तरीके के सार्वजनिक अनुबंध का परीक्षण करना चाहिए। ऐसा नहीं है कि एक निश्चित निर्भरता को एक्स बार कहा गया है, यह कहना हमेशा गलत होता है: ऐसी परिस्थितियां हैं जहां यह समझ में आता है। आपको बस यह सुनिश्चित करना है कि यह एक जानकारी है जिसे आप वास्तव में परीक्षण के तहत उस इकाई के अनुबंध में व्यक्त करना चाहते हैं।
विंसेंट सवार्ड

3
@ दाविद अरनो: [ श्रग ] मैं अब थोड़ी देर के लिए ऐसा कर रहा हूं। निजी तरीकों के लिए यूनिट परीक्षण हमेशा मेरे लिए ठीक काम करते थे, जब तक कि माइक्रोसॉफ्ट ने अपने परीक्षण ढांचे में प्रॉक्सी वस्तुओं का समर्थन बंद करने का फैसला नहीं किया। परिणामस्वरूप कुछ भी कभी नहीं फटा। मैंने एक निजी पद्धति के लिए परीक्षण लिखकर ब्रह्मांड में एक छेद नहीं किया।
रॉबर्ट हार्वे

2
@DavidArno: मैं पूरी तरह से एक अच्छी तकनीक का उपयोग करना क्यों छोड़ दूंगा जो मुझे लाभ प्रदान करता है, सिर्फ इसलिए कि इंटरनेट पर कोई व्यक्ति बिना किसी औचित्य के एक बुरा विचार कहता है?
रॉबर्ट हार्वे

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

2
@ फ़्रेक्स ज़रूर, मैं कर सकता था, लेकिन उस तर्क से, मुझे सिस्टम-वाइड एकीकरण परीक्षणों के पक्ष में यूनिट परीक्षणों को त्यागना चाहिए। आखिरकार, "ज्यादातर मामलों में आपको एक ही व्यवहार का परीक्षण करने के लिए इन परीक्षणों को संशोधित करने में सक्षम होना चाहिए"
अलेक्जेंडर - मोनिका

6

अपने अनुभव से मैंने पाया है कि आंतरिक कक्षाओं का परीक्षण करने वाली इकाई, तरीकों का आमतौर पर मतलब है कि मुझे परीक्षण किए गए कार्यों, कक्षाओं को बाहर निकालना होगा। अमूर्तता का एक और स्तर बनाने के लिए।

इससे एकल जिम्मेदारी सिद्धांत का बेहतर पालन होता है।


यह स्वीकृत उत्तर होना चाहिए।
जैक एडली

0

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

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

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



मैंने इसे अपने प्रश्न में यह कहकर संबोधित करने का प्रयास किया कि पायथन में गोपनीयता की सच्ची अवधारणा नहीं है और छिपी हुई विधियाँ बस सूचीबद्ध नहीं हैं, लेकिन इसका उपयोग तब किया जा सकता है जब आप उनका नाम जानते हैं
सर्ज बलेस्टा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.