2013-06-05 5 views
7

मैं कुछ कोड का यूनिट परीक्षण करने के लिए Moq का उपयोग कर रहा हूं जिसमें Parallel.foreach लूप शामिल है।एक .NET इकाई परीक्षण एक समानांतर .foreach लूप हार्डवेयर-निर्भर को कवर क्यों करता है?

व्यवस्थित करें चरण लूप के भीतर फेंकने के लिए 4 अपवाद सेट करता है और फिर AggregateException में लपेटा जाता है।

यह मेरे i7 प्रोसेसर पर पारित हुआ और मैंने कोड में चेक किया।

बाद में, एक सहयोगी ने शिकायत की कि वह उसके लिए गुजर रहा नहीं है। यह Parallel.foreach बाहर निकलने से पहले अपने कोर 2duo पर केवल 2 धागे पैदा कर रहा था और इसलिए AggregateException में केवल 2 अपवाद लपेट गए थे।

सवाल यह है कि इस बारे में क्या करना है ताकि इकाई परीक्षण प्रोसेसर आर्किटेक्चर पर निर्भर न हो? विचारों के एक जोड़े: -

  1. मैन्युअल AggregateException के अपवाद जोड़ने पर कोई Microsoft article है, लेकिन हम पाश के रूप में यह कर जल्द से जल्द अवसर पर बाहर निकलने चाहिए अगर वहाँ एक समस्या है के लिए उत्सुक नहीं कर रहे हैं।
  2. ParallelOptions.MaxDegreeOfParallelism उपयोग किए गए धागे की संख्या पर ऊपरी सीमा डाल सकते हैं। लेकिन इस जब तक 1 को ठुकरा दिया है कि कैसे इकाई परीक्षण पता कर सकते हैं कि कितने धागे वास्तव में इस्तेमाल किया जाएगा और इसलिए की स्थापना व्यवस्था और जोर चरणों propertly (जो और अधिक उचित इकाई परीक्षण की तुलना में धोखाधड़ी की तरह लगता है)?
+2

बाल अपवादों की संख्या एक आवश्यकता नहीं है और इस तरह से परीक्षण नहीं किया जाना चाहिए। यह एक कार्यान्वयन विस्तार है। आप सही प्रकार के 1+ अपवादों की जांच कर सकते हैं। –

+0

@ हेंकहोल्टरमैन ट्रू लेकिन मुझे उचित रूप से नकली सेट अप करना होगा। क्या आप सुझाव दे रहे हैं कि मुझे अधिकतम संख्या में नकली कॉल के लिए सेट अप करना चाहिए, लेकिन यह नहीं कहें कि इन सभी को वास्तव में अंत में बुलाया गया था? –

+0

मुझे यकीन नहीं है कि आप किस भाग को नकल करना चाहते हैं लेकिन इससे कोई फर्क नहीं पड़ता। –

उत्तर

6

आपको ऐसा कुछ परीक्षण नहीं करना चाहिए - यह कार्यान्वयन विस्तार है।

बात है - Parallel.ForEach तब तक तत्वों को संसाधित करेगा जब तक कि यह अपवाद न हो। जब अपवाद होता है तो यह किसी भी नए तत्व को संसाधित करना बंद कर देगा (लेकिन वर्तमान में संसाधित किए गए लोगों की प्रसंस्करण समाप्त हो जाएगा) और फिर AgregateException फेंक दें।

अब - आपके आई 7 सीपीयू में 4 कोर + हाइपर थ्रेडिंग है, जिसके परिणामस्वरूप प्रसंस्करण के लिए अधिक धागे उत्पन्न होते हैं, इस प्रकार आप अधिक अपवाद प्राप्त कर सकते हैं (उदाहरण के लिए अपवाद होने पर 4 चीजों को संसाधित किया जा सकता है)। लेकिन Core2Duo पर केवल 2 कोर के साथ, केवल 2 आइटम एक ही समय में संसाधित किए जाएंगे (ऐसा इसलिए है क्योंकि टीपीएल प्रोसेसिंग के लिए पर्याप्त थ्रेड बनाने के लिए पर्याप्त स्मार्ट है, उपलब्ध कोर से अधिक नहीं)।

परीक्षण वास्तव में 4 अपवाद होने पर आपको कोई ज्ञान नहीं मिलता है। यह मशीन निर्भर है। यदि आपको कम से कम एक अपवाद हुआ तो आपको इसकी जांच करनी चाहिए - क्योंकि आप यही उम्मीद कर रहे हैं। यदि भविष्य का उपयोगकर्ता पुरानी एकल कोर मशीन पर आपका कोड चलाएगा तो वह AggregateException में केवल एक अपवाद प्राप्त करेगा।

