21

Does anyone know how to perform unit testing on app extension target, especially keyboard extension target?

What have I tried (in the unit test target):

  • In the "General" tap, set it's target to the extension target instead of the container app.
  • Set the "Bundle Loader" to the path of the binary of the extension target, which looks like $(BUILT_PRODUCTS_DIR)/com.mycompany.keyboard.appex/com.mycompany.keyboard
  • Set the "Test Host" to $(BUNDLE_LOADER).
  • In the "Build Phases" tap, set the "Target Dependencies" to both the container app and the extension.

After these things done, I can build it successfully but always get "Test Failed" with an log Test target SogouInputTests encountered an error (Test session exited(1). without checking in. If you believe this error represents a bug, please attach the log file at /tmp/TestStatus-UXfvxw.log).

I'm using Xcode 6 beta 3.

mfaani
  • 33,269
  • 19
  • 164
  • 293
liuyaodong
  • 2,547
  • 18
  • 31

3 Answers3

22

I have reported the bug to Apple. And sadly, the answer is that the keyboard extension is not support unit test now. The answer comes from Apple:

  • It's not currently supported to run unit tests inside an app extension
  • Instead, factor the code you want to test into a framework and test the code there
  • Link the framework into your extension
liuyaodong
  • 2,547
  • 18
  • 31
5

Just ran into similar issues trying to unit test an extension. Independently did exactly the same thing the author tried with Bundle Loader pointing to .appx path with no success of course. I really did not like the idea of creating a separate framework just for testing so I ended up of adding testable source into the extension test target. It is really simple if you don't have too many source files in your extension:

  1. Select you extension test target in Project settings
  2. Go to Build Phases
  3. Expand Compile Sources
  4. Click +
  5. Add source files with your testable code.
  6. Build for Testing

Why it works:

Once you add extension sources into your extension test target, XCode is going to double reference each of them and compile in both the normal extension build and the test build thus eliminating linking issues.

Are there any drawbacks?

You will have to manually synchronize the source file list in the extension test target. Whenever you add/remove files in the extension target, you may need to do the same in its test target.

yurgis
  • 4,017
  • 1
  • 13
  • 22
  • 1
    Also see [here](https://stackoverflow.com/questions/51070263/whats-the-difference-between-importing-a-target-into-unit-testing-and-including) – mfaani Jun 18 '20 at 23:02
3

What I did which was easier than the other suggestions (no framework creation, no weird settings on build settings, phases, etc) was adding the file that I wanted to test (from the extension target) into the Target Membership of the test target:

enter image description here

The only "drawback" would be that your test target will also include files from your extension (rather than using @testable import like with the main app), but since you are not shipping your test target I would say there is no drawback :)

Tested on Xcode 10.

Note: Only works with Swift code, with ObjC due the BridgingHeader is not possible to follow this approach.

rgkobashi
  • 2,551
  • 19
  • 25
  • It may work in some cases and not in other. For example if you have Objective-C code importing Bridging-header and you add it to tests target, the compilation will fail because bridging header is target specific. – dispatchMain Jan 10 '20 at 08:42
  • 1
    yeah you right, I will update my answer to state it works only on Swift, thanks for the catch! – rgkobashi Jan 10 '20 at 10:12
  • 1
    Also see [here](https://stackoverflow.com/questions/51070263/whats-the-difference-between-importing-a-target-into-unit-testing-and-including) – mfaani Jun 18 '20 at 23:02