I am developing an iOS project, and I need to access to the codes of the host app from the UI test target, but I found that it shows link error: undefined symbol when I tried to. I found the test host and bundle loader for this target are all empty, so I set those to my host app and could get past the link error. However, at runtime it still fails when calling XCUIApplication.launch(). Has anyone figured out how to access the codes of the host app from this UI test target? Without being able to do this, we are forced to do all UI test, which is very flaky. We definitely need to have non-UI steps in test scenarios. I am using Swift for my project.
-
I'm having the exact same problem. I used [link](http://twobitlabs.com/2011/06/adding-ocunit-to-an-existing-ios-project-with-xcode-4/) for bundle loader/test host and [link](http://savvyapps.com/blog/how-to-implement-ui-testing-in-an-existing-ios-app) which noted to verify "Enable Testability" in the main target. I have gotten to the exact same point as you. Any luck in the last couple days since you posted this question? – Chris Sep 21 '15 at 12:43
-
Like @Konnor says in their answer, you can't access your app's process from within a UI test. What are you trying to do? I've had some success working around these limitations in our tests. – kubi Oct 26 '15 at 22:22
-
@kubi: I'm interested about your workaround. I want to set/read an attribute in a singleton object. Of cause this can be done by adding an UI for this in the tested application, but that feels a bit of an overkill. Have you found any better solution? – Fredrik Johansson Nov 01 '15 at 16:53
-
@FredrikJohansson: posted below as an answer. – kubi Nov 01 '15 at 19:07
-
I think I've just run into the same problem. I'm trying to access an enum that I use to set all the accessibilityIdentifiers in the UI. Xcode sees the enum no problem, but the compiler fails accessing any properties such as rawValue. – drekka Mar 31 '16 at 03:01
-
You might want to check out SBTUITestTunnel which may come handy to dynamically inject data from test code to app code. See my answer [here](http://stackoverflow.com/a/36909859/574449) – Tomas Camin Apr 28 '16 at 10:53
2 Answers
I use the following technique to set values in my App before running UI tests. Useful for setting defaults or turning on networking mocks, etc. For the most part, I haven't needed to read anything out of the app yet. Everything is reflected in the UI and can be tested that way. Soon we're going to add tests to ensure the app makes certain network calls. I'm not yet sure how we'll test that from inside a UI test case.
Set arguments in your UI test
let app = XCUIApplication()
app.launchArguments = ["ResetDefaults", "NoAnimations", "UserHasRegistered"]
app.launch()
Read arguments in your app
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var arguments = NSProcessInfo.processInfo().arguments
arguments.removeFirst()
print("App launching with the following arguments: \(arguments)")
// Always clear the defaults first
if arguments.contains("ResetDefaults") {
destroyUserDefaults()
clearKeychain()
}
for argument in arguments {
switch argument {
case "NoAnimations":
UIView.setAnimationsEnabled(false)
case "UserHasRegistered":
Defaults.userRegistered = true
default:
break
}
}
}
Additional bonus: If you use launch arguments to configure your app, it's trivial to add flags to your Xcode scheme. For example, I have a scheme that clears all stored data, and stubs out any login attempt with a success response. I can now "login" via the simulator without hitting any servers.

- 48,104
- 19
- 94
- 118
-
Haha, I've just implemented that. And as a second step I tried to pass back information via a file interface. I write file 'a' in the app, and try to read it in the tests but it is not the same. Don't know why... @"/var/mobile/Containers/Data/Application/8EDD0F16-005B-49E7-B8E3-726F195989DD/Documents/a" @"/var/mobile/Containers/Data/Application/DD4A912D-5808-40AC-9BAD-0475842190DA/Documents/a" – Fredrik Johansson Nov 01 '15 at 19:18
-
If you figure something out, write a blog post! i'm sure a lot of people would be interested. I think the way forward might be to make an API call to a local server. Sounds a bit complicated, but I bet it could be handled with a 30-line python script. – kubi Nov 01 '15 at 19:21
-
Note that for the arguments to be parsed by NSUserDefaults, the key and value, e.g. `-AppleLanguages` and `(en)`, need to be two separate array elements. – Frank Schmitt Apr 29 '16 at 23:23
-
I was breaking my head for more than a week. Where were you bro. Thanks a lot. This helped me entirely. – Manoj Nov 03 '16 at 11:13
-
I just get the feeling that this is not the intended way to do testing. By doing this, you're not testing the same product the user will use. – Jonny Dec 22 '16 at 06:17
-
You could also create a custom view (table/collection view) for all the states in your app you'd want to test and then make the UI test select the state for every test in the UI itself. You could make this view a hidden feature only accessible while testing – Lobsterman Apr 21 '17 at 19:14
-
@FredrikJohansson UI Tests Target run within its own process so it has its own environment and cannot share data easily with the tested app. The only way to do that is to pass launch arguments or have some sort of shared data (a file, a webservice, whatever), but it can be very fragile. I personnally share some swift files between the app target and UI Test target, so that they can share accessibility identifiers & launch arguments. – nverinaud Feb 07 '18 at 13:14
-
Why did you do the `arguments.removeFirst()`? wouldn't that remove `ResetDefaults` on your array? – Zonily Jame May 30 '18 at 10:40
-
1@ZonilyJame The first argument is always the process name, so you've got to remove it before parsing the rest of the arguments. – kubi Jun 01 '18 at 16:46
Using the new UI automation framework Apple introduced in WWDC 15 it is not possible to access your app's code from the UI-Automation test. It's meant to simulate what a user would have access too, which can be frustrating at times.

- 1,857
- 5
- 24
- 33
-
3Do you have a source for your statement regarding app code not being accessible from the ui tests? – Francesco Puglisi Nov 06 '15 at 15:16
-
@singingAtom The UI tests are a separate module from the app, therefore not run inside your app as a logic test would. The only way for them to share code is to compile in all the app files you need to share between the two modules. Hope that helps. – cakes88 Nov 06 '15 at 20:52
-
1@cakes88 Do you have any references to how your last statement works? – Teresa Peters Sep 20 '16 at 22:42