Unit testing is super useful, because it boosts your confidence to know that you aren’t breaking existing features while making changes to your app. However, they are notoriously slow to run, especially in Xcode. It needs to launch the simulator, install your app, launch your app, and loads the UI. If it takes too long to see pass or failure, it makes you not want to run them.
Fast feedback in unit testing is what makes it effective.
If you have two seconds to spare, I’m going to show you a quick tip from my book Effective Unit Testing to make all unit tests in your app run faster for the life of your project.
A quick tip to make your unit tests run much faster
When you generate a new project in Xcode, there are two boxes that are checked by default to generate both unit tests and UI tests. UI testing takes a considerable amount of time to run. When you hit ⌘U, it’ll run ALL tests. This can be very slow. When you’re looking for your unit tests to give you fast feedback, you don’t really want to run the UI tests.
There is a super easy way to disable UI tests. Just follow these simple steps. It literally takes two seconds to do.
- Select Product —> Scheme —> Edit Scheme, or hit ⇧⌘\<, to bring up the scheme editor.
- Choose Test on the left pane. You should see both sets of tests – one for unit tests (with the suffix
Tests
), and one for UI tests (with the suffixUITests
). - Under the Test column, uncheck it for the UI tests.
Your unit tests will run a lot faster. Give it a whirl.
Want even more speed?
Paul Solt wrote in to let me know he found yet another way to speed up his unit tests. And he is very kind to even record a screencast to detail his steps.
To recap from the video above, the steps are:
- Disable the Host Application on the Unit Test project settings
- Statically link all source code files for your unit tests
As the host settings apply to the test target, that means all tests within the same test target are affected. So if they’re turned off, the test target can only contain business logic tests (i.e. no UIKit classes). This is fine if all your unit tests in the test target do not need to access the UIKit. I can see separating the pure unit tests from the view controller tests can be a good thing.
In Clean Swift, I can separate the tests into 3 categories:
- Business logic tests – testing the interactor
- Presentation logic tests – testing the presenter
- Display logic tests – testing the view controller
Both the business and presentation logic tests can have the host setting turned off to make them run faster. But leaving the setting on allows me to run the display logic tests.
I also asked Paul:
From your screencast, it seems like the simulator needs to be opened, and the app needs to be installed and launched, even when the host settings are turned off. Do all three of these things need to happen, or just some?
And he responded:
The simulator opens, since I believe the tests run in the environment, but you don’t have to wait as long. I’m not exactly sure what’s going on, but it’s much faster, especially on the slow computer’s at RIT where I’m teaching an iPhone app course. Big difference in test boot up time.
It’s important to make sure everyone on the team knows what files and for what targets to check and uncheck the host application settings.
Neat trick “Disable the Host Application on the Unit Test project settings” – runs faster and does not pollute the console with debug printouts from the application.
Thanks Raymond and Paul
Hello,
I’m having a hard time making my apps’ unit testing start fast and I was wondering if you could recommend me any free resources that explore the topic.
I’ve just solved the issue of UI tests launching alongside unit tests by making the default testing plan one with unit tests only.
So I’ve already been able to cut the unit testing starting process from several minutes down to about 20 seconds.
However, I can see that some developers are able to run tests in 1-2 seconds, which would be a huge deal for TDD.
I have implemented the solutions in https://hacknicity.medium.com/how-to-switch-your-ios-app-and-scene-delegates-for-improved-testing-9746279378c3.
I also tried setting the host application to none, as described in this blog post, but I eventually had to rollback because it caused the error “Linker command failed with exit code 1 (use -v to see)”, for which I’ve yet to find a working solution.
This all makes me wonder that I’m doing something seriously wrong, and I was wondering if my issue (unit tests taking 10 times longer than normal to start) could be linked to some well known cause.
Thank you