Do you write unit tests for your apps? Whatever answer you have writing tests in Swift became a popular subject in the development community. Many developers published great articles, made outstanding talks and podcasts on writing tests in Swift. It became easier than ever learning with these materials. At the end of 2017, I decided to share my favorite materials that would be good for you to pickup unit-test skills from zero to one.
Happy learning :)
Before getting your hands dirty
Engineering for Testability
If you are a newcomer in writing unit tests, I highly recommend you start with this video from WWDC 2017. In this video, Brain Croom and Greg Tracy state the motivation of writing testable code and the importance of testability. Then they show how to decouple modules step by step. They also introduce many techniques and tips that you should know in modeling your apps and writing unit tests. This is definitely a good place to begin your journey.
iOS Unit Testing and UI Testing Tutorial
I still remember that when I checked the “Include Unit Tests” checkbox first time, I wasn’t aware of any change to the project and didn’t know how to proceed. This is a complete guide to writing tests in Swift presented by Audrey Tam. She covers some essential topics such how to set-up the unit test in Xcode and how to create mock objects or stub objects. She also introduces more advanced topics such as performance tests and the test coverage.
Along the way, you’ll pick up some of the vocabulary used by testing ninjas, and by the end of this tutorial you’ll be injecting dependencies into your System Under Test (SUT) with aplomb!
Stylish Developers Guide to Unit Testing in Swift
Should I write tests to my code at this current stage? Jaim Zuber shows why you need tests and the benefits of introducing tests into your projects. He also provides detailed step by step tutorial to write test in practice:
We’ll answer questions like: How do I test my ViewControllers? How can I test Storyboard code? How do I survive without a mocking library or partial mocks?
If you’re still not sure about what’s the benefit of writing tests, check this video talk!
TDD in Xcode Playgrounds
Not familiar with the XCTest? Afraid to mess up with your existing projects? Don’t worry, you can start with the playground! Go check this brilliant presentation and don’t panic when you hear “TDD” term (Test-Driven Development). In this video, Paul Ardeleanu guides you through writing XCTest cases with simple examples in Playground that you can easily start with and follow up, even if you don’t know what TDD is.
The biggest advantage of this solution is the playground (re)running all your tests every time something changes shortening the feedback look drastically!
The complete guide to Network Unit Testing in Swift
Now you know how to decouple modules and how to write XCTestCase. However, it’s still confusing how to combine those techniques in practice. This is my tutorial talking about the widely-used decoupling technique, Dependency Injection (DI). It explains how to use the DI and Swift protocols to decouple the network service and shows you how to write tests for the service.
Dependency injection makes our system more flexible… we can also “inject” the mock networking environment to run the test code without access to the internet.
Testing iOS Apps
It’s somehow difficult to master the test writing skill: there are too many rules or patterns to be remembered. But you don’t need to learn all of them in a single jump. Krzysztof Zabłocki lists consolidated and universal concepts that you should first emphasize when writing tests. With those principles in mind, you will be able to write maintainable tests and benefit from them in the long run.
A big corporation might have dedicated QA team, but if you are one of 2 developers, then you are often responsible for ensuring quality and reliability of your work.
Singleton, Service Locator and tests in iOS
Are you an engineer who rolls the eyes when you see a singleton in your project? Bohdan Orlov compares two primarily abused patterns, Singleton and Service Locator, and pinpoints why they are so notorious. He also provides ways to do better and write unit tests based on that two patterns. It’s handy for decoupling modules and refactoring legacy codes.
The access to a global object from any layer of the app violates the principle of least privilege and our efforts to keep dependencies explicit.
Let’s make some more cool stuff!
Testing an Untested App
With every little change that you make, your code is getting more robust, and you’re getting more tests.
If you’re lucky enough, you might start your project from zero. However, most of the time you have to do teamwork, review or modify some others’ codes. In such case, how do we start to write tests for those projects? In this video, Michael May does a live code review with you. He refactors an existed project and explains his thoughts line by line. This is a real-life experience!
Common unit testing techniques on iOS
Learning techniques and practicing them over and over are the keys to become a high-performance developer.
Swift does not have mocking frameworks because reflection is limited and for pure swift objects it’s not possible to change the implementation of methods.
Luciano Marisi tells you how to craft them! There you will find some really useful techniques. Those great patterns cover almost all everyday situations in writing tests.
Test Doubles In Swift
“A test double is an object that can stand in for a real object in a test” from Google Testing Blog. You must have heard the “mock” and the “stub,” but there are more useful test doubles that facilitate the unit tests.
Test Doubles are what you need to make a test easy to write.
Marco Santarossa introduces handful test doubles with comprehensive examples, making creating test doubles a breeze.
Waiting in XCTest
Waiting is hard, and waiting in Xcode is no exception. Even choosing from the myriad of options Xcode and XCTest provide can be difficult.
In mobile/desktop development async requests are inevitable. Xcode provides a bunch of classes for you to handle waiting events. Joe Masilotti writes a holistic instruction about the XCTestExpectation and its families. He also covers pitfalls you should avoid and helps you writing test cases for async requests like a boss.
Cracking the Tests for Core Data
It getting harder to mock the context and write tests to the container (NSPersistentContainer)
Writing tests for the Core Data is kind of a black box to many people. In this article, I briefly introduce the test techniques for Core Data, including in-memory database and DI in Core Data. If you’re using Core Data as the storage layer and still wondering how to write test, this is the one for you.
Xcode unit tests with ⌘+S
Running tests is a hard task for large projects since it takes a long time to rebuild the projects. Here’s a tool, InjectionTDD by John Holdsworth, to rescue. InjectionTDD injects new implementations without rebuilding the whole project. Now Bartosz Polaczyk has an excellent step by step introduction to the InjectionTDD.
InjectionForXcode saves a ton of time by compiling updated file on-fly and replacing/swizzling its implementation in a live iOS process.
Something you must know
Time traveling in Swift unit tests
It’s common that our code is depending on various time. But it’s a big problem in writing tests: it’s difficult to get proper date objects ready without waiting. John Sundell presents a cool technique, time traveling, to help you “jumping” to the appropriate time so that you don’t need to sit tight.
A fast & predictable date-dependent test, without having to invent a lot of infrastructure or resort to hacky solutions like swizzling the system date.
Reducing flakiness in Swift tests
Flakiness is what happens when tests don’t run consistently
Test code is also code. You still need to pay attention to the quality of your test code. John Sundell writes a great article tell you how to avoid ‘flakiness’ in writing tests. He shares three tips that are helpful in real work situations. One more thing, if you’re interested in advancing your test skills, don’t miss his excellent weekly-updated blog.
Tests that don’t crash
Intuitively, crashes on unit test seem no harm. They happen merely during development and won’t affect users at all. However, they break your continuous integration flow: tests after the exception won’t execute. Tim Vermeulen shows how to tackle the problem elegantly and how to make exceptions more descriptive.
It’s fairly straight-forward to write tests that fail gracefully when an unexpected nil is encountered, or when an error is thrown unexpectedly.
Testing and mocking without OCMock
Are you an OCMock user? Without the benefit of run-time swizzling in Objective-C, it’s challenging to mock pure Swift code with the OCMock. Jesse Squires introduces an alternative way utilizing the protocol and the XCTestExpectation to test the behaviors of the SUT.
This method of testing keeps our tests rather simple and straightforward, and gives us a kind of “mocking” in Swift.
Making Mock Objects More Useful
Why do we need mock objects? Why would you ever want to use a mock object instead of the real object?
Once you start to write your own tests, you might found that designing mocks is not as easy as the sample code shows. In fact, mocks are just like real products: they should be reusable and maintainable. The author of the OCMockito, Jon Reid, brings his experiences of mocking objects here. He covers many mock techniques such as utilizing helper methods and making asserts more descriptive. Those help you creating high-quality mocks and improving your efficiency.
More life saver
Using protocol compositon for dependency injection
DI sometimes is cumbersome if there are multiple dependencies on a single entity. Krzysztof Zabłocki gives a nice shortcut: using protocol composition!
iOS Cookies — The Testing Section
iOS Cookies curates many high-quality Swift libraries weekly. The testing section is definitely made for you, test lovers 🍻
And Arek Holko shows you how to save your life with a simple trick. :)
Conclusion
As a sole developer, I don’t have a mentor teaching me how to write unit test face to face. However, thanks to the Swift community, I have many resources where I can consult and learn.
If you have any question or you found anything that I’ve missed, feel free to leave response below. And don’t forget to like/clap/share those articles. :)