2012-12-20 5 views
8

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

मुझे लगता है कि जैसे एक कोड है कहते हैं: मैं Foo::action() परीक्षण करना चाहते हैं

Class Foo { 

public: 
    int action() ; 
private: 
    int state ; 

} ; 

int Foo::action() 
{ 
    if(this->state == 1) 
    return 1 ; 
    else 
    return 0 ; 
} 

तो अब, लेकिन मैं विभिन्न परिदृश्यों के तहत समारोह की जाँच करने में सक्षम हो Foo::state सेट करने में सक्षम होने की जरूरत है। एक समाधान परीक्षण कोड में बुराई "define private public" है। लेकिन क्या कुछ और सुरुचिपूर्ण है? मैं तनाव देना चाहता हूं कि Foo::state एक वैरिएबल है जिसे क्लाइंट द्वारा एक्सेस नहीं किया जाना चाहिए, इसलिए मैं कोई भी सार्वजनिक सेटटर घोषित नहीं करना चाहता हूं।

संपादित करें:

मैं अब, लगता है कि है कि व्युत्पन्न वर्ग में परीक्षण कोड में कक्षा मैं परीक्षण करना चाहते हैं का विस्तार और सहित setters काम करेगा प्रदान करने संरक्षित करने के लिए मैं निजी चर बदल दिया है। लेकिन यह एक 'पीढ़ी केवल' समाधान है और अभी भी एक उचित दृष्टिकोण के बजाय हैक की तरह लगता है।

संपादित करें 2:

जवाब और टिप्पणियों को पढ़ने के बाद मैं (Lieven और एपी के लिए धन्यवाद विशेष रूप से।) दिया गया था मेरा मानना ​​है कि वास्तविक वर्ग मैं (नहीं सरल उदाहरण मैं प्रदान की गई) बस का परीक्षण करने के कोशिश कर रहा हूँ अब बहुत अधिक करता है और मेरी समस्या का उत्तर किसी अन्य तर्क को दूसरे वर्ग में ले जा रहा है जिसका उपयोग बड़े लड़के द्वारा किया जाएगा।

+0

