Swift is great, but all of the Cocoa frameworks are written in Objective-C. This sometimes results in a tension between Swift and the frameworks. Today we’ll talk about a couple of helpers we can add to XCTest to help ease this tension.
Lets say we have a struct in our model layer like this
Now, lets say we want to write a unit test checking that this failable initializer returns us a Thing
when given valid JSON
Unfortunately this gives us a nasty compiler error. In Swift 1.1 we get…
…and in Swift 1.2 we get…
This is because our struct doesn’t conform to the AnyObject
protocol. What we’d like to do is create our own generic helper that can take any optional value, and assert whether it is nil or not. A first pass looks a little something like this
In Swift 1.2 the way @autoclosure
keyword works has changed so the function prototype needs to be…
This little helper looks great, until we run our tests, and discover that our assertion fails at the wrong line in our code. Xcode points out the failure within our helper, rather than at the callsite.
This is suboptimal. However if we take a look at the prototype of XCTAssertTrue
we find a couple of things that look like they might be helpful
Take a look at those file
and line
parameters with default values. Maybe we could pass in our own values for those parameters to tell the test runner where the assertion failure originates from? Apple’s Swift blog comes to our rescue:
Swift has a number of built-in identifiers, including
__FILE__
,__LINE__
,__COLUMN__
, and__FUNCTION__
. These expressions can be used anywhere and are expanded by the parser to string or integer literals that correspond to the current location in the source code.
…
These identifiers expand to the location of the caller when evaluated in a default argument list
This means if we add file
and line
parameters to our helper, with default values of __FILE__
and __LINE__
respectively, like so…
…then our assertion failure happens at the correct point in our code
Huzzah! We can define a similar helper for checking if an optional is nil. For completeness here are the two helpers in Swift 1.1 and Swift 1.2
Hopefully this has helped you understand how to write your own XCTest helpers, and understand the role of identifiers like __LINE__
and __FILE__
.