प्रतिनिधि इंटरव्यू विषय

कोडिंग इंटरव्यू: आप testing/synctest के साथ कंकरेंट Go कोड का परीक्षण कैसे करेंगे?

कोडिंगकठिन
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

टाइमआउट, बैकग्राउंड रीट्रीज और context.AfterFunc वाले एक Go फ़ंक्शन का परीक्षण करें। टेस्ट वास्तविक स्लीप के बिना तेज़ और दोहराने योग्य होना चाहिए। testing/synctest बबल, वर्चुअल टाइम, Wait, कैंसलेशन सेमेंटिक्स और उन मामलों की व्याख्या करें जिन्हें अभी भी वास्तविक इंटीग्रेशन टेस्ट की आवश्यकता है।

प्रॉम्प्ट और दायरा

फ़ंक्शन एक बैकग्राउंड गोरूटीन शुरू करता है, एक्सपोनेंशियल बैकऑफ के साथ पुन: प्रयास (retry) करता है, और टाइमआउट होने पर context.AfterFunc के माध्यम से परिणाम रिकॉर्ड करता है। time.Sleep का उपयोग करने वाले टेस्ट धीमे, अस्थिर (flaky) होते हैं, या बैकग्राउंड कार्य छोड़ देते हैं। डिटरमिनिस्टिक टेस्ट डिज़ाइन करने के लिए Go testing/synctest का उपयोग करें, और एक्सपेरिमेंट बनाम स्टेबल API, गोरूटीन लीक, वास्तविक I/O और क्लॉक सीमाओं को कवर करें।

API और वर्शन लक्षित Go रिलीज़ से मेल खाना चाहिए। यह बैकएंड कोडिंग, कंकरेंसी लाइब्रेरी और इंफ्रास्ट्रक्चर भूमिकाओं के अनुकूल है। मुख्य कौशल डिटरमिनिस्टिक कंकरेंट टेस्टिंग है, इसलिए यह coding से संबंधित है।

इंटरव्यूअर्स क्या आंकते हैं

पहला, क्या आप synctest बबल को समझते हैं? यह गोरूटीन्स और समय को अलग करता है, जबकि Wait बबल के अंदर के कार्य को स्थिरता (quiescence) तक पहुँचने देता है।

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

तीसरा, क्या आप कैंसलेशन और क्लीनअप का परीक्षण कर सकते हैं? संदर्भ (context) कैंसलेशन, एक AfterFunc कॉलबैक, और रीट्री गोरूटीन्स को टेस्ट समाप्त होने से पहले पूरा होना चाहिए या स्पष्ट रूप से रोका जाना चाहिए।

चौथा, क्या आप वर्शन के अंतर को संभाल सकते हैं? Go 1.24 ने synctest को एक फ्लैग के पीछे प्रयोगात्मक रूप से प्रदर्शित किया; Go 1.25 स्थिर API प्रदान करता है। CI में वर्शन पिन होना चाहिए।

पाँचवाँ, क्या आप इंटीग्रेशन कवरेज बनाए रख सकते हैं? वर्चुअल-टाइम टेस्ट तार्किक क्रम की पुष्टि करते हैं, वास्तविक प्रोसेस में HTTP, डेटाबेस, शेड्यूलर या रेस-डिटेक्टर व्यवहार की नहीं।

पहले स्पष्ट करने योग्य प्रश्न

  • क्या CI, Go 1.24 एक्सपेरिमेंट का उपयोग करता है या Go 1.25 स्टेबल API का?
  • क्या सभी टेस्ट गोरूटीन्स बबल के अंदर बनाए गए हैं?
  • क्या रीट्रीज time.After, एक टाइमर, या किसी बाहरी शेड्यूलर का उपयोग करते हैं?
  • कैंसलेशन के बाद, क्या वर्तमान I/O समाप्त हो सकता है या इसे तुरंत वापस लौटना चाहिए?
  • क्या हमें वास्तविक नेटवर्क लेटेंसी, डेटाबेस लॉक और रेस कवरेज की आवश्यकता है?
  • क्या कोड एक क्लॉक या डिपेंडेंसी इंटरफ़ेस प्राप्त कर सकता है, या मौजूदा फ़ंक्शन को रैप किया जाना चाहिए?

30-सेकंड उत्तर ढांचा