फेंक दिया अपवाद की संख्या मशीन विशिष्ट है, उदाहरण के लिए गणना समय - आप इस बात पर जोर नहीं देंगे कि कितनी देर की गणना की गई थी, इसलिए आपको इस मामले में अपवाद की संख्या पर जोर नहीं देना चाहिए।

+2

बीटीडब्ल्यू, यह सिर्फ सीपीयू के बारे में नहीं है। विशिष्ट व्यवहार थ्रेडपूल पर एक ही प्रक्रिया में और क्या चल रहा है, इस पर निर्भर करता है कि सीपीयू का उपयोग करने वाली अन्य प्रक्रियाएं क्या हैं, चाहे लूप में ऑपरेशन अवरुद्ध हो रहा है और संभवतः अन्य चीजें हैं। – svick

+0

हां, यह पूरी तरह से सच है। सीपीयू रिश्ते सिर्फ स्थान के लिए सबसे आसान है, लेकिन आपने जो भी उल्लेख किया है वह भी मान्य है। – Pako

+0

@Pako धन्यवाद - आपका उत्तर समस्या को बहुत अच्छी तरह से बताता है। जैसा कि मैं इसे समझता हूं, आपका समाधान अधिकतम अपवाद (= धागे) की अनुमति देने के लिए नकली सेट करना है, लेकिन फिर वास्तव में यह नहीं कहता कि वे सभी हुए हैं। ऐसा लगता है कि आम तौर पर जब मैं मजाक कर रहा हूं तो मुझे लगता है कि मैं सभी सेटअप को सत्यापित करने के लिए उपयोग किया जाता है। –

1

यूनिट परीक्षण सत्यापित करता है कि आप क्या होने की उम्मीद कर रहे हैं और वास्तव में क्या होता है वही बात है। इसका मतलब है कि आपको खुद से पूछना होगा कि आप क्या होने की उम्मीद कर रहे हैं।

यदि आप उम्मीद करते हैं कि प्रसंस्करण में सभी संभावित त्रुटियों की सूचना दी जाएगी, तो आपके सहयोगी के रन को वास्तव में आपके कोड में एक बग मिला।इसका मतलब यह है कि सादा Parallel.ForEach() आपके लिए काम नहीं करेगा, लेकिन Parallel.ForEach() जैसे try - catch और कस्टम अपवाद प्रोसेसिंग के साथ कुछ ऐसा होगा।

यदि आप उम्मीद करते हैं कि प्रत्येक फेंक दिया गया अपवाद पकड़ा जाएगा, तो यही आपको परीक्षण करने की आवश्यकता है। यह आपके परीक्षण को जटिल कर सकता है या आप अपवादों को फेंकने के तरीके के आधार पर परीक्षण करना संभव नहीं हो सकता है। इस के लिए एक साधारण परीक्षण इस प्रकार दिखाई देगा:

[Test] 
public void ParallelForEachExceptionsTest() 
{ 
    var exceptions = new ConcurrentQueue<Exception>(); 
    var thrown = Assert.Throws<AggregateException>(
     () => Parallel.ForEach(
      Enumerable.Range(1, 4), i => 
      { 
       var e = new Exception(i.ToString()); 
       exceptions.Enqueue(e); 
       throw e; 
      })); 

    CollectionAssert.AreEquivalent(exceptions, thrown.InnerExceptions); 
} 

क्या आप उम्मीद करते हैं कि जब एक या अधिक अपवाद फेंक दिया जाता है, तो उनमें से कम से कम कुछ पकड़ा हो जाएगा, तो यह है कि आप क्या परीक्षण करना चाहिए है, और आप अगर सभी अपवादों को सही ढंग से पकड़ा गया तो चिंता न करें।

+0

पर काम करने के लिए साबित कर दिया है। यहां आपके प्रयासों के लिए बहुत धन्यवाद। यह दूसरा मामला है - प्रत्येक * फेंक दिया * अपवाद पकड़ा जाना चाहिए। फेंकने वाले अपवाद वास्तव में एक मॉक ऑब्जेक्ट पर एक विधि कॉल से आ रहे हैं। तो जैसा कि आप कहते हैं, मुझे बस यह सत्यापित करने की आवश्यकता है कि इनमें से एक सबसेट वास्तव में फेंक दिया गया है। –

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