XCode App Data
Not many iOS developers know about XCode App Data bundles.
Shiny new feature
Imagine you developing a feature deep into app functions. For a user to get to that feature they might need to sign up for the service, login, pass the onboarding, create some content and then they will see your shiny feature. Let's say you want to congratulate the user with fireworks. The challange is how you test that feature or even see how it works, as you need to walk all that path to get to it.
Getting to it
Another case might be when user reported a bug and you are trying to reproduce it. Do you start over by creating account and content and navigating to get to the place of failure? And even if you do all that work of recreating the state where user experienced the problem, how you make it repeatable?
XCode App Data
XCode App Data is a bundle containing complete state of the app. It has .xcappdata
extension. You can load that bundle into app and get immediately into that state of a feature or a bug you want to explore.
Start app with state
XCode has an option to start the app with a given Application Data package.
Edit the scheme you use to launch the app (Shift-Command-<
) then select Run action and Options tab:
In the Application Data drop down menu you can select one .xcappdata
bundle from your project to use.
Create App Data bundle
One of the fasterst way to create XCode App Data package is to download app container from your test device.
Open Devices and Simulator in XCode (Shift-Command-2
) select your app in the list of installed apps, then click in the gear icon to show container menu. Save the downloaded container to your XCode project. Obviously you do not need to inlcude it into any target.
Test Setup Automation
You can also load the XCode App Data bundle for your UI Tests and even Application Tests. I often have several .xcappdata
bundles in a project to represent different states of the app.
The Bug
Current version of XCode has a bug not loading XCode App Data container even it is selected in Options. Please report this to Apple to upvote it: Open Radar - Cannot use xcappdata package in simulator
To workaround that bug I've created loadAppData() function that does just that depending on environment variable passed at launch.
import Foundation
func loadAppData() {
let processInfo = ProcessInfo.processInfo
guard let appDataPath = processInfo.environment["LOAD_APPDATA"] else {
return
}
let loaderUrl = URL(fileURLWithPath: #file)
let bundleUrl = URL(fileURLWithPath: appDataPath, relativeTo: loaderUrl).appendingPathExtension("xcappdata")
let contentsURL = bundleUrl.appendingPathComponent("AppData")
let fileManager = FileManager.default
let enumerator = fileManager.enumerator(at: contentsURL,
includingPropertiesForKeys: [.isDirectoryKey],
options: [],
errorHandler: nil)!
let destinationRoot = fileManager.urls(for: .libraryDirectory, in: .userDomainMask).last!.deletingLastPathComponent()
try! fileManager.removeItem(at: destinationRoot)
let sourceRoot = contentsURL.standardizedFileURL.path
while let sourceUrl = enumerator.nextObject() as? URL {
guard let resourceValues = try? sourceUrl.resourceValues(forKeys: [.isDirectoryKey]),
let isDirectory = resourceValues.isDirectory,
!isDirectory else {
continue
}
let path = sourceUrl.standardizedFileURL.path.replacingOccurrences(of: sourceRoot, with: "")
let destinationURL = destinationRoot.appendingPathComponent(path)
try! fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(),
withIntermediateDirectories: true,
attributes: nil)
try! fileManager.copyItem(at: sourceUrl,
to: destinationURL)
}
}
The above function is safe to include into the app target, as it only does container replacement when your pass LOAD_APPDATA
environment.
Complete example
You can find complete example with an automated UI test on GitHub here: https://github.com/paulz/WeightTracker
The example project has Continuous Intergration on Travis passing all tests here: https://travis-ci.org/paulz/WeightTracker
The code is also 100% test covered by testing both states with and without .xcappdata
: https://codecov.io/gh/paulz/WeightTracker/tree/master/WeightTracker