Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Add Xcode UI tests using PBXProject class

Discussion in 'iOS and tvOS' started by DanielC2017, Aug 1, 2019.

  1. DanielC2017

    DanielC2017

    Joined:
    Dec 5, 2017
    Posts:
    4
    I'm using Unity to generate an Xcode project for iOS which by default contains a target with the game, and an xcode unit tests target.
    I would like to create UI tests, automatically, by using the UnityEditor.iOS.Xcode's PBXProject class in a PostBuildProcess function.
    I have two files which I'm adding to the project: CustomXcodeUITests.m containing my UI tests logic and the Info.plist file.
    I'm calling the following methods:

    PBXProject proj = new PBXProject()
    proj.ReadFromFile(PBXProject.GetPBXProjectPath(buildPath));
    string targetGuid = project.AddTarget("MyUITests", "xctest", "com.apple.product-type.bundle.ui-testing");
    string targetProjectPath = Path.Combine(buildPath, "MyUITests");
    Directory.CreateDirectory(targetProjectPath);
    // Copying the CustomXcodeUITests.m and Info.plist file into the created project directory

    // The local paths relative to the xcode project source tree
    string plistLocalPath= "MyUITests/Info.plist";
    string sourceCodeLocalPath = "MyUITests/CustomXcodeUITests.m";

    // Adding the files into the project
    proj.AddFile(plistLocalPath, plistLocalPath);
    string sourceCodeFileGuid = project.AddFile(sourceCodeLocalPath, sourceCodeLocalPath);

    // Adding the .m file to the build
    proj.AddFileToBuild(targetGuid, sourceCodeFileGuid);
    // ... other flag changes
    // ... writing the changes;


    After the AddFileToBuild gets called, I receive the following error:

    Exception: The given path .m does not refer to a file in a known build section
    at UnityEditor.iOS.Xcode.PBXProjectData.BuildSectionAny (UnityEditor.iOS.Xcode.PBX.PBXNativeTargetData target, System.String path, Boolean isFolderRef) [0x00241] in /Users/builduser/buildslave/unity/build/External/XcodeAPI/Xcode/PBXProjectData.cs:243
    at UnityEditor.iOS.Xcode.PBXProject.BuildSectionAny (UnityEditor.iOS.Xcode.PBX.PBXNativeTargetData target, System.String path, Boolean isFolderRef) [0x0000a] in /Users/builduser/buildslave/unity/build/External/XcodeAPI/Xcode/PBXProject.cs:84
    at UnityEditor.iOS.Xcode.PBXProject.AddBuildFileImpl (System.String targetGuid, System.String fileGuid, Boolean weak, System.String compileFlags) [0x0005c] in /Users/builduser/buildslave/unity/build/External/XcodeAPI/Xcode/PBXProject.cs:240
    at UnityEditor.iOS.Xcode.PBXProject.AddFileToBuild (System.String targetGuid, System.String fileGuid) [0x00006] in /Users/builduser/buildslave/unity/build/External/XcodeAPI/Xcode/PBXProject.cs:254

    I tried to remove that last call to AddFileToBuild and everything else works fine, the project is updated. I even checked the contents of the project.pbxproj file and I couldn't spot any missing part.
    I wasn't sure if the "xctest" is the correct extension for the new UI Tests target, but according to this webpage, the xctest extension results in having an wrapper.cfbundle as the file type. I checked the project.pbxproject contents for a normal, manually created UI test target and indeed the target file is of wrapper.cfbundle type. But again, I'm not sure if the xctest value is the correct one to pass to the AddTarget method to create an UI test target.

    Did someone encounter this issue or does someone know the cause?
     
    Last edited: Aug 1, 2019
  2. DanielC2017

    DanielC2017

    Joined:
    Dec 5, 2017
    Posts:
    4
    I found the issue. It seems that you need to add a Compile sources build phase for new targets, before adding any file to build (something that is not documented anywhere, well, nothing from that namespace is documented as it should be).
    So, the fix was to add the following method call before any other calls to AddFileToBuild(...):

    proj.AddSourcesBuildPhase(targetGuid);
     
    Voxel-Busters and Kumo-Kairo like this.
  3. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    @DanielC2017 Hi!
    How are you adding Unity-iPhone reference to your UI Tests? It looks like it requires a PBXTargetDependency with a PBXContainerItemProxy, but I haven't managed to find appropriate APIs in the PBXProject class/namespace
     
  4. DanielC2017

    DanielC2017

    Joined:
    Dec 5, 2017
    Posts:
    4
    Hello @Kumo-Kairo!

    It's been a while since I've worked on this, but from what I remember this is the minimum required to set the Target Application for UI Tests:

    project.SetBuildProperty(uiTestsTargetGUID, "PRODUCT_NAME", "MyUITests");
    project.SetBuildProperty(uiTestsTargetGUID, "TEST_HOST", "");
    project.SetBuildProperty(uiTestsTargetGUID, "BUNDLE_LOADER", "");
    project.SetBuildProperty(uiTestsTargetGUID, "TARGET_APPLICATION", "Unity-iPhone");
    project.SetBuildProperty(uiTestsTargetGUID, "USES_XCTRUNNER", "YES");
    project.SetBuildProperty(uiTestsTargetGUID, "TEST_TARGET_NAME", "Unity-iPhone");
    project.SetBuildProperty(uiTestsTargetGUID, "WRAPPER_EXTENSION", "xctest");

    Note: The TEST_HOST and BUNDLE_LOADER need to be empty if you want Xcode to behave normally during the UITests execution. If any of them is set, then the target application will start before the tests, which you might not want in an UITest (e.g. you want to launch XCUIApplication from the tests code).

    The project variable represents your PBXProject and the uiTestsTargetGUID is the value returned by the call of project.AddTarget for your UITests.

    For the Xcode Build properties, you can check this Apple page:
    https://help.apple.com/xcode/mac/current/#/itcaec37c2a6

    I hope that this helps.
     
    Kumo-Kairo likes this.