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.");
What don't I understand about XCTAssertEqual? Why does the last assertion fail?
I have also had quite a bit of trouble with Xcode 5's tests. It still seems quite buggy with some odd behaviour - however I have found the definitive reason your particular
XCTAssertEqualisn't working.If we have a look at the test code we see it actually does the following (taken directly from
XCTestsAssertionsImpl.h- it may be easier to view there):Here's the problem:
What the test is actually doing is encoding the values into an
NSValueand then comparing them. "Okay," you say, "but what's the problem with that?" I didn't think there was one either until I made my own test case for it. The problem is that NSValue's-isEqualToValuemust also compare the NSValue's encoding type as well as its actual value. Both must be equal for the method to returnYES.In your case,
arr.countis anNSUIntegerwhich is a typedef ofunsigned int. The compile-time constant3presumably degenerates into asigned intat runtime. Thus when the two are put into anNSValueobject, their encoding types are not equal and thus the two CANNOT be equal according to-[NSValue isEqualToValue].You can prove this with a custom example. The following code explicitly does exactly what
XCTAssertEqualdoes:"3 != 3 :("will appear in the log every time.I hasten to add here that this is, in fact, expected behaviour.
NSValueis supposed to check its type encoding when doing comparisons. Unfortunately it's just not what we were expecting when testing two ('equal') integers.XCTAssertTrue, incidentally, has much more straightforward logic, and behaves generally as expected (again, see the actual source for how it determines whether the assertion fails).