“मैं फ़ंक्शन को एक synctest.Test बबल के अंदर चलाऊँगा, बैकऑफ और डेडलाइन के माध्यम से वर्चुअल टाइम को आगे बढ़ाऊँगा, और स्थिरता के लिए synctest.Wait का उपयोग करूँगा। मैं रीट्री काउंट, अंतिम एरर, वन-टाइम AfterFunc व्यवहार, और कैंसलेशन के बाद कोई कार्य शेष न रहने का सत्यापन (assert) करूँगा। Go 1.24 के लिए एक्सपेरिमेंट फ्लैग की आवश्यकता होती है; Go 1.25 में स्टेबल API है, इसलिए CI इसे पिन करता है। वास्तविक HTTP, डेटाबेस, शेड्यूलर और रेस जांचें अलग से चलती हैं क्योंकि वे बबल द्वारा स्वचालित रूप से नियंत्रित नहीं होती हैं।”

चरण-दर-चरण उत्तर

चरण 1: वर्शन और API पिन करें

Go 1.24 का testing/synctest प्रयोगात्मक था और इसके लिए GOEXPERIMENT=synctest की आवश्यकता थी; Go 1.25 मानक Test और Wait API प्रदान करता है। go.mod, CI इमेज और कमांड-लाइन वातावरण को पिन करें ताकि स्थानीय और CI सेमेंटिक्स मेल खाएँ।

चरण 2: कार्य को बबल के अंदर रखें

टेस्ट फ़ंक्शन के बाहर अनियंत्रित कार्य शुरू करने के बजाय बबल के अंदर प्रत्येक टेस्ट गोरूटीन बनाएं। बबल को कैंसलेशन, चैनल क्लोजर और रिसोर्स क्लीनअप का स्वामित्व रखना चाहिए, और इसके बाहर निकलने से पहले सभी कार्यों को वापस लौटना चाहिए।

go
func TestRetryTimeout(t *testing.T) {
  synctest.Test(t, func(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    got := runWithRetry(ctx)
    synctest.Wait()
    // Advance virtual time and assert retry/timeout state here.
    _ = got
  })
}

चरण 3: वर्चुअल टाइम को आगे बढ़ाएं

बैकऑफ के लिए वास्तविक time.Sleep का उपयोग न करें। बबल क्लॉक को अगले टाइमर या स्पष्ट डेडलाइन तक आगे बढ़ाएं, फिर Wait को कॉल करें ताकि निष्पादन योग्य गोरूटीन्स रन हो सकें। कई सीमाओं को छोड़ने के बजाय प्रत्येक प्रगति के बाद जांच (assert) करें, अन्यथा विफल होने वाला ट्रांजिशन छिप जाएगा।

चरण 4: AfterFunc और कैंसलेशन सत्यापित करें

कैंसलेशन होने पर context.AfterFunc एक कॉलबैक गोरूटीन शुरू करता है। कॉलबैक काउंट और देखे गए एरर को रिकॉर्ड करें, फिर कैंसलेशन के बाद Wait को कॉल करें। यदि फ़ंक्शन बार-बार कॉलबैक पंजीकृत करता है, तो सत्यापित करें कि कैंसलेशन पाथ केवल डिज़ाइन किए गए साइड इफेक्ट्स ही उत्पन्न करता है।

चरण 5: रीट्रीज और अंतिम परिणामों को कवर करें

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

चरण 6: बबल सीमाओं की जांच करें

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

चरण 7: अन्य सत्यापन उपकरणों को संयोजित करें

Synctest तार्किक समय (timing) को कवर करता है। go test -race डेटा रेस की जांच करता है, जबकि वास्तविक HTTP और डेटाबेस टेस्ट कनेक्शन, डेडलाइन और प्रोटोकॉल व्यवहार की जांच करते हैं। टेस्ट अवधि, रीट्री सीमाओं और टास्क कन्वर्जेंस को ट्रैक करें ताकि टेस्ट चुपचाप लीक न हों या धीमे न हों।

मॉडल उत्तर

“मैं पहले Go वर्शन को पिन करूँगा। Go 1.24 के synctest को एक एक्सपेरिमेंट फ्लैग की आवश्यकता होती है; Go 1.25 स्टेबल synctest.Test और synctest.Wait का उपयोग करता है। मैं बबल के अंदर सभी टेस्ट गोरूटीन्स बनाऊँगा, एक विफलता अनुक्रम इंजेक्ट करूँगा, बैकऑफ और डेडलाइन के माध्यम से वर्चुअल टाइम को आगे बढ़ाऊँगा, प्रत्येक प्रगति के बाद स्थिरता की प्रतीक्षा करूँगा, और कॉल्स, एरर्स, कॉलबैक्स व कैंसलेशन क्लीनअप का सत्यापन करूँगा।

