2009-06-01 14 views
35

मेरे पास यह जांचने के लिए एक इकाई परीक्षण है कि कोई विधि सही IEnumerable देता है या नहीं। विधि yield return का उपयोग करके गणना करने योग्य बनाता है। वर्ग इसके बारे में एक गणनीय है कि नीचे है:Assert.AreEqual दो जेनेरिक IENumerables के बीच समानता निर्धारित करता है?

enum TokenType 
{ 
    NUMBER, 
    COMMAND, 
    ARITHMETIC, 
} 

internal class Token 
{ 
    public TokenType type { get; set; } 
    public string text { get; set; } 
    public static bool operator == (Token lh, Token rh) { return (lh.type == rh.type) && (lh.text == rh.text); } 
    public static bool operator != (Token lh, Token rh) { return !(lh == rh); } 
    public override int GetHashCode() 
    { 
     return text.GetHashCode() % type.GetHashCode(); 
    } 
    public override bool Equals(object obj) 
    { 
     return this == (Token)obj; 
    } 
} 

इस विधि के प्रासंगिक हिस्सा है: यदि मैं actual में इस विधि के परिणाम की दुकान

foreach (var lookup in REGEX_MAPPING) 
{ 
    if (lookup.re.IsMatch(s)) 
    { 
     yield return new Token { type = lookup.type, text = s }; 
     break; 
    } 
} 

, एक और गणनीय expected बनाने के लिए, और उन्हें इस तरह तुलना करें ...

Assert.AreEqual(expected, actual); 

..., दावा विफल रहता है।

मैं IEnumerable के लिए एक विस्तार विधि ने लिखा है कि Python's zip function के समान है (यह जोड़ों का एक समूह में दो IEnumerables को जोड़ती है) और इस की कोशिश की:

foreach(Token[] t in expected.zip(actual)) 
{ 
    Assert.AreEqual(t[0], t[1]); 
} 

यह काम किया! तो इन दो Assert.AreEqual एस के बीच क्या अंतर है?

+1

@Jason बेकर: यह गलत नहीं लेते हैं तो कृपया वैसे, क्या आपने सोचा है कि इस तथ्य को आपको इस तरह के सवाल पूछना है, इसका मतलब यह हो सकता है कि आप चीजों को बहुत जटिल बना रहे हैं? –

+1

एआरएम ... नहीं, वास्तव में नहीं। :-) क्या आप मुझे इंगित कर सकते हैं कि मैं कहां जटिल बना रहा हूं? –

+0

इसके अलावा, मुझे विश्वास नहीं है कि "text.GetHashCode()% type.GetHashCode();" GetHashCode() के लिए वापसी मूल्य के रूप में एक अच्छा विचार है ... –

उत्तर

25

Assert.AreEqual हाथों की दो वस्तुओं की तुलना करने जा रहा है। IEnumerable एस अपने आप में और अपने प्रकार के हैं, और कुछ संग्रह पर पुनरावृत्ति करने के लिए एक तंत्र प्रदान करते हैं ... लेकिन वे वास्तव में संग्रह नहीं हैं। आपकी मूल तुलना दो IEnumerable एस की तुलना में की गई है, जो एक वैध तुलना है ... लेकिन आपको जो चाहिए वह नहीं। आपको की तुलना करने की आवश्यकता है जो IEnumerable एस को गिनने का इरादा था।

यहाँ कैसे मैं दो enumerables तुलना है:

Assert.AreEqual(t1.Count(), t2.Count()); 

IEnumerator<Token> e1 = t1.GetEnumerator(); 
IEnumerator<Token> e2 = t2.GetEnumerator(); 

while (e1.MoveNext() && e2.MoveNext()) 
{ 
    Assert.AreEqual(e1.Current, e2.Current); 
} 

मैं यकीन नहीं है कि इसके बाद के संस्करण अपने .Zip विधि की तुलना में कम कोड है नहीं कर रहा हूँ, लेकिन यह के रूप में यह हो जाता है के बारे में के रूप में सरल है।

+0

यह समझ में आता है। क्या ऑब्जेक्ट द्वारा दो आईएन्यूमेरेबल्स ऑब्जेक्ट की तुलना करने के लिए कोई तरीका नहीं है, जितना अधिक कोड लिखने के बिना? –

+0

