Skip to main content

Speed up your unit tests! Swap out your App Delegate for testing.

Faster, please
One thing that can slow our tests down is if our App performs expensive tasks on startup and it is not unusual to place code that synchronizes with a server in our implementation of UIAppDelegate.

Luckily for us there is a way to change the production App Delegate with a fake that does nothing.

Objective-C
class FakeAppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?

  func application(application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
    self.window?.rootViewController = UIViewController()
    return true
  }
}

let isRunningTests = NSClassFromString("XCTestCase") != nil

if isRunningTests {
  UIApplicationMain(Process.argc, Process.unsafeArgv, nil,
    NSStringFromClass(FakeAppDelegate))
} else {
  UIApplicationMain(Process.argc, Process.unsafeArgv, nil,
    NSStringFromClass(AppDelegate))
}

Swift
class FakeAppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  
  func application(_ application: UIApplication,
                   didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.window?.rootViewController = UIViewController()
    return true
  }
}

let isRunningTests = NSClassFromString("XCTestCase") != nil

// There is a Swift bug with the UIApplication signature in the newest Swift 3 version
// https://bugs.swift.org/browse/SR-1390
let unsafeArgv = UnsafeMutableRawPointer(CommandLine.unsafeArgv)
  .bindMemory(
    to: UnsafeMutablePointer.self,
    capacity: Int(CommandLine.argc))

if isRunningTests {
  UIApplicationMain(CommandLine.argc,
                    unsafeArgv,
                    nil,
                    NSStringFromClass(FakeAppDelegate.self)
  )
} else {
  UIApplicationMain(CommandLine.argc,
                    unsafeArgv,
                    nil,
                    NSStringFromClass(AppDelegate.self)
  )
}

Alex Salom

Comments

Most Favorite Posts

Using Speech with iOS and Android: SiriKit, Voice Capabilities, Google Assistant

SiriKit SiriKit enables your iOS apps and watchOS apps to work with Siri, so users can get things done using just their voice. Your content and services can be used in new scenarios including access from the lock screen and hands-free use. Apps adopt SiriKit by building an extension that communicates with Siri, even when your app isn’t running. The extension registers with specific domains and intents that it can handle. For example, a messaging app would likely register to support the Messages domain, and the intent to send a message. Siri handles all of the user interaction, including the voice and natural language recognition, and works with your extension to get information and handle user requests. Apple Developer Adding Voice Capabilites Voice actions are an important part of the wearable experience. They let users carry out actions hands-free and quickly. Wear provides two types of voice actions: System-provided These voice actions are task-based and are built into ...

Titanium: Releasing Memory

- It’s true that you can’t manually manage your application objects’ reference count in iOS applications. There are, however, things you can do to free up memory – the big ones in the 1.x product are closing windows (which releases all UI resources associated with the window) and setting references to a proxy object (like one returned by Ti.UI.createXXX) to null, which will release the resources associated with that object. Why you should stay away from Titanium

Judo App - Server Driven UI out of the box

Judo App Judo brings server-driven UI to your iOS and Android apps. Build user interfaces visually in a fraction of time and publish them instantly without submitting to the app store. Build Experiences - With No Code The Judo app for macOS, available through the App Store, is built for design professionals with common keyboard shortcuts and familiar concepts like canvas, layers and inspector panel. Workflow is streamlined with the ability to drag and drop media files directly into your experiences and manage your own Judo files in Finder. Manage Creative Execution A Judo experience is interactive and can include text, images, video and buttons. An experience may be part of a screen, a single screen, or more typically multiple linked screens. Judo supports screen transitions, carousels, horizontal scrolling and modals. Clients can add custom fonts and define global colors and these are updates applied universally. Effortlessly Deploy Judo Cloud syncs your experiences with your iOS and ...

CFPropertyList

The PHP implementation of Apple's PropertyList plist can handle XML PropertyLists as well as binary PropertyLists. It offers functionality to easily convert data between worlds, e.g. recalculating timestamps from unix epoch to apple epoch and vice versa. A feature to automagically create (guess) the plist structure from a normal PHP data structure will help you dump your data to plist in no time. github

PlistBuddy

If you want to generate a Plist within the shell script: The PlistBuddy command is used to read and modify values inside of a plist. Unless specified by the -c switch, PlistBuddy runs in interactive mode. Apple PlistBuddy ManPage

How to link to TestFlight App in iOS

There are two things you need to do. First, check to see if TestFlight is installed. Then create a new link to your app. NSURL *customAppURL = [NSURL URLWithString:@"itms-beta://"]; if ([[UIApplication sharedApplication] canOpenURL:customAppURL]) {     // TestFlight is installed     // Special link that includes the app's Apple ID     customAppURL = [NSURL URLWithString:@"https://beta.itunes.apple.com/v1/app/978489855"];      [[UIApplication sharedApplication] openURL:customAppURL]; } This special https://beta.itunes.apple.com URL will be opened directly in TestFlight. Finally, if you are using iOS 9 (or later), you need to make an addition to your Info.plist to get the canOpenURL: method to work. If your app is linked on or after iOS 9.0, you must declare the URL schemes you want to pass to this method. Do this by using the LSApplicationQueriesSchemes array in your Xcode project’s Info.plist file. For each URL scheme you wan...