ChargePoint / xcparse

Command line tool & Swift framework for parsing Xcode 11+ xcresult
MIT License
392 stars 47 forks source link

[QUESTION] How to find xcresult and read it without knowing the exact filename - like using RegEx or such? #71

Closed MartinMajewski closed 2 years ago

MartinMajewski commented 2 years ago

Hi there,

I love your project but somehow, the usage is not feasible in the XCode environment currently provided by Apple. Why? Let me explain:

I want to read out attachments of the xcresult file and store it elsewhere for easier access. Moreover, I have to do this in Azure Pipelines, where I do not have lasting access to the worker instance, as it is destroyed after everything is finished. So I have to read out all data during a pipeline job.

Now, even on my local machine, I found that the xcresult file is inconveniently stored in the DerivedData folder and here in a projects folder with an arbitrary appendix in the folder's name. Even more, in this folder, there are several xcresult files, all with a naming scheme like '''Test-PROJECTNAME_iOS-2021.12.02_11-25-32-+0100.xcresult'''

So, how can I use xcparse to get the latest of those files? Wildcards seem not to work.

I find it somewhat interesting that nobody else seems to care about the location of the xcresult file. All examples and tutorials assume it in a location like "Desktop". Is there a way to configure XCode to store this file at a custom path?

Best wishes, Martin

abotkin-cpi commented 2 years ago

Yeah, the tutorials may often skip this as several commonly used CI systems will simplify this by giving you an environment variable that gives you the xcresult path from your Xcode run (Bitrise, which we use, does this) or allows you to specify where you want the file (like fastlane).

Apple talked a bit about how to do this in WWDC 2019 on slide 137 - xcodebuild has an option to specify the result bundle path (-resultBundlePath).

xcodebuild test -project MyProject.xcodeproj -scheme MyScheme -resultBundlePath /path/to/ResultBundle.xcresult

You can set the result bundle name directly that way or just give it a directory like ~/Desktop if you prefer to let Xcode name it itself still.

I'm unfamiliar with Azure Pipelines, but if you can link us to how you build with Xcode there, I can see if there's any further advice we can provide if you're not using xcodebuild directly.

EDIT: Looks like they may be missing this option in their plugin system (https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/xcode?view=azure-devops). Could you open an issue in their repo (https://github.com/microsoft/azure-pipelines-tasks/issues) specifying that you'd like to specify the "-resultBundlePath" found in xcodebuild so you can get access to the xcresult from the run?

-resultBundlePath PATH specifies the directory where a result bundle describing what occurred will be placed

You can provide them the above spiel from xcodebuild to give them context.

Once you've opened that issue, please link it here as well & I can help follow up with them in a comment. Would prefer you own the issue since you actually have access to Azure Pipelines.

MartinMajewski commented 2 years ago

Thank you very much for the reply.

Yes, the Xcode@5 task has no native input parameter for setting the resultBundlePath. However, it can be set anyways within the args parameter, like this:

- task: Xcode@5
    displayName: "Xcode Unit and UI testing"
    continueOnError: true
    inputs:
        actions: test
        scheme: MyScheme_iOS
        sdk: iphonesimulator
        configuration: Debug
        xcWorkspacePath: "**/*.xcodeproj/project.xcworkspace"
        xcodeVersion: default
        packageApp: true
        useXcpretty: true
        publishJUnitResults: true
        testRunTitle: Xcode Tests
        destinationSimulators: iPhone 11 Pro
        destinationTypeOption: simulators
        destinationPlatformOption: iOS
        args: '-resultBundlePath $(System.DefaultWorkingDirectory)/xcresults/ResultBundle.xcresult'

- task: PublishPipelineArtifact@1
      displayName: "Publish xcresults Bundle"
      condition: succeededOrFailed()
      inputs:
          targetPath: $(System.DefaultWorkingDirectory)/xcresults/
          artifactName: XCResults`

Note: This example above is a stripped-down version to hide some sensible project information.

With this, I altered the path to the xcresults file, which I could then retrieve with the PublishPipelineArtifact task. So the first step is done, and I can now download the bundle and open it with XCode.

It is important to have continueOnError: true and condition: succeededOrFailed() set so that all subsequent steps are executed.

Next, I will try to parse it with your tool to retrieve only the snapshots taken by the Snapshot tool (https://github.com/pointfreeco/swift-snapshot-testing). If I find the time, I will open up a support ticket as you proposed. Maybe Microsoft can implement something more convenient.

Thank you, and stay safe! Martin

abotkin-cpi commented 2 years ago

Awesome to hear you found a solution & thanks for sharing it here for other future folks! I'm going to go ahead and close this issue since it sounds like you're all set.