Swift UI Testing crashes when accessing enum rawValue - ios

Xcode 7.3
Open Radar: rdar://25456632
In my app I have a string enum which I use to define some accessibility identifiers. For example
enum AccessibilityIds:String {
case ButtonFoo
}
I've built some UI tests where I want to search for controls. So I do something like this:
XCUIApplication().buttons[AccessibilityIds.ButtonFoo.rawValue]
XCode thinks this is fine and does not indicate any errors on the line. However when I compile the UI tests I get this compiler error:
Undefined symbols for architecture x86_64:
"myApp.AccessibilityIds.rawValue.getter : Swift.String", referenced from:
(extension in myAppUITests):__ObjC.XCTestCase.fooButton (myApp.AccessibilityIds) -> Swift.Bool in TestCaseExtensions.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Cross referencing the UI test target with the unit test target (Which compiles fine and uses the enum), I found that the UI tests did not have the Test Host set. Setting it meant that the UI test code would now compile, however the test itself then failed with a SIGKILL and the error:
testFooButton() encountered an error (Lost connection to test manager service. If you believe this error represents a bug, ...
So it appears that I cannot access enum rawValues in UI test code. Has anyone else come across this and managed to figure it out?

I'm still seeing this in Xcode 11.2.1
As a workaround I have placed fileprivate copies of the enums in the Tests.swift file.
This is working for me without any issues or warnings.

Click the source file go the Target Membership of the right panel, then tick the UITests target. Now it should work without any errors.

Related

Linker error when accessing application module in UI tests in Xcode 7.1

I'm trying to implement some UI tests in my project. Everything goes fine as long as I keep it simple: record the test case, add some asserts, then run the test. This works fine, however when I try to access the application module from inside my test, the linker throws an error (See below):
In the application source file:
func foo() {
assert(true)
}
In the UI tests:
import XCTest
#testable import MyApp
func testExample() {
foo()
}
Error:
Undefined symbols for architecture i386: "MyApp.foo () -> ()",
referenced from:
MyAppUITests.MyAppUITests.testExample (MyAppUITests.MyAppUITests)() -> () in MyAppUITests.o ld:
symbol(s) not found for architecture i386 clang: error: linker command
failed with exit code 1 (use -v to see invocation)
Undefined symbols for architecture x86_64: "MyApp.foo () -> ()",
referenced from:
MyAppUITests.MyAppUITests.testExample (MyAppUITests.MyAppUITests)() -> () in MyAppUITests.o ld:
symbol(s) not found for architecture x86_64
I have found similar issue reported here:
https://forums.developer.apple.com/thread/20609
but no solution. Seems to me like the #testable simply doesn't work correctly. The guy on the developer.apple.com tried to workaround by adding the Test Host and Bundle Loader in the settings, but I don't think this is the correct approach. I think the #testable should just make everything work, and it doesn't look like it at the moment. Any help appreciated!
#testable import MainModule won't work for UI test, though it would enable code completion (may make you feel it works). It's designed only for unit test so far. And it would lead to build failure, something like:
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
The workaround is to add the source code file to UI test target as well, then it will work out of the box (even without #testable import).
File Inspector -> Target Membership -> check UI test target (in addition to main target)
Hope Apple will fix it soon so that we can have a cleaner way to use it.
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.
Check this blog for how you can achieve that, https://www.bignerdranch.com/blog/ui-testing-in-xcode-7-part-1-ui-testing-gotchas/
Also found a radar filed here, https://openradar.appspot.com/23116258
#testable import <yourApp> could actually be causing this bug. Just take out the line. It isn't needed for UI Tests.
"UI tests run outside your app in a separate process. You can’t access app code from inside a UI test - that’s intentionally part of the design. Use unit testing for tests that need to access the app code and UI tests to automate user interaction testing"
Notice at 6 minutes in, #testable isn't used by Apple Developers. https://www.youtube.com/watch?v=7zMGf-0OnoU&t=1316s

Swift: Apple Mach-O Linker Error

I'm working on Parse/Facebook login that keeps giving me the following error:
Undefined symbols for architecture x86_64:
"_FBSDKAccessTokenDidChangeNotification", referenced from:
There are over 60+ such errors, not sure why they are appearing since this code is working in a different project. I was copying over some code and this started happening, any advice?
Check if you have the import part copied to your new project as well, so does the dependencies.
When it said undefined symbols, it means the function _FBSDKAccessTokenDidChangeNotification can't be found while compiling, which usually means the correspond framework/SDK/library were not there.
While I'm not sure what caused this issue, the following solution cleared up the error messages:
Go to the main page for the app (on the navigation thing on the left click on your apps name or the top section) -> Build Settings and under Linker Flags, make sure there is nothing in your Other Linker Flags

Mach-O Linker Error in Xcode 6.1

I get the following Linker Error in Xcode 6.1 only, Xcode 6.01 works fine:
Undefined symbols for architecture x86_64:
"__TWvdvC7Bamberg18TourViewController2mmT_", referenced from:
__TFC7Bamberg18TourViewControllerm2mmT_ in tours.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Now I am aware about the standard suggestions. I have tried exhaustively:
cleaning project & build folder
deleting derived data in organizer & developer folder
deleting previous version of the App from simulator and device
resetting simulator
setting "Build Active Architecture Only" to Yes/No
playing around with compiler and architecture settings
adding every single framework that is imaginably (including adding them all)
make sure all implementation files are included in "Compile Sources"
I even recreated the entire project in XCode 6.1 to make sure its not some hidden buggy derived data issue
Finally, I managed to point the source of the problem to an imported Objective C class, which is properly bridged - the error is gone when I do not make use of this class:(https://github.com/mrcrow/MRoundedButton)
If I directly open the demo project of that class in 6.1, it works fine. So I reckon it must be either a conflict of that class with my specific code while being bridged or a bridging error of that class with swift code in general.
Any help is much appreciated.
You seem to have problem in your Swift code or triggered a bug in the Swift compiler. The symbols your linker complains about are Swift symbols (as identified by the __T prefix). When passed to the swift-demangle tool, the symbols translate to:
_TFC7Bamberg18TourViewControllerm2mmT_ ---> Bamberg.TourViewController.mm.materializeForSet : ()
_TWvdvC7Bamberg18TourViewController2mmT_ ---> direct field offset for Bamberg.TourViewController.mm : ()
So in your TourViewController you seem to reference a field mm, but the linker can't find it. Maybe you can rewrite/reorganize your code to avoid/fix this problem.

How to add CocoaHTTPServer to an iOS project on XCode 4

I'm trying to add CocoaHTTPServer to my project. I encountered many problems on the way - my problem (adding CocoaHTTPServer to a project (and have it working)) is still there - but I've also included the errors and solutions I encountered on the way for others' reference.
First I looked at tutorials on adding a framework, but it didn't look like a framework.
Next I right clicked on my project (on the left sidebar), and manually added it with "add files". I followed the SimpleHTTPServer example but got a "cocoa/cocoa.h" not found error. I searched around and found that Cocoa is for mac and not iOS. But the CocoaHTTPServer description talks about iOS apps too, so I just deleted the samples folder (the error was coming from the DynamicHTTPServer example if I recall.
Then I got a "Lexical or preprocessor issue libxml/parser.h not found" error. I tried adding it as a framework, but that didn't work. I found this tutorial on adding libxml to the header search path (at the end), but I ended up with 46 "Apple Mach-O Linker Error _CFHTTPMessage..." errors, and I decided to ask my question here. I tried this answer but got many Apple Mach-O Linker Errors
I added CFNetwork and Security frameworks (project => build phases => link binary with libraries), and was left with 2 errors:
ld: warning: path '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.1.sdk/usr/lib/libxml2.dylib' following -F not a directory
Undefined symbols for architecture i386:
"_NSlog", referenced from:
-[AppDelegate application:didFinishLaunchingWithOptions:] in AppDelegate.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I see i386 which is intel, and not the ARM architecture on iDevices. However, the real problem was I mispelled NSLog (look carefully - it wasn't capitalized in the error message). When I googled this - other possible causes may be missing frameworks.
Now it compiles. When I run the sample application, I get the "server started on X port" and when I go to localhost:X I get the welcome/success screen. When I do the same on my project, I still get the "server started on X port" messages, but when I go to localhost:X the browser gives a "cannot connect" messages. No errors in the XCode console.
There are no errors from [httpServer start:&error] and httpServer.isRunning is true.
So what's the best way to add CocoaHTTPServer to my project? In terms of a clean setup - for example, when I inspect the sample iPhone project, I don't see any of the messy steps to add libxml - I don't even see libxml anywhere at all. And in terms of configuring everything so that it actually works and serves files. Right now, I'm suspecting there may be some project settings that need to be enabled for it to actually be a server.
While adding the external files, have you checked your project as a "Build Target"?

Trouble Adding OCUnit Testing Framework to Existing Xcode Project

I am trying to integrate Unit Tests in my current Xcode project using the OCUnit Testing Framework. I have been following Apple's documentation:
http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/UnitTesting/02-Setting_Up_Unit_Tests_in_a_Project/setting_up.html,
regarding setting up Logic Tests. When I switch to my testing scheme and run 'Test' under the 'Product' tab, I am receive two errors:
Error 1: Undefined symbols for architecture i386:
"_main", referenced from:
start in crt1.o
Error 2: ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I've tried cleaning my build and also using application tests but nothing seems to work. The tutorials I've views on Lynda seems not to run into these errors. Adding a target and linking it to my current project seems like all that needs to happen in order to start utilizing Unit Tests within Xcode. What do these errors mean and what do they refer to? All input is appreciated!
1) Create a new iOS project say one view controller type, and specify you want unit tests at creation, now you can see how Xcode has wired it - you will have a reference.
2) create a new project of the type and name as your current one in a temp folder. Move your original project file to another temp folder, move the new one to where original one was, then import all files checking unit test target.

Resources