XCTest tips and tricks that can level up your Swift testing.
🧵👇
1. Use XCTUnwrap instead of force wrapping optionals
Force unwrapping a nil will cause the test suite to completely crash, meaning no output or reporting. XCTUnwrap provides a nice failure message and fails the test.
2. Set continueAfterFailure to false
If you have multiple assertions in a test they might increase in specificity. The first asserts the size of the array and the second assets the first element. You don't want to run the second if the first fails, it's just noise.
3. Use KVO observing asynchronous expectations
Use XCTKVOExpectation to assert KVO-compliant properties on your subject under test.
This technique is helpful when you only care about the type and not a particular instance.
XCTAssert(controller.presentedViewController is CustomViewController)
5. Keep XCTAssertEqual parameter order consistent
The documentation doesn't indicate if the expected or actual value should be first. Pick one and stick with it to make it obvious which is which for any test. (Personally, I put the actual value first.)
6. Extract helpers judiciously
If I need 3 or more lines of code to "do something" I extract it to a helper. This includes test setup, the action, and the assertion(s). Define the function with #filepath and #line to pass along test failures to the caller.
If you made it this far you might also enjoy reading Masilotti.com, where I blog about testing in Swift.
What other XCTest tips have you picked up? Reply here I'll add them to this thread!
7. Add test extensions to models to make your code easier to understand by reducing noise via @lightsprint09
struct User {
let firstName: String
let lastName: String
}
I spent most of today reworking the core logic of @TheMugshotBot and really enjoyed it! This is super exciting because it opens up a lot of new opportunities for upcoming themes and customizations. And ironed out a bunch of bugs.
A big help was commenting out the entire model and TDDing the bulk of the logic. I missed a few things on the first pass, but was able to backfill a feature or two and then wrap it in tests.
I'm all for this "TDDish" approach I've developed over the past few years!
Deep in the weeds...
The code had a bunch of features slapped on here and there. Taking the time document the entire flow (on paper!) and then reimplementing helped consolidate a lot of logic and missed edge cases.
All the more reason to dedicate time to refactoring!