Soheil Hassas:
done := make(chan bool)
// Send notification event.
mock.devices <- Job {
Data: []sparkapi.Device{deviceA, deviceFuncs, deviceRefresh},
Done: done,
}
// Wait until `done` is closed.
<-done
// Check that no refresh method was called.
c.Check(mock.actionArgs, check.DeepEquals, mockFunctionCall{})
इस पद्धति का प्रयोग करके आप अपने परीक्षण के लिए एक टाइमआउट लागू कर सकते हैं Yeganeh का समाधान आमतौर पर जाने के लिए एक अच्छा तरीका है, या कम से कम कुछ ऐसा है। लेकिन यह एपीआई में एक बदलाव है, और यह कॉलर के लिए कुछ ओवरहेड बना सकता है (हालांकि ज्यादा नहीं; कॉलर को Done
चैनल पास करने के लिए कॉलर की आवश्यकता नहीं है)। उस ने कहा, ऐसे मामले हैं जहां आप उस तरह की एसीके प्रणाली नहीं चाहते हैं।
मैं इस तरह की समस्या के लिए परीक्षण पैकेज Gomega की अत्यधिक अनुशंसा करता हूं। यह Ginkgo के साथ काम करने के लिए डिज़ाइन किया गया है, लेकिन इसका उपयोग स्टैंडअलोन किया जा सकता है। इसमें Consistently
और Eventually
मैचर्स के माध्यम से उत्कृष्ट एसिंक समर्थन शामिल है।
यह कहा गया है, जबकि गोमेगा गैर-बीडीडी परीक्षण प्रणाली के साथ अच्छी तरह से काम करता है (और testing
में ठीक से एकीकृत करता है), यह एक बहुत बड़ी बात है और यह प्रतिबद्धता हो सकती है। यदि आप बस एक टुकड़ा चाहते हैं, तो आप इन दावों का अपना संस्करण लिख सकते हैं। मैं गोमेगा के दृष्टिकोण के बाद निम्नलिखित अनुशंसा करता हूं, जो केवल एक नींद की बजाय मतदान कर रहा है (यह अभी भी सोता है; इसे आपके एपीआई को फिर से डिजाइन किए बिना ठीक करना संभव नहीं है)।
यहां परीक्षण के लिए चीजों को देखने का तरीका बताया गया है।
http://play.golang.org/p/qpdEOsWYh0
const iterations = 10
const interval = time.Millisecond
func Consistently(f func()) {
for i := 0; i < iterations; i++ {
f() // Assuming here that `f()` panics on failure
time.Sleep(interval)
}
}
mock.devices <- []sparkapi.Device{deviceA, deviceFuncs, deviceRefresh}
Consistently(c.Check(mock.actionArgs, check.DeepEquals, mockFunctionCall{}))
जाहिर है आप पुनरावृत्तियों और अंतराल अपनी आवश्यकताओं से मिलान करने के लिए परिवर्तित कर सकते हैं: आप की तरह एक सहायक समारोह पैदा करते हैं। (गोमेगा एक 10 सेकंड टाइमआउट का उपयोग करता है, प्रत्येक 10 एमएमएस मतदान करता है।)
Consistently
के किसी भी कार्यान्वयन का नकारात्मक हिस्सा यह है कि जो भी आपका टाइमआउट है, आपको हर टेस्ट रन खाना पड़ेगा। लेकिन इसके आसपास वास्तव में कोई रास्ता नहीं है। आपको यह तय करना होगा कि "ऐसा नहीं होने के लिए कितना समय लंबा है।" जब संभव हो, Eventually
की जांच के लिए अपने परीक्षण को चालू करना अच्छा होता है, क्योंकि यह तेजी से सफल हो सकता है।
Eventually
थोड़ा अधिक जटिल है, क्योंकि आपको पैनिक्स को सफल होने तक recover
का उपयोग करने की आवश्यकता होगी, लेकिन यह बहुत बुरा नहीं है।कुछ इस तरह:
func Eventually(f func()) {
for i := 0; i < iterations; i++ {
if !panics(f) {
return
}
time.Sleep(interval)
}
panic("FAILED")
}
func panics(f func()) (success bool) {
defer func() {
if e := recover(); e != nil {
success = true
}
}()
f()
return
}
अंत में, यह सिर्फ तुम्हारे पास क्या है के लिए थोड़ी ज्यादा जटिल संस्करण है, लेकिन यह एक समारोह में तर्क लपेटता इसलिए यह थोड़ा बेहतर पढ़ता।
मैं सवाल को सरल रखने की कोशिश कर रहा था, लेकिन शायद मैंने इसे खत्म कर दिया .. मैं एक घटक को डेटा भेज रहा हूं जो अन्य घटकों को पास कर सकता है, जो अन्य घटकों को पारित कर सकता है। पास ऑफ चेन में शाखाएं और कांटे और सभी प्रकार की जटिलता शामिल हो सकती है। इससे यह (अन्यथा उत्कृष्ट) सुझाव इतना उपयोगी नहीं होता है। – DonGar
हाँ, यह बात है। श्रृंखला में आपके सभी घटकों को अपने एआईएनएनसी नौकरी के हिस्से के रूप में 'किया गया' चैनल प्राप्त करना चाहिए। अन्यथा, आप सीपीयू को बर्बाद कर देंगे और आपके जाने-माने जाने के लिए जागना और मतदान करना होगा। –
@ डोंगर आप 'शुद्ध/संदर्भ' और http://blog.golang.org/pipelines में रुचि भी ले सकते हैं। जटिल क्रॉस-घटक श्रृंखलाओं के लिए कुछ बहुत अच्छे मौजूदा गो पैटर्न हैं। (टेस्टेबिलिटी सवाल नहीं बदलता है, लेकिन आपके समवर्ती डिजाइन को प्रभावित कर सकता है।) –