मैं वास्तविक स्लीप का उपयोग नहीं करूँगा और न ही बबल के बाहर नेटवर्क, डेटाबेस या तीसरे पक्ष के गोरूटीन्स को वर्चुअल-टाइम कार्य के रूप में मानूँगा। उन पाथ्स को लॉजिक टेस्ट के लिए इंटरफ़ेस फेक मिलते हैं और प्रोटोकॉल, लॉक व रेस के लिए वास्तविक इंटीग्रेशन और go test -race मिलते हैं। टेस्ट को यह साबित करना होगा कि बाहर निकलते समय कोई बबल टास्क शेष नहीं रहता है।”

सामान्य गलतियाँ

  • बबल के अंदर time.Sleep रखना → टेस्ट धीमे और गैर-डिटरमिनिस्टिक बने रहते हैं → वर्चुअल टाइम को आगे बढ़ाएं।
  • केवल अंतिम परिणाम का सत्यापन करना → रीट्रीज और कैंसलेशन क्लीनअप गलत हो सकते हैं → टाइमर, कॉल्स और कॉलबैक्स को चरण-दर-चरण सत्यापित करें।
  • बबल के बाहर गोरूटीन्स शुरू करना → कन्वर्जेंस की प्रतीक्षा नहीं की जा सकती → बबल को कार्य का स्वामी बनाएं।
  • वास्तविक नेटवर्क को वर्चुअल टाइम के रूप में मानना → I/O अस्थिर बना रहता है → फेक और अलग इंटीग्रेशन टेस्ट का उपयोग करें।
  • 1.24/1.25 API अंतरों को अनदेखा करना → स्थानीय और CI बिल्ड में अंतर आ जाता है → Go और एक्सपेरिमेंट फ्लैग को पिन करें।
  • रेस डिटेक्टर को छोड़ना → डेटा रेस शेष रहने के बावजूद टाइमिंग सही हो सकती है → go test -race को संयोजित करें।
  • कैंसलेशन के बाद पुन: प्रयास करना → अनुरोध और संसाधन उपयोग बढ़ते हैं → प्रत्येक प्रतीक्षा और कॉल से पहले संदर्भ (context) की जांच करें।
  • सभी असर्शन के लिए एक अंतिम Wait का उपयोग करना → विफलता की सीमाएं स्पष्ट नहीं होती हैं → चरणों में आगे बढ़ें और सत्यापित करें।

फ़ॉलो-अप प्रश्न

फ़ॉलो-अप 1: क्या synctest रियल-टाइम टेस्टिंग की जगह लेता है?

नहीं। यह नियंत्रित कंकरेंट लॉजिक और टेम्पोरल संबंधों को सत्यापित करता है; क्लॉक्स, नेटवर्क, डेटाबेस और शेड्यूलर को अभी भी वास्तविक-वातावरण परीक्षणों की आवश्यकता होती है।

फ़ॉलो-अप 2: Wait को कॉल क्यों करें?

वर्चुअल टाइम को आगे बढ़ाने से टाइमर समाप्त हो जाते हैं; Wait बबल में निष्पादन योग्य गोरूटीन्स को तब तक चलाता है जब तक वे स्थिरता तक नहीं पहुँच जाते, जिससे असर्शन स्थिर हो जाते हैं।

फ़ॉलो-अप 3: आप स्थायी ब्लॉकिंग का परीक्षण कैसे करते हैं?

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

फ़ॉलो-अप 4: क्या Go 1.24 एक्सपेरिमेंट का उपयोग प्रोडक्शन में किया जा सकता है?

यह नियंत्रित टेस्ट का समर्थन कर सकता है, लेकिन एक्सपेरिमेंट स्थिति, फ्लैग और अपग्रेड जोखिम स्पष्ट होना चाहिए। स्थिर संगतता के लिए, Go 1.25 API को प्राथमिकता दें और CI को पिन करें।

फ़ॉलो-अप 5: आप बबल के बाहर लीक कैसे ढूंढते हैं?

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

फ़ॉलो-अप 6: आप बैकऑफ ड्रिफ्ट का पता कैसे लगाते हैं?

प्रत्येक कॉल के वर्चुअल टाइमस्टैम्प को रिकॉर्ड करें और अपेक्षित अनुक्रम के साथ इसकी तुलना करें। साथ ही अंतिम प्रतीक्षा के डेडलाइन ट्रंकेशन और प्रारंभिक कैंसलेशन का परीक्षण करें।

सार्वजनिक स्रोत

संबंधित प्रश्न

संबंधित इंटरव्यू टूल

कोडिंग प्रॉम्प्ट के लिए स्क्रीनशॉट का उपयोग करें

समस्या को कैप्चर करें, फिर क्रम से प्रतिबंधों (constraints), समाधान, कोड, एज केस और जटिलता पर काम करें।

टूल देखें