2010-05-06 9 views
5

आप कैसे इकाई परीक्षण do_int_to_string_conversion होगा है परीक्षण?यूनिट एक कार्यों जिसका उद्देश्य दुष्प्रभाव

#include <string> 
#include <iostream> 

void do_int_to_string_conversion(int i, std::string& s) { 
    switch(i) { 
    case 1: 
     s="1"; 
     break; 
    case 2: 
     s="2"; 
     break; 
    default: 
     s ="Nix"; 
    } 
} 

int main(int argc, char** argv){ 
    std::string little_s; 

    do_int_to_string_conversion(1, little_s); 
    do_int_to_string_conversion(2, little_s); 
    do_int_to_string_conversion(3, little_s); 

} 
+0

आप बस यह सुनिश्चित करते हैं कि कॉल के बाद वांछित प्रभाव हुआ? – jball

+2

मुझे लगता है कि इस उदाहरण में "साइड इफेक्ट" का मतलब std :: cout को आउटपुट को संदर्भित करता है। –

+0

मुझे पूछना है, हालांकि, आप संदर्भ में गुजरने के बजाय केवल एक स्ट्रिंग क्यों नहीं लौटते? आप पूरी तरह से उस स्थान को बदल रहे हैं जिसे आप पास करते हैं, इसलिए आपको प्रतिलिपि से बचने के लिए कोई प्रदर्शन लाभ नहीं मिलता है (क्योंकि आप इसे टालना नहीं चाहते हैं), और यदि आपने स्ट्रिंग वापस कर दी है, तो आप आरवीओ (रिटर्न वैल्यू ऑप्टिमाइज़ेशन) से लाभ उठा सकते हैं। । –

उत्तर

9

मुझे लगता है कि यह सिर्फ एक उदाहरण है। आप प्रत्येक कॉल के बाद little_s के मूल्य पर क्यों जोर नहीं दे सकते?

do_int_to_string_conversion(1, little_s); 
assert_are_equal("1", little_s); 
+1

उत्कृष्ट विचार। – David

-1

आप इसे कुछ इनपुट पारित और सत्यापित करें कि इसके उत्पादन यह क्या होना चाहिए करने के लिए Expect की तरह कुछ का उपयोग कर सकते हैं।

3

आप वास्तव में सुनिश्चित करना है कि उत्पादन में लिखा गया है की जरूरत है, तो आप std::cout से अपनी निर्भरता को तोड़ने और परीक्षण के दौरान एक और std::ostream उपयोग करने के लिए की जरूरत है।

यह एक वैश्विक चर के रूप में सरल हो सकता है:

#if PRODUCTION 
std::ostream my_output = std::cout; 
#else 
std::ostream my_output = std::ostringstream; 
#endif 

void setup() 
{ 
    my_output = std::ostringstream; 
} 

void print_hello() 
{ 
    my_output << "hello"; 
} 

void test_hello_was_printed() 
{ 
    print_hello(); 
    ASSERT("hello" == my_output.str()); 
} 

या उस प्रभाव के लिए कुछ इसी तरह।

+0

यह भी एक अच्छा विचार है और जिस पर मैंने विचार नहीं किया था। Std :: cout का अधिकार अनिवार्य है [इसमें शामिल करने के लिए मेरी गलती]। – David

3

मैं do_int_to_string_conversion बदल सकते हैं कि यह सिर्फ एक बात (एक स्ट्रिंग के लिए रूपांतरित) करता हूँ।

void do_int_to_string_conversion(int i, std::string& s) { 
    switch(i) { ... } 
} 

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

अगर मैं एक समारोह है कि रूपांतरण के परिणाम मुद्रित की जरूरत है, मैं एक अलग समारोह में डाल चाहते हैं कि, और मैं उत्पादन धारा parameterize चाहते हैं।

void output_int(int i, ostream &stream) { 
    std::string s; 
    do_int_to_string_conversion(i, s); 
    stream << s; 
} 

इकाई परीक्षण के लिए, मैं एक std :: स्ट्रिंगस्ट्रीम ऑब्जेक्ट में पास करता हूं और परिणाम की जांच करता हूं।

+0

@ एड्रियन: +1 - आप इसे हराते हैं। –

11

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

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

मैं 1 से शुरुआत करते हैं,) इसे बंटवारे तार्किक कार्यों में, और 2) एक पैरामीटर के रूप धारा की आपूर्ति।

std::string convert_int(int val) { 
    switch (val) { 
     case 1: return "1"; 
     case 2: return "2"; 
     default: return "Nix"; 
    } 
} 

std::ostream &write_string(std::ostream &os, std::string const &s) { 
    return os << s; 
} 

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

भवदीय, write_string एक अच्छे उम्मीदवार पूरी तरह से समाप्त कर दिया गया है, लेकिन जब से तुम था कि क्षमता के बुनियादी प्रकार, हम इस समय के लिए यह अपने पास रखेंगे। इनका परीक्षण करना अपेक्षाकृत सरल है - convert_int के लिए, हम उस स्ट्रिंग को देखते हैं जो इसे लौटाता है, और हम जो अपेक्षा करते हैं उसकी तुलना करें। write_string के लिए, हम एक सामान्य ostream के बजाय stringstream पास कर सकते हैं - फिर हम उस परिणाम को प्राप्त करने के लिए .str() का उपयोग कर सकते हैं, और (फिर से) हम अपेक्षा करते हैं इसकी तुलना करें।

+1

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

+1

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

+0

मैंने इस प्रश्न को मेरे दूसरे मित्र से पूछा, और उसके साथ आपके समान प्रतिक्रिया थी। Std :: cout को लिखने सहित मेरे हिस्से पर बुरा था क्योंकि यह चीजों को उलझन में था। अभी भी मेरे प्रश्न पूछने के कौशल पर काम कर रहे हैं। इस मामले में स्ट्रिंग बड़ी-मेमोरी-मैप-डेटा-स्ट्रक्चर के लिए प्रॉक्सी है जो इंटरफ़ेस में रहती है और हम पुराने किले के ढेर के साथ काम कर रहे हैं। Int उस स्थान पर लिखने के लिए संभावित चीजों की सूची सूचीबद्ध करता है। – David

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