मैं बस थोड़ी देर लूप का उपयोग करूंगा। मैंने एक उदाहरण के साथ अपना जवाब अपडेट कर लिया है। – jrista

+0

मुझे एक और तरीका मिला जो काम करता है और सरल है। मैं इसे स्वीकार करूंगा क्योंकि आपने दिखाया कि मेरा कोड क्यों काम नहीं कर रहा था। :-) –

86

यह मिला:

Assert.IsTrue(expected.SequenceEqual(actual)); 
+0

अच्छा लगता है! मुझे यह भी पता नहीं था कि एक अनुक्रमिक() एक्सटेंशन था। Ty! – jrista

+0

बहुत बहुत धन्यवाद। आपने मेरे लूप को बचाया ;-) –

+3

यह आपको इस बारे में कोई जानकारी नहीं देगा कि परीक्षण विफल होने पर कौन सा तत्व असमान था; यह आपको बताएगा कि यह असफल रहा। Jerryjvl द्वारा सुझाए गए CollectionAssert तंत्र में अधिक समृद्ध विफलता जानकारी मिलती है। – bacar

47

आप के बजाय CollectionAssert वर्ग का उपयोग कर विचार किया है ... यह देखते हुए कि यह संग्रह पर समानता जांच करने के लिए करना है?

परिशिष्ट:
'संग्रह' तुलना की जा रही enumerations हैं, तो बस उन्हें 'new List<T>(enumeration)' के साथ लपेटकर तुलना करने का सबसे आसान तरीका है। एक नई सूची का निर्माण निश्चित रूप से कुछ ओवरहेड का कारण बनता है, लेकिन यूनिट परीक्षण के संदर्भ में इससे कोई फर्क नहीं पड़ता कि मुझे उम्मीद है?

+0

संग्रह एस्र्टर्ट में सभी विधियां आईसीओलेक्शन के खिलाफ तुलना करने के लिए सेट हैं। मेरे पास IENumerables है। क्या उन्हें आईसीओलेक्शन में बदलने का कोई आसान तरीका है? –

+0

ऐसे मामलों में मैं आमतौर पर एक 'नई सूची (गणना)' में एक त्वरित रैप-अप करता हूं ताकि मैं तुलना कर सकूं। ऐसा नहीं है कि ओवरहेड यूनिट टेस्ट के संदर्भ में एक समस्या होने की संभावना है। – jerryjvl

+6

संग्रह एएसएसर्ट का उपयोग करते समय बस दोनों तर्कों पर .ToArray() करें। – MEMark

18

मैं समानता आप चाहते हैं का दावा करने की सबसे सरल और स्पष्ट रास्ता लगता है jerryjvl से जवाब का एक संयोजन है और MEMark द्वारा अपने पोस्ट पर टिप्पणी - विस्तार के तरीकों के साथ CollectionAssert.AreEqual गठबंधन:

CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); 

यह अमीर त्रुटि देता है ओपी द्वारा सुझाए गए अनुक्रमिक उत्तर के मुकाबले की जानकारी (यह आपको बताएगी कि कौन सा तत्व पाया गया था जो अप्रत्याशित था)।उदाहरण के लिए: - कभी कभी आप भी पता कर सकते हैं डिबगर बाहर तोड़ के बिना क्या गलत है -

IEnumerable<string> expected = new List<string> { "a", "b" }; 
IEnumerable<string> actual = new List<string> { "a", "c" }; // mismatching second element 

CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); 
// Helpful failure message! 
// CollectionAssert.AreEqual failed. (Element at index 1 do not match.)  

Assert.IsTrue(expected.SequenceEqual(actual)); 
// Mediocre failure message: 
// Assert.IsTrue failed. 

आप वास्तव में प्रसन्न आप इसे इस तरह से किया था यदि/जब अपने परीक्षण में विफल रहता है हो जाएगा और हे आप कर रहे हैं टीडीडी सही कर रहे हैं, तो आप पहले एक असफल परीक्षण लिखते हैं, है ना? ;-)

त्रुटि संदेश और भी अधिक उपयोगी मिल अगर आप AreEquivalent का उपयोग कर रहे तुल्यता के लिए परीक्षण करने के लिए (क्रम आवश्यक नहीं है):

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); 
// really helpful error message! 
// CollectionAssert.AreEquivalent failed. The expected collection contains 1 
// occurrence(s) of <b>. The actual collection contains 0 occurrence(s). 
संबंधित मुद्दे