2013-10-04 8 views
37
NSMutableArray *arr = [NSMutableArray array]; 
[arr addObject:@"1"]; 
[arr addObject:@"2"]; 
[arr addObject:@"3"]; 

// This statement is fine. 
XCTAssertTrue(arr.count == 3, @"Wrong array size."); 

// This assertion fails with an error: ((arr.count) equal to (3)) failed: ("3") is not equal to ("3") 
XCTAssertEqual(arr.count, 3, @"Wrong array size."); 

मैं XCTAssertEqual के बारे में क्या समझ नहीं पा रहा हूं? अंतिम दावा क्यों विफल रहता है?XCTAssertEqual त्रुटि: ("3") बराबर नहीं है ("3")

+2

कुछ अन्य महान मिलान पुस्तकालयों हैं: OCHamcrest और Expecta। । अच्छी इनबिल्ट मैचर पुस्तकालयों के साथ पूरी तरह से विकसित टेस्ट फ्रेमवर्क - कीवी और सीडर भी हैं। । (बस अगर आपने अभी तक इन कोशिश नहीं की है)। –

उत्तर

47

मुझे एक्सकोड 5 के परीक्षणों में भी काफी परेशानी हुई है। यह अभी भी कुछ अजीब व्यवहार के साथ काफी छोटी गाड़ी प्रतीत होता है - हालांकि मुझे आपके विशेष XCTAssertEqual काम करने का निश्चित कारण नहीं मिला है।

अगर हम परीक्षण कोड पर एक नजर है हम देखते हैं यह वास्तव में निम्नलिखित करता है (XCTestsAssertionsImpl.h से सीधे लिया - यह वहाँ देखने के लिए आसान हो सकता है):

:

#define _XCTPrimitiveAssertEqual(a1, a2, format...) \ 
({ \ 
    @try { \ 
     __typeof__(a1) a1value = (a1); \ 
     __typeof__(a2) a2value = (a2); \ 
     NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; \ 
     NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; \ 
     float aNaN = NAN; \ 
     NSValue *aNaNencoded = [NSValue value:&aNaN withObjCType:@encode(__typeof__(aNaN))]; \ 
     if ([a1encoded isEqualToValue:aNaNencoded] || [a2encoded isEqualToValue:aNaNencoded] || ![a1encoded isEqualToValue:a2encoded]) { \ 
       _XCTRegisterFailure(_XCTFailureDescription(_XCTAssertion_Equal, 0, @#a1, @#a2, _XCTDescriptionForValue(a1encoded), _XCTDescriptionForValue(a2encoded)),format); \ 
     } \ 
    } \ 
    @catch (id exception) { \ 
     _XCTRegisterFailure(_XCTFailureDescription(_XCTAssertion_Equal, 1, @#a1, @#a2, [exception reason]),format); \ 
    }\ 
}) 

यहाँ समस्या है

वास्तव में परीक्षण क्या कर रहा है वह मान को NSValue में एन्कोड कर रहा है और फिर उनकी तुलना कर रहा है। "ठीक है," आप कहते हैं, "लेकिन इसके साथ क्या समस्या है?" मैंने नहीं सोचा था कि तब तक एक था जब तक कि मैंने इसके लिए अपना खुद का टेस्ट केस नहीं बनाया। समस्या यह है कि NSValue के -isEqualToValue को NSValue के एन्कोडिंग प्रकार के साथ-साथ इसके वास्तविक मान की तुलना भी करनी चाहिए। YES लौटने की विधि के बराबर होना चाहिए।

आपके मामले में, arr.count एक NSUInteger है जो unsigned int का टाइपिफ़ है। संकलन-समय स्थिर संभावित रूप से रनटाइम पर signed int में खराब हो जाता है। इस प्रकार जब दोनों को NSValue ऑब्जेक्ट में रखा जाता है, तो उनके एन्कोडिंग प्रकार बराबर नहीं होते हैं और इस प्रकार दोनों -[NSValue isEqualToValue] के अनुसार बराबर नहीं हो सकते हैं।

आप इसे एक कस्टम उदाहरण के साथ साबित कर सकते हैं। निम्नलिखित कोड को स्पष्ट रूप से करता है वास्तव में क्या XCTAssertEqual करता है:

// Note explicit types 
unsigned int a1 = 3; 
signed int a2 = 3; 

__typeof__(a1) a1value = (a1); 
__typeof__(a2) a2value = (a2); 

NSValue *a1encoded = [NSValue value:&a1value withObjCType:@encode(__typeof__(a1))]; 
NSValue *a2encoded = [NSValue value:&a2value withObjCType:@encode(__typeof__(a2))]; 

if (![a1encoded isEqualToValue:a2encoded]) { 
    NSLog(@"3 != 3 :("); 
} 

"3 != 3 :(" लॉग में हर बार दिखाई देगा।

मैं यहां जोड़ना चाहता हूं कि वास्तव में, यह अपेक्षित व्यवहार है। तुलना करते समय NSValue है जो इसकी टाइप एन्कोडिंग की जांच करता है। दुर्भाग्यवश यह नहीं है कि हम दो ('बराबर') पूर्णांक परीक्षण करते समय क्या उम्मीद कर रहे थे।

XCTAssertTrue, संयोग से, और अधिक सरल तर्क है, और आम तौर पर बर्ताव करता है के रूप में उम्मीद (फिर से, यह कैसे निर्धारित करता है कि दावे विफल रहता है के लिए वास्तविक स्रोत देखें)।

+27

यह ध्यान देने योग्य है कि इसके लिए सही फिक्स केवल प्रकार की जानकारी शामिल करना है। 'XCTAssertEqual (arr.count, (NSUInteger) 3, @" गलत सरणी आकार ");' –

+5

धन्यवाद, एक आसान तरीका यह भी है: 'XCTAssertEqual (arr.count, 3U, @ "गलत सरणी आकार।"); ' – owenfi

+3

'3U' के बजाय' (NSUInteger) 3' का उपयोग करने के लिए बेहतर है क्योंकि NSUInteger 64 बिट और 32 बिट संकलन के लिए अलग-अलग टाइप किया गया है। 64 बिट के लिए, एनएसयूइंटर 32 बिट के लिए 'हस्ताक्षरित लंबे' बनाम 'हस्ताक्षरित int' बनाम है। – zim

5

मुझे भी यह समस्या है। @ephemera और @napier के रूप में संकेत दिया गया है, यह प्रकार समस्या है।

इसे सी-शाब्दिक संशोधक का उपयोग करके सही प्रकार के मूल्य की आपूर्ति करके हल किया जा सकता है।

XCTAssertEqual(arr.count, 3ul, @"Wrong array size."); 

आप बाएं हाथ की ओर इस्तेमाल किया समारोह की वापसी प्रकार ऊपर देखकर भी सही प्रकार पा सकते हैं - आगमन पर ALT-clickcount:

- (NSUInteger)count; 

अब अपने प्रकार खोजने के लिए NSUInteger पर एएलटी-क्लिक करें:

typedef unsigned long NSUInteger; 

अब अहस्ताक्षरित लंबे समय के लिए ग शाब्दिक सांख्यिक फ़ॉर्मेट लगता है - गूगल एक अच्छा दोस्त है, लेकिन यह पृष्ठ काम करता है:

http://www.tutorialspoint.com/cprogramming/c_constants.htm

एक त्वरित संकेत यहाँ के रूप में, आप यू (अहस्ताक्षरित) एल (लंबी) या एफ (नाव) का उपयोग करने की आवश्यकता हो सकती है, और सुनिश्चित करें कि आप लिख कर एक डबल पाने के लिए 1 के बजाय 1.0। लोअरकेस भी मेरे उदाहरण के रूप में काम करता है। खासकर यदि आप कोड जहां XCTAssertEqual एक बहुत उपयोग कर रहे हैं और नहीं करते हैं,

XCTAssertEqual(arr.count, (NSUInteger)3, @"Wrong array size."); 

यह उपकरण की वर्तमान स्थिति से सबसे अच्छा समाधान हो सकता है:

+0

मुझे नहीं लगता कि यह काम करता है यदि आप अपने परीक्षण 32 और 64 बिट दोनों पर काम करना चाहते हैं। '3ul' का उपयोग करने से 32 बिट के साथ विफलता होगी। – ThomasW

0

एक वैकल्पिक बस कास्टिंग उपयोग करने के लिए है XCTAssertTrue पर स्विच करना चाहते हैं।

(मैं @RobNapier एक टिप्पणी में इस सुझाव को बनाया देखा।)

0

मैं इस समस्या से snagged मिल गया के रूप में अच्छी तरह से, यहाँ प्रदान समाधान के लिए बहुत आभारी। त्वरित एफवाईआई, ऐसा लगता है कि यह एक्सकोड 5.1 रिलीज में तय किया गया था।

https://developer.apple.com/library/mac/releasenotes/DeveloperTools/RN-Xcode/xc5_release_notes/xc5_release_notes.html

The XCTAssertEqual macro (formerly STAssertEquals using OCUnit) correctly compares scalar values of different types without casting, for example, int and NSInteger. It can no longer accept nonscalar types, such as structs, for comparison. (14435933)

मैं अभी तक Xcode 5.0.2 से अपग्रेड किया है नहीं, लेकिन मेरे सहयोगी है, और एक ही XC परीक्षण है कि पहले इस समस्या की वजह से नाकाम रहने के थे अब कास्टिंग वैकल्पिक हल के बिना गुजर रहे हैं।

3

किसी और मामले में किसी को डबल मेरे जैसे की तुलना द्वारा इस मुद्दे को नेतृत्व की तलाश में है (समाधान ऊपर नाव & डबल के लिए काम नहीं करेगा), कोशिश:

XCTAssertEqualWithAccuracy(number.doubleValue, 12.34, 0.01); 

Generates a failure when (difference between (\a expression1) and (\a expression2) is > (\a accuracy))).

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