संभावित डुप्लिकेट [मैं एक ऐसे वर्ग का परीक्षण कैसे करूं जिसमें निजी विधियां, फ़ील्ड या आंतरिक कक्षाएं हों?] (Https://stackoverflow.com/questions/34571/how-do-i-test-a-class-that -हाउस-निजी-विधियों-फ़ील्ड-या-आंतरिक-वर्ग) – Raedwald

उत्तर

3

केवल दो posibilities (रिफैक्टरिंग asside)

  1. राज्य स्थापित करने के लिए सार्वजनिक इंटरफ़ेस का प्रयोग कर रहे हैं।
  2. यदि आप इसे सार्वजनिक इंटरफ़ेस के माध्यम से सेट नहीं कर सकते हैं तो राज्य अनावश्यक है।

विकल्प 2 स्वयं व्याख्यात्मक है और संभवतः आपके मामले पर लागू नहीं है, इसलिए आपको अपनी कक्षा के सार्वजनिक इंटरफ़ेस के माध्यम से राज्य स्थापित करने के लिए छोड़ दिया गया है।

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

Do not test private methods

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

और Unit testing private members

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

इस पर एक आम बोली में बाहर refactor करने के लिए है आप अपने साधारण सैनिक स्पर्श कभी नहीं करना चाहिए

है

+0

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

+1

@ पुचटेक - यदि आपको उस राज्य में ऑब्जेक्ट प्राप्त करने के लिए हुप्स के माध्यम से कूदने की आवश्यकता है, तो यह संकेत हो सकता है कि आपको वर्तमान ऑब्जेक्ट को छोटे, टेस्टेबल ऑब्जेक्ट्स में रीफैक्टर करने की आवश्यकता है। आपके वर्तमान ऑब्जेक्ट को इन छोटे ऑब्जेक्ट को यह काम करने के लिए इंजेक्शन दिया जाएगा। आप निर्भरता इंजेक्शन पर पढ़ना चाह सकते हैं। मैं अत्यधिक मिस्को हेवरी के ब्लॉग पढ़ने की सलाह देते हैं। –

+0

मैं आपको टिप के लिए धन्यवाद दूंगा। – Puchatek

1

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

Class Foo { 
public: 
    int action(); 
private: 
    int state; 

    friend class MyTestClass; 
}; 
+0

मुझे लगता है कि वास्तविक कोड में परीक्षण कोड का कोई निशान नहीं होना चाहिए। शायद सिर्फ एक राय है, लेकिन यह मेरे लिए सही नहीं लगता है। – Puchatek

+0

कभी-कभी आप अच्छे अभ्यास के साथ संघर्ष कर रहे हैं और नौकरी कर रहे हैं और यह रास्ता तय करने का तरीका है। – jopa

1

आप कुछ public ly निजी चर state का मान बदलने के लिए (या "protected ly") सुलभ तंत्र होने की जानी चाहिए। सादगी के लिए, मान लें कि यह एक विधि है Foo::setState(int inState)। राज्य को बदलने के लिए यूनिट परीक्षण में इसका उपयोग करें, और इस प्रकार Foo::action() विधि का परीक्षण करें। यह सुनिश्चित करता है कि भविष्य में किसी भी कार्यान्वयन में परिवर्तन यूनिट परीक्षण को प्रभावित नहीं करेगा (जब तक कि "एपीआई" Foo::setState() परिवर्तन न हो - निश्चित रूप से, आपको यूनिट परीक्षण को बदलना होगा)।

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

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

जैसा कि नीचे दी गई टिप्पणियों में चर्चा की गई है, यदि इनपुट से कोड से "पथ" का परीक्षण किया गया है तो भी लंबा है, कोड/परीक्षण को छोटे मॉड्यूल या इंटरमीडिएट पॉइंट में तोड़ना पड़ सकता है। विस्तार करने के लिए, के रूप में कोड प्रवाह पर विचार करें:

Input -> A -> B -> C -> Output 
// A, B, C are intermediate execution points which are not "publicly accessible". 

ऊपर मामले में, तुम सब कर सकते हैं

Input को देखते हुए, तो देखें कि क्या Output सही है।

को देखते हुए Input, अगर जाँच:

इसके बजाय, यह मध्यवर्ती A, B, C, कम से कम इकाई परीक्षण करने के लिए, ताकि आप अब में अपने परीक्षण तोड़ सकते हैं बेनकाब करने के लिए अच्छा होगा A सही है।

A दिया गया, जांचें कि B सही है या नहीं।

B को देखते हुए, C सही है या नहीं।

C दिया गया, जांचें कि Output सही है या नहीं।

जैसा कि आप कल्पना कर सकते हैं, यदि परीक्षण विफल रहता है, तो यह पता लगाना आसान हो जाता है कि क्या विफल हुआ, और इसलिए इसे ठीक करने के लिए।

+0

ठीक है, अगर इनपुट से कोड में "पथ" कोड को यूनिट परीक्षण किया जाता है तो यह _too_ लंबा होता है, आमतौर पर इसका मतलब है कि कोड/परीक्षण को छोटे मॉड्यूल में दोबारा क्रियान्वित करने की आवश्यकता है। वैकल्पिक रूप से, यह हो सकता है कि परीक्षण को "उच्च स्तर" पर लागू किया जाना चाहिए। आपके विवरण से, ऐसा लगता है कि आप आवश्यकतानुसार कम स्तर के अमूर्तता पर परीक्षण कर रहे हैं। –

+0

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

+1

मेरी व्यक्तिगत राय यह है कि इंटरमीडिएट पॉइंट्स का पर्दाफाश करना ठीक है, अगर केवल परीक्षण के लिए, यदि यह परीक्षण की गुणवत्ता में सुधार करने में मदद करता है (और इसलिए कोड)। प्रीप्रोसेसर आपकी मदद कर सकता है। '#ifdef UNIT_TEST ... # endif' के अंदर" केवल परीक्षण "कोड संलग्न करें, और इकाई परीक्षण करते समय' -DUNIT_TEST' के साथ संकलित करें। यह भी सुनिश्चित करता है कि परीक्षण केवल कोड को "असली" निष्पादन योग्य से बाहर रखा गया है। –

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