2010-05-06 16 views
16

सी ++ में पीआईएमपीएल मुहावरे उस वर्ग के उपयोगकर्ताओं से कक्षा के कार्यान्वयन विवरण (= निजी सदस्यों) को छिपाने का लक्ष्य रखता है। हालांकि यह उस वर्ग की कुछ निर्भरताओं को भी छुपाता है जिसे आम तौर पर एक परीक्षण बिंदु से खराब माना जाता है।पीआईएमपीएल मुहावरे और टेस्टेबिलिटी

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

क्या कोई इस समस्या से पहले आया है? और क्या आपको कोई समाधान मिला है?

- संपादन -

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

+3

आपके संपादन का जवाब देने के लिए, यदि आपकी "निजी" कार्यक्षमता पर्याप्त जटिलता है, तो इसे स्वतंत्र रूप से परीक्षण करने की आवश्यकता है, तो आपको इसे अपने मॉड्यूल में रखना चाहिए जिसे आप स्वतंत्र रूप से परीक्षण करते हैं। – zdan

उत्तर

16

पिंपल के पीछे विचार कक्षाओं से कार्यान्वयन विवरण छुपाने के लिए इतना नहीं है, (निजी सदस्य पहले से ही ऐसा करते हैं) लेकिन शीर्षलेख से कार्यान्वयन विवरण को स्थानांतरित करने के लिए। समस्या यह है कि सी ++ के मॉडल में, निजी विधियों/चर बदलने से इस फ़ाइल को पुन: संकलित करने के लिए किसी भी फाइल को मजबूर कर दिया जाएगा। यह एक दर्द है, और यही वजह है कि पिंपल खत्म करना चाहता है। यह बाहरी पुस्तकालयों पर निर्भरताओं को रोकने में मदद नहीं करता है। अन्य तकनीकें ऐसा करती हैं।

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

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

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

17

यूनिट परीक्षण को ए के कार्यान्वयन के आंतरिक भाग तक पहुंच की आवश्यकता क्यों है?

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

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

+2

सहमत हुए। आप * इंटरफेस * का परीक्षण करते हैं, आंतरिक नहीं। –

+0

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

+1

@ रिमो, 'पीआईएमपीएल', 'पिंपल' का पूरा बिंदु, पढ़ें: http://en.wikipedia.org/wiki/Cheshire_Cat_Idiom_(programming_technique) * छुपाएं * कार्यान्वयन है। एक परीक्षण परिप्रेक्ष्य से, आपको 'y' आउटपुट अपेक्षित 'y' आउटपुट का परीक्षण करने की आवश्यकता है। यह कैसे आता है एक कार्यान्वयन विस्तार है, और परीक्षण करने की आपकी ज़िम्मेदारी नहीं है (यूनिट-टेस्ट परिप्रेक्ष्य से)। –

11

यदि आप निर्भरता इंजेक्शन सही कर रहे हैं, तो किसी भी निर्भरता कक्षा ए को अपने सार्वजनिक इंटरफ़ेस के माध्यम से पारित किया जाना चाहिए - यदि आपका पीआईएमपी निर्भरता के कारण आपके परीक्षण में हस्तक्षेप कर रहा है, तो ऐसा लगता है कि आप इंजेक्शन नहीं कर रहे हैं उन निर्भरताओं।

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

+1

आप कह रहे हैं कि क्लास ए के केवल सार्वजनिक तरीकों का परीक्षण किया जाना चाहिए। लेकिन क्या आपको कभी-कभी अलगाव में निजी सहायक तरीके से यूनिट-टेस्ट की आवश्यकता नहीं होती है? उदाहरण के लिए, Google टेस्ट फ्रेमवर्क विशेष रूप से इसके लिए एफआरआई END_TEST मैक्रो का समर्थन करता है। – Rimo

+1

@ रिमो: क्या आप पिंपल क्लास का परीक्षण करने के लिए गैर-पिंपल कक्षाओं के निजी तरीकों का परीक्षण करने के लिए उपयोग की जाने वाली तकनीकों का उपयोग कर सकते हैं? या क्या मैं कुछ न कुछ भूल रहा हूं? –

0

इकाई परीक्षण कार्यान्वयन कक्षा को अपने पैसों के माध्यम से रखना चाहिए। एक बार जब पीआईएमपीएल कक्षा तस्वीर में है, तो आप पहले से ही "एकीकरण" के क्षेत्र में हैं - और इसलिए यू/टी इस तरह लागू नहीं होता है। पीआईएमपीएल कार्यान्वयन को छिपाने के बारे में है - आपको कार्यान्वयन के वर्ग सेटअप को नहीं जानना चाहिए।

0

पीआईएमपीएल मुहावरे परीक्षण को अधिक आसान बनाता है। ओपी के बाद इतने लंबे समय तक जवाब देने के लिए प्रेरित करने के लिए "कार्यान्वयन का परीक्षण न करें" विषय पर उत्तर का एक सेट देखने के लिए पर्याप्त अजीब बात है।

सामान्य रूप से, गैर-पिंपल आधारित सी ++ आपके पास सार्वजनिक और निजी क्षेत्रों के साथ एक कक्षा है। सार्वजनिक क्षेत्रों का परीक्षण करना आसान है, निजी क्षेत्र कुछ हद तक अधिक कठिन हैं। सार्वजनिक और निजी के बीच विभाजन महत्वपूर्ण है, क्योंकि यह एपीआई की चौड़ाई को कम करता है और आमतौर पर बाद में परिवर्तनों को आसान बनाता है।

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

class my_things 
{ 
    public: 
    my_things(); 
    ~my_things(); 
    void do_something_important(int); 
    int also_this(); 
    private: 
    struct my_things_real; 
    std::unique_ptr<my_things_real> state; 
}; 

my_things_real वर्ग बाहर से दिखाई देने वर्ग के नाशक के रूप में ही स्रोत फ़ाइल में दिखाई दे होने की उम्मीद है, लेकिन शीर्षक में नहीं। यह सार्वजनिक इंटरफ़ेस का हिस्सा नहीं है, इसलिए सभी फ़ील्ड सार्वजनिक हो सकते हैं।

void my_things::do_something_important(int x) { state->doit(x); } // etc 

class my_things_real // I'd probably write 'struct' 
{ 
    public: 
    int value; 
    void doit(int x) { value = x; } 
    int getit() { return value; } 
}; 

यूनिट परीक्षण तब वास्तविक कक्षा के खिलाफ लिखे जाते हैं। जितना चाहें उतना या उससे कम परीक्षण करें। मैंने जानबूझकर इसे "प्रत्यारोपण" के बजाय "वास्तविक" कहा है ताकि यह सुनिश्चित करने में सहायता मिल सके कि यह केवल कार्यान्वयन विस्तार के लिए गलत नहीं है।

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

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

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