📋 Go यूनिट टेस्ट लॉग्स को साफ़ कैसे रखें: केवल विफल इनपुट को ही लॉग करें 🔗

Go में यूनिट टेस्ट लिखते समय—विशेष रूप से टेबल-संचालित (table-driven) टेस्ट—वे फ़ंक्शन जो मानक ग्लोबल log पैकेज में लिखते हैं, आपके टर्मिनल को तेज़ी से अव्यवस्थित (clutter) कर सकते हैं।

यदि आपके पास एक दर्जन टेस्ट केस हैं और उनमें से केवल एक विफल होता है, तब भी आपको त्रुटि (error) खोजने के लिए सभी सफल केसों के लॉग आउटपुट को स्क्रॉल करना पड़ता है। यह अनावश्यक शोर डीबगिंग को धीमा कर देता है और आपके टेस्ट आउटपुट को पढ़ना कठिन बना देता है।

आइए एक सामान्य परिदृश्य को देखें और जानें कि लॉग्स को कैप्चर करके और उन्हें केवल टेस्ट विफल होने पर प्रिंट करके इसे कैसे ठीक किया जाए।

📑 विषय-सूची 🔗


🔊 समस्या: शोरगुल वाला टेस्ट आउटपुट 🔗

मान लीजिए हमारे पास एक सरल फ़ंक्शन है जो अपने इनपुट और अपने अंतिम परिणाम को लॉग करता है:

package add

import (
	"log"
)

func add(x, y int) int {
	log.Printf("add %d %d", x, y)
	res := x + y
	log.Printf("add %d %d = %d", x, y, res)
	return res
}

अब, हम तीन केसों के साथ एक मानक टेबल-संचालित यूनिट टेस्ट लिखते हैं (जहाँ अंतिम केस को जानबूझकर विफल होने के लिए डिज़ाइन किया गया है):

package add

import (
	"testing"
)

func TestAdd(t *testing.T) {
	inputs := []struct {
		x    int
		y    int
		want int
	}{
		{x: 1, y: 2, want: 3},
		{x: 3, y: 2, want: 5},
		{x: 4, y: 5, want: 0}, // Intentionally failing case
	}

	for _, in := range inputs {
		got := add(in.x, in.y)
		if in.want != got {
			t.Errorf("add %d %d got %d want %d", in.x, in.y, got, in.want)
		}
	}
}

जब हम go test चलाते हैं, तो आउटपुट में अंततः विफलता दिखाने से पहले सभी पास होने वाले इनपुट के लॉग शामिल होते हैं:

$ go test
2020/09/05 09:01:25 add 1 2
2020/09/05 09:01:25 add 1 2 = 3
2020/09/05 09:01:25 add 3 2
2020/09/05 09:01:25 add 3 2 = 5
2020/09/05 09:01:25 add 4 5
2020/09/05 09:01:25 add 4 5 = 9
--- FAIL: TestAdd (0.00s)
    add_test.go:28: add 4 5 got 9 want 0
FAIL
exit status 1

🛠️ समाधान: डिपेंडेंसी इंजेक्शन और बफ़र्स (Buffers) 🔗

यह कहीं बेहतर होगा कि केवल विफल होने वाले इनपुट द्वारा जनरेट किए गए लॉग ही दिखाई दें। हम अपने फ़ंक्शन में एक लॉगर पास करके (डिपेंडेंसी इंजेक्शन) और अपने टेस्ट के दौरान लॉग्स को एक अस्थायी बफ़र में लिखकर इसे प्राप्त कर सकते हैं।

सबसे पहले, आइए *log.Logger स्वीकार करने के लिए अपने फ़ंक्शन को अपडेट करें:

package add

import "log"

func add(logger *log.Logger, x, y int) int {
	logger.Printf("add %d %d", x, y)
	res := x + y
	logger.Printf("add %d %d = %d", x, y, res)
	return res
}

इसके बाद, हम अपने टेस्ट को अपडेट करते हैं। प्रत्येक टेस्ट केस इटरेशन के लिए, हम एक नया bytes.Buffer बनाएंगे और उससे एक नया लॉगर जोड़ेंगे। यदि टेस्ट पास हो जाता है, तो बफ़र को बस छोड़ (discard) दिया जाता है। यदि टेस्ट विफल हो जाता है, तो हम त्रुटि संदेश के साथ बफ़र की सामग्री प्रिंट करते हैं!

(नोट: हम t.Run का उपयोग करने के लिए टेस्ट को अपग्रेड भी कर रहे हैं, जो Go में टेबल-संचालित सब-टेस्ट चलाने का मुहावरेदार (idiomatic) तरीका है).

package add

import (
	"bytes"
	"log"
	"testing"
)

func TestAdd(t *testing.T) {
	inputs := []struct {
		name string
		x    int
		y    int
		want int
	}{
		{name: "1+2", x: 1, y: 2, want: 3},
		{name: "3+2", x: 3, y: 2, want: 5},
		{name: "4+5", x: 4, y: 5, want: 0}, // Intentionally failing case
	}

	for _, in := range inputs {
		t.Run(in.name, func(t *testing.T) {
			// 1. Create a buffer to capture the logs
			var buf bytes.Buffer
			
			// 2. Create a new logger that writes to the buffer
			logger := log.New(&buf, "", log.LstdFlags)
			
			// 3. Pass the custom logger into our function
			got := add(logger, in.x, in.y)
			
			if in.want != got {
				// 4. Print the buffer contents ONLY if the test fails
				t.Errorf("got %d want %d\n\nExecution Logs:\n%s", got, in.want, buf.String())
			}
		})
	}
}

✨ साफ़ आउटपुट 🔗

अब, जब हम अपने टेस्ट चलाते हैं, तो आउटपुट बिल्कुल साफ़ और अत्यधिक कार्रवाई योग्य (actionable) होता है। हमें केवल वे लॉग दिखाई देते हैं जो विफलता से संबंधित हैं:

$ go test
--- FAIL: TestAdd (0.00s)
    --- FAIL: TestAdd/4+5 (0.00s)
        add_test.go:35: got 9 want 0
            
            Execution Logs:
            2020/09/05 09:22:48 add 4 5
            2020/09/05 09:22:48 add 4 5 = 9
            
FAIL
exit status 1

अपने फ़ंक्शनों को ग्लोबल लॉगर से अलग (decouple) करके, हम अपने कोड को अधिक लचीला, अपने टेस्ट सुइट्स को अधिक शांत, और अपनी डीबगिंग प्रक्रिया को काफ़ी तेज़ बनाते हैं।


📚 मेरी निःशुल्क ई-बुक डाउनलोड करें 🔗

काउए की जीवनशैली का क्यूरेटेड ऑफ़लाइन संस्करण प्राप्त करें—🍏 स्वास्थ्य, 💰 धन, ❤️ प्रेम और 🧘 अर्थ को बेहतर बनाने के लिए एक व्यावहारिक मार्गदर्शिका।

काउए की जीवनशैली

काउए की जीवनशैली

📬 न्यूज़लेटर की सदस्यता लें 🔗

जब भी मैं बेहतर जीवन जीने पर नए निबंध, पुस्तक सारांश और व्यावहारिक गाइड प्रकाशित करूँ, तो सूचना प्राप्त करें। कोई स्पैम नहीं—कभी भी सदस्यता समाप्त करें।


💬 टिप्पणियाँ और चर्चा 🔗

क्या आपका कोई प्रश्न, दृष्टिकोण या सुझाव है? नीचे अपने विचार साझा करें। टिप्पणियाँ GitHub Discussions (विज्ञापन-मुक्त और स्पैम-मुक्त) द्वारा संचालित हैं—टिप्पणी करने या प्रतिक्रिया देने के लिए नीचे Sign in with GitHub पर क्लिक करें (निःशुल्क GitHub खाता बनाने में एक मिनट से भी कम समय लगता है)।



अंतिम अपडेट: 11 अक्टू॰ 2026.

अस्वीकरण (DISCLAIMER): इस साइट की सामग्री केवल सूचनात्मक और शैक्षिक उद्देश्यों के लिए है और यह चिकित्सा, मनोवैज्ञानिक, वित्तीय, निवेश, कर या कानूनी सलाह का गठन नहीं करती है। यहाँ प्रस्तुत विचार, संकलन और राय पूरी तरह से मेरे अपने हैं और मेरे नियोक्ता का प्रतिनिधित्व नहीं करते हैं। पुस्तकों, व्याख्यानों और लेखों के सारांश स्वतंत्र शैक्षिक टिप्पणियाँ हैं और उनके संबंधित लेखकों की बौद्धिक संपदा बने रहते हैं। संपादन, स्वरूपण और संश्लेषण में सहायता के लिए AI उपकरणों का उपयोग किया जा सकता है; यद्यपि सटीकता सुनिश्चित करने का हर संभव प्रयास किया जाता है, फिर भी त्रुटियाँ हो सकती हैं। गोपनीयता (PRIVACY): यह साइट वैकल्पिक न्यूज़लेटर सदस्यता (follow.it), टिप्पणियों (giscus / GitHub Discussions) और एम्बेडेड मीडिया (YouTube) के लिए तृतीय-पक्ष सेवाओं का उपयोग करती है, जो अपनी संबंधित गोपनीयता नीतियों के अनुसार आगंतुकों के IP पते और कुकीज़ को संसाधित कर सकती हैं।