Subito-it / SBTUITestTunnel

Enable network mocks and more in UI Tests

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Undefined symbol: _OBJC_CLASS_$_SBTUITestTunnelServer

AboulEinein opened this issue · comments

Hello,

I'm trying to integrate SBTUITestTunnel in my Swift project, but whenever I add it using cocoapods and add the imports in my AppDelegate (as instructed in the Setup document) and build I get the following error:

  "_OBJC_CLASS_$_SBTUITestTunnelServer", referenced from:
      objc-class-ref in MLAppDelegate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation

Any ideas what is the problem?

@AboulEinein Are you using a custom build config name? I just ran into the same issue when using QA and a co-worker helped me realize we need to set ENABLE_UITUNNEL=1 in the Podfile as mentioned here. Additionally, I also had to set ENABLE_UITUNNEL_SWIZZLING=1 to avoid an error where CLLocationManager+Swizzles.m:15 was not being included as it is gated behind #if ENABLE_UITUNNEL && ENABLE_UITUNNEL_SWIZZLING.

Screen Shot 2022-01-21 at 3 08 28 PM

In short, this is what you need in post_install to make it work:

+if config.name == 'QA'
-  config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'ENABLE_UITUNNEL=1']
+  config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', 'ENABLE_UITUNNEL=1', 'ENABLE_UITUNNEL_SWIZZLING=1']
+end

You can still have ENABLE_UITUNNEL_SWIZZLING=0 in GCC_PREPROCESSOR_DEFINITIONS for your project if you want to disable swizzling like I am.

@tcamin Should the doc be updated to include ENABLE_UITUNNEL_SWIZZLING=1 in post_install or is this a bug?

I'm hitting this same error, regards of whether I integrate via Cocopods or SPM.

Adding ENABLE_UITUNNEL_SWIZZLING=1 to my UITest target's GCC_PREPROCESSOR_DEFINITIONS didn't help, (not that I'd expect it to.)

Xcode 13.2.1

I am getting the same error, integration via SPM. XCode 13.1. Custom build config name.
ENABLE_UITUNNEL_SWIZZLING=1 and DEBUG=1 is set.

@kapoorlakshya I'm using custom build config name and I've followed the docs you sent and I'm still getting the same error.

Same here, integration with spm and I have the same error ...

@AboulEinein Is the pod added directly in the app target? I was getting the error when not adding the pod directly to the app target. This is the setup that's working for me:

# App target
def ui_test_app_helper_pods
  pod 'SBTUITestTunnelServer', '~> 8.2.0', configurations: %w[Debug QA]
  pod 'SBTUITestTunnelCommon', '~> 8.2.0', configurations: %w[Debug QA]
  pod 'GCDWebServer', '~> 3.5', inhibit_warnings: true, configurations: %w[Debug QA]
end

project 'MyProject'
target 'MyApp' do
  use_frameworks!
  inhibit_all_warnings!

  # CocoaPods won't link transitive dependencies of 'MyApp' or 'UITestAppHelpers'
  # that have 's.static_framework = true' such as 'SBTUITestTunnelServer'. Manually
  # add them here to fix this issue.
  ui_test_app_helper_pods
end

target 'UITestAppHelpers' do
  use_frameworks!
  inhibit_all_warnings!
  ui_test_app_helper_pods
end

Note: A co-worker (build eng) helped me figure this out and the comments above explain what's happening based on our troubleshooting steps.

Then in UITestAppHelpers, I am importing SBT and calling takeoff inside a wrapper method. The wrapper method is then called in AppDelegate:

#if canImport(SBTUITestTunnelServer)
import SBTUITestTunnelServer
#endif

@objc public final class UITestAppHelper: NSObject {
  @objc public class func startProxyServerForUITesting() {
#if canImport(SBTUITestTunnelServer)
    SBTUITestTunnelServer.takeOff()
#endif
  }
}
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(nullable NSDictionary<UIApplicationLaunchOptionsKey, id> *)launchOptions {
#if DEBUG || QA
  [UITestAppHelper startProxyServerForUITesting];
#endif

...redacted

I got the following error if the pod wasn't directly scoped under MyApp:

ld: warning: Could not find or use auto-linked framework 'FBLPromises'
ld: warning: Could not find or use auto-linked framework 'SBTUITestTunnelServer'
Undefined symbols for architecture arm64:
  "_OBJC_CLASS_$_SBTUITestTunnelServer", referenced from:
      objc-class-ref in UITestAppHelpers(UITestAppHelper.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I would like to have it work by just adding to UITestAppHelpers target, but it does not work. Hope this helps.

This is not a cocoapod only related issue, it is happening with Swift Package Manager as well. The documentation is simple, add server into the app target and client into the ui-test target.

In my case, app and ui tests are compiling and running perfectly, but the unit-tests target which does not use SBTUITestTunnel at all, fails compiling because it does not find the server dependency. I even tried with a new empty project with unit tests, ui tests and not default configs and everything works.

At this point, not sure what to try next ...

Sorry for the late reply. Can anyone share a sample project (either CocoaPods or SPM) that replicates the issue? As @gomera commented staring with a blank project everything seems to work both with SPM and CocoaPods.