2014-11-07 3 views
8

मैं एक साधारण कार्य है परीक्षण करने के लिए मैं परीक्षण करना चाहते हैं:कैसे एक समारोह के उत्पादन (stdout/stderr) जाओ इकाई में परीक्षण

func (t *Thing) print(min_verbosity int, message string) { 
    if t.verbosity >= minv { 
     fmt.Print(message) 
    } 
} 

लेकिन यह कैसे मैं परीक्षण कर सकते हैं समारोह वास्तव में मानक आउटपुट में भेजा जाने वाला? Test::Output क्या मैं पर्ल में चाहते हैं करता है। मैं जानता हूँ कि मैं (के रूप में वर्णित here) जाओ में भी ऐसा ही करने के लिए सभी मेरे अपने बॉयलरप्लेट लिख सकते हैं:

orig = os.Stdout 
r,w,_ = os.Pipe() 
thing.print("Some message") 
var buf bytes.Buffer 
io.Copy(&buf, r) 
w.Close() 
os.Stdout = orig 
if(buf.String() != "Some message") { 
    t.Error("Failure!") 
} 

लेकिन वह हर एक परीक्षा के लिए अतिरिक्त काम का एक बहुत कुछ है। मुझे आशा है कि इसे संभालने के लिए एक और मानक तरीका है, या शायद एक अमूर्त पुस्तकालय है।

उत्तर

15

एक बात भी याद रखना, कार्य लेखन बॉयलरप्लेट से बचने के लिए करने से रोकने के लिए कुछ भी नहीं है।

उदाहरण के लिए मैं log का उपयोग करता है एक कमांड लाइन अनुप्रयोग है और मैं इस समारोह ने लिखा है:

func captureOutput(f func()) string { 
    var buf bytes.Buffer 
    log.SetOutput(&buf) 
    f() 
    log.SetOutput(os.Stderr) 
    return buf.String() 
} 

तो इस तरह इसका इस्तेमाल किया: http://godoc.org/github.com/stretchr/testify/assert:

output := captureOutput(func() { 
    client.RemoveCertificate("www.example.com") 
}) 
assert.Equal("removed certificate www.example.com\n", output) 

इस ज़ोर पुस्तकालय का उपयोग करना।

+0

शायद यह है कि मैं क्या करूँगा, क्योंकि यह @ ऐनार-जी द्वारा प्रदान किए गए एक सामान्य समाधान है, जिसके लिए मुझे यह आवश्यक है कि मैं कुछ कोड को नियंत्रित कर सकूं जो कुछ आउटपुट कर सकता है। – Flimzy

9

आप दो चीजों में से एक कर सकते हैं। सबसे पहले Examples का उपयोग करना है।

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

func ExampleHello() { 
     fmt.Println("hello") 
     // Output: hello 
} 

दूसरी (और अधिक उपयुक्त, IMO) अपने आईओ के लिए नकली कार्यों का उपयोग करने के लिए है। अपने कोड में आप करते हैं:

var myPrint = fmt.Print 

func (t *Thing) print(min_verbosity int, message string) { 
    if t.verbosity >= minv { 
     myPrint(message) // N.B. 
    } 
} 

और अपने परीक्षण में:

func init() { 
    myPrint = fakePrint // fakePrint records everything it's supposed to print. 
} 

func Test... 

एक अन्य विकल्प एक io.Writer वह यह है कि उत्पादन कोड में os.Stdout साथ fmt.Fprintf उपयोग करने के लिए है, लेकिन टेस्ट मैचों में bytes.Buffer कहना जा सकता है।

+1

उदाहरण आपके लिए अच्छा है जब आपके पास टर्मिनिस्ट आउटपुट और fmt.Fprint तब अच्छा होता है जब आप प्रिंट कोड को नियंत्रित कर सकते हैं (जिसे आप बाहरी लाइब्रेरी या कुछ में नहीं कर सकते हैं)। मुझे लगता है कि ज्यादातर समय इनमें से एक चीज सच होगी। यदि कोई ऐसा मामला है जहां ओएस को लिखा गया पढ़ने के लिए कोई विकल्प सही नहीं है। स्ट्रिंग में सबमिट करना अच्छा होगा। – voutasaurus

1

आप अपने कार्य करने के लिए एक वापसी कथन जोड़ने स्ट्रिंग है कि वास्तव में मुद्रित वापस जाने के लिए विचार कर सकते हैं।

func (t *Thing) print(min_verbosity int, message string) string { 
    if t.verbosity >= minv { 
     fmt.Print(message) 
     return message 
    } 
    return "" 
} 

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

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

0

मैं टिप्पणी यहाँ के सभी प्यार और Print कार्यों से निपटने के लिए मेरे समाधान जोड़ना चाहते थे।आप देख सकते हैं, मैं एक वापसी प्रकार string लागू कर दिया है, लेकिन से निपटने यह वैकल्पिक है के रूप में मैं यह बस के रूप में कहते हैं:

PrintWarning("Some warning")

समारोह घोषणा:

var test = false 

func PrintWarning(format string, values ...interface{}) string { 
    message := fmt.Sprintf("[WARNING] " + format, values...) 

    c := color.New(color.FgYellow) 
    if !test { 
     c.Println(message) 
    } 

    return c.Sprintln(message) 
} 

टेस्ट घोषणा:

func TestPrintWarning(t *testing.T) { 
    test = true 
    result := PrintWarning("Testing warning") 
    assert.Equal(t, result, "[WARNING] Testing warning\n") 
} 
संबंधित मुद्दे