mokacoding

unit and acceptance testing, automation, productivity

Prevent Unit Tests from Loading AppDelegate in Swift

Update 2020/11/12: Checkout the SwiftUI-compatible version

Update 2018/09/19: Updated to work with Swift 4.2. You can find the previous implementations looking at the history of the demo project on GitHub.

Credits to Witold Skibniewski and Paul Boot who shared the Swift 2.0 implementation in Jon Reid's post "How to Easily Switch Your App Delegate for Testing", and to Jon for wirting the post that started the conversation.

Here's how to have a dedicated AppDelegate for the unit test target in Swift:

// main.swift
import UIKit

private func delegateClassName() -> String? {
  return NSClassFromString("XCTestCase") == nil ? NSStringFromClass(AppDelegate.self) : nil
}

UIApplicationMain(
  CommandLine.argc,
  CommandLine.unsafeArgv,
  nil,
  delegateClassName()
)

// AppDelegate.swift
import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {
  // ...
}

Note how we have removed the @UIApplicationMain annotation from the app delegate class definition that Xcode generates for us, as that is now implemented by main.swift.

You can checkout this example for a full project using this approach.

I really like how leaner and faster the test target is without having to perform all the initialization code that is done in the normal AppDelegate. I encourage you to adopt this simple approach.

On top of that, less things happening on the Simulator while testing == more confidence in the results 🎉.

Leave the codebase better than you found it.

Want more of these posts?

Subscribe to receive new posts in your inbox.