---
title: Allure Report 3 - XCResults Reader
description: The guide describes how you can generate an Allure Report based on Xcode test results
---

# Allure Report 3: XCResults Reader (Allure 3)

Allure Report 3 introduces native support for Apple Xcode test results. You can now generate fully functional Allure reports directly from your XCTest and/or Swift Testing executions without additional conversion tools.

This article is both an overview of features and a basic integration guide for your Xcode projects.

Info: Note
Allure 2 requires you to use the separate [xcresults CLI tool](https://github.com/eroshenkoam/xcresults) to export Xcode test results into a compatible format. The vast majority of its features are present in Allure 3, and many more advanced ones were added on top. Read on to find out the details.

## Getting Started

### Prerequisites

- [Xcode IDE](https://developer.apple.com/xcode/)
- [Xcode-generated test results](https://developer.apple.com/documentation/xcode/running-tests-and-interpreting-results)
- [Allure 3](https://github.com/allure-framework/allure3)

Tip:
The full Xcode IDE is required for proper report generation. Xcode Command Line Tools Package is not sufficient. Moreover, if you install the full Xcode IDE on top of the CLI, make sure to set it as the active development environment via [xcode-select --switch](https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-SOURCECODE4)

### Sample Project

You can explore various examples of Xcode tests and see how Allure displays the results in its reports here:

https://github.com/allure-examples/allure3-xcresult

### Generate Report

Allure Report can read Xcode test results and generate reports from them - simply use Swift Testing’s or XCTest’s standard features and Allure will automatically extract the structure, outcomes, and metadata from your test results.

You can generate a basic Allure report from your .xcresult bundle directly, no additional changes to the code required:

`npx allure generate <path/to/xcresult/file> -o <path/to/report/directory>`

And then open it like any other Allure report:

`npx allure open <path/to/report/directory>`

Below are some examples of Xcode tests and how they will be displayed in Allure Report.

**Swift Testing:**
```swift
import Testing

struct MathTests {
    @Test
    func addition() async throws {
        let result = 2 + 3
        #expect(result == 5)
    }

    @Test
    func incorrectMultiplication() async throws {
        let result = 3 * 4
        #expect(result == 11) // This will fail
    }
}
```

**XCTest:**
```swift
import XCTest

final class MathTests: XCTestCase {
    func testAddition() throws {
        let result = 2 + 3
        XCTAssertEqual(result, 5)
    }

    func testIncorrectMultiplication() throws {
        let result = 3 * 4
        XCTAssertEqual(result, 11) // This will fail
    }
}
```

![Xcode in Allure Report](/images/guides/xcresults/xcresults_02.png "Xcode in Allure Report")

# Supported Features

While any existing Xcode test results can be turned into an Allure Report, and most metadata will be picked up automatically, you might want to organize and label your tests a certain way to get the most out of Allure. Explore this section to learn how various features work, and how they are reflected in the resulting report.

(Swift Testing) and (XCTest) badges will be used below to mark which framework(s) a particular feature applies to.

## 1. Setting Custom Names for Tests (Swift Testing) (XCTest)

Unless otherwise specified, Allure uses test function names as names. You can also give a custom name to your test. In Swift Testing, you accomplish this using the `@Test` annotation, while XCTest employs a naming convention for activities that lets you add various metadata to tests, including custom names. We'll discuss the naming convention API in more detail [below](#_3-3-allure-api-metadata-naming-convention).

**Swift Testing:**
```swift

@Test("This name was assigned to the test via the @Test annotation")
func renamedTest() async throws {

}

```

**XCTest:**
```swift
final class AllureApiActivities: XCTestCase {
    func testDisplayName() throws {
        XCTContext.runActivity(named: "allure.name:This name was set by an activity", block: { _ in })
    }
}
```

## 2. Working With Outcomes

### Failed Assertions (Swift Testing) (XCTest)

When a test result includes one or more failed assertions, it is marked as failed. The failures’ count and the details of the failures are listed on the result page.

![Xcode Failed Assertions in Allure Report](/images/guides/xcresults/xcresults_15.png "Xcode Failed Assertions in Allure Report")

Refer to [this example](https://allure-examples.github.io/allure3-xcresult/main/#f24e5564a18e8e57ddeda434b22069b5) to see how Allure handles multiple failed assertions specifically.

### Uncaught Exceptions (Swift Testing) (XCTest)

When a test throws an uncaught exception, test frameworks mark it as failed and Allure captures the exception details in the failure report. Such tests will be labeled **Broken** in Allure report.

![Xcode Uncaught Exceptions in Allure Report](/images/guides/xcresults/xcresults_05.png "Xcode Uncaught Exceptions in Allure Report")

### Skipping Tests (Swift Testing) (XCTest)

Swift Testing provides native test skipping through the `.disabled()` trait. You can optionally include a description explaining why the test is disabled. These appear as **Skipped** in Allure report with the reason displayed. XCTest supports skipping via the `XCTSkip()` error.

**Swift Testing:**
```swift
@Test(.disabled("This description was provided via the disabled trait"))
func skippedTestWithDescription() async throws {
}

```

**XCTest:**
```swift
func testSkippedTestWithDescription() throws {
    throw XCTSkip("This description was provided via XCTSkip")
}
```

![Xcode Skipped Tests in Allure Report](/images/guides/xcresults/xcresults_16.png "Xcode Skipped Tests in Allure Report")

### Expected Failures (XCTest)

XCTest's `XCTExpectFailure()` allows you to mark tests containing asserts that are known to fail. When an expected failure occurs, the test passes. If the test unexpectedly passes or fails in a different way, it's marked as failed. Allure distinguishes between expected and unexpected failures in the report.

```swift
func testOneExpectedFailureWithMessage() throws {
    XCTExpectFailure("This message was set via XCTExpectFailure")
    XCTAssertEqual("foo", "bar")
}

func testUnmetExpectedFailure() throws {
    XCTExpectFailure()
    XCTAssertEqual("foo", "foo")  // This passes, but we expected it to fail
}

```

In the example above `testOneExpectedFailureWithMessage` will be marked as **passed** in Allure, as we expected the assertion inside it to fail, while `testUnmetExpectedFailure` will be displayed as failed - as we expected the assertion to fail, but it passed instead.

`XCTExpectFailure()` works in a logical OR manner: if at least one assertion after this function fails, the whole test passes. Otherwise, the test fails.

**Example**: code [sample](https://github.com/allure-examples/allure3-xcresult/blob/main/XcresultSamplesXCTests/ExpectedFailures.swift) and the [report generated based on it](https://allure-examples.github.io/allure3-xcresult/main/).

## 3. Test Grouping and Labeling

Allure 3 can be configured to group test results into a convenient navigation tree by a wide variety of labels. This section discusses how these labels are mapped and processed by the tool.

### 3.1. Suites and Suite Hierarchy (Swift Testing) (XCTest)

Allure has three levels of suites:

- parentSuite
- suite
- subSuite

The exact mapping of these levels depends on the test framework.

#### Swift Testing

**Suite hierarchy** is mapped to Allure's navigation tree, creating a nested organization in the Allure report matching your code structure:

- The **module name** always becomes the **parentSuite** in Allure
- The top-level Swift Testing suite becomes the **suite** in Allure
- nested suites become **subSuites** (if there are more than two nested suites, they are joined with > and the result is assigned to **subSuite**)

- **Unannotated suites** use struct names (`UnannotatedSuite` → `UnannotatedSubSuite`)
- **Named suites** use custom names (`Named suite` → `Named sub-suite`)
- **testClass** and **testMethod** labels always hold the original names of the class/struct and the method.

```swift
// Unannotated suite - uses struct name
struct UnannotatedSuite {
    struct UnannotatedSubSuite {
        struct UnannotatedSubSubSuite {
            @Test("testInSubSubSuite (defined in Suites.swift)")
            func testInSubSubSuite(){

            }
        }

        @Test("testInSubSuite (defined in Suites.swift)")
        func testInSubSuite(){

        }
    }

    @Test("testInTopLevelSuite (defined in Suites.swift)")
    func testInTopLevelSuite(){

    }
}

// Named suite with @Suite annotation
@Suite("Named suite") struct NamedSuites {
    @Suite("Named sub-suite") struct NamedSubSuite {
        @Test("testInNamedSubSuite (defined in Suites.swift)")
        func testInNamedSubSuite(){

        }
    }

    @Test("testInNamedTopLevelSuite (defined in Suites.swift)")
    func testInNamedTopLevelSuite(){

    }
}

```

![Xcode Suites in Allure Report](/images/guides/xcresults/xcresults_06.png "Xcode Suites in Allure Report")

#### XCTest

For XCTest, Allure suites are based on the class structure of the test files:

- The **module name** always becomes the **parent suite** in Allure
- Each **class** becomes a **suite** in Allure
- **testClass** label shows the class name
- **suite** label typically matches the class name

```swift
final class Activities: XCTestCase {
    func testOnePassedActivity() throws {
        XCTContext.runActivity(named: "Step 1", block: { _ in })
    }

    func testOneActivityWithOneFailedAssertion() throws {
        XCTContext.runActivity(named: "Step 1") { _ in
            XCTAssertEqual("foo", "bar")
        }
    }
```

### 3.2. Packages (Swift Testing) (XCTest)

Allure automatically creates package labels using the format `<project>.<bundle>`:

**Examples from the sample project:**

- [`XcresultSamples.XcresultSamplesSwiftTests`](https://allure-examples.github.io/allure3-xcresult/main/#a07256b6c04ead7cfdd484ca63460056) (Swift Testing tests)

These appear as `package` labels in Allure reports.

### 3.3. Activities and Steps (XCTest)

XCTest supports organizing tests into activities within a single test function, which Allure then translates into [steps](/docs/steps/). Each activity becomes a step (or substep) in the test execution flow.

```swift
func testSixNestedSteps() throws {
    XCTContext.runActivity(named: "Step 1") { _ in
        XCTContext.runActivity(named: "Step 1.1") { _ in

        }
        XCTContext.runActivity(named: "Step 1.2") { _ in

        }
    }
    XCTContext.runActivity(named: "Step 2") { _ in
        XCTContext.runActivity(named: "Step 2.1") { _ in

        }
        XCTContext.runActivity(named: "Step 2.2") { _ in

        }
    }
}

```

![Xcode Activities in Allure Report](/images/guides/xcresults/xcresults_07.png "Xcode Activities in Allure Report")

Tip:
Allure has an API that allows to add native Allure metadata (which XCTest doesn’t support) to your tests by naming activities according to a certain convention, which we discuss in the section below. Allure doesn’t translate activities named according to the API convention into steps.

### 3.4. Allure API: Metadata Naming Convention (XCTest)

XCTest activity names additionally serve as a vehicle to add native Allure metadata and labels to your tests.

The `allure.*` prefixed activity names become rich metadata in the report:

- `allure.name:` sets custom test names
- `allure.label.*:` adds Allure labels
- `allure.parameter.*:` adds parameter information with masking options
- `allure.description.:` adds a description
- `allure.link.*:` adds a link (there are convenient shorthands for adding links to bugs, which we discuss [below](#_5-issue-tracking))
- `allure.flaky` marks a test as [flaky](/docs/test-stability/#flaky-tests).

```swift
func testDisplayName() throws {
    XCTContext.runActivity(named: "allure.name:This name was set by an activity", block: { _ in })
}

func testLabel() throws {
    XCTContext.runActivity(named: "allure.label.owner:John Doe", block: { _ in })
}

func testParameters() throws {
    XCTContext.runActivity(named: "allure.parameter.Regular parameter:Value 1", block: { _ in })
    XCTContext.runActivity(named: "allure.parameter.Masked parameter[masked]:Value 2", block: { _ in })
}
```

Tip:
Allure doesn’t translate such activities into test steps, so you shouldn’t put any actual test code in them.

Make also sure that activities used to insert Allure metadata into tests are not nested, otherwise they won’t be properly recognized. This is a change from Allure 2’s xcresultstool CLI tool behavior, that parses even nested activities for metadata.

**Example**: code [sample](https://github.com/allure-examples/allure3-xcresult/blob/main/XcresultSamplesXCTests/AllureApiActivities.swift) and [report](https://allure-examples.github.io/allure3-xcresult/main/)

### 3.5. Tags (Swift Testing)

Allure 3 supports Swift Testing tags. Currently they are displayed among the labels on the test result page, and in future releases it will be possible to filter by them.

```swift
extension Tag {
    @Tag static var fromSuite: Self
    @Tag static var fromSubSuite: Self
    @Tag static var fromTest: Self
}

@Suite(.tags(.fromSuite)) struct Tags {
    @Suite(.tags(.fromSubSuite)) struct SubSuite {
        @Test(.tags(.fromTest)) func hasTagsFromBothSuitesAndTest() {

        }

        @Test func hasTagsFromSuitesOnly() {

        }
    }

    @Test(.tags(.fromTest)) func hasTagsFromOneSuiteAndTest() {

    }
}

```

Example: code [sample](https://github.com/allure-examples/allure3-xcresult/blob/3b79ff76b643ab36188aa38afc1d19eaffe146a7/XcresultSamplesSwiftTests/Tags.swift#L12) and [report](https://allure-examples.github.io/allure3-xcresult/main/#3483a7ad2fdf38ffa2ecf4f586a96a1d).

### 3.6. Test Repetitions (Swift Testing) (XCTest)

Allure supports repeated test executions, if the source bundle contains them. You can find repetition results on the **Retries** tab of a test result page.

Tip:
‘Retries’ is the term that Allure uses for repeated test executions. It has the same meaning as ‘repetitions’ in Xcode.

![Xcode Repetitions in Allure Report](/images/guides/xcresults/xcresults_08.png "Xcode Repetitions in Allure Report")

### 3.7. Destinations (Devices) and Multiple Test Plans (Swift Testing) (XCTest)

Allure automatically labels all Xcode tests with the destination (the physical or emulated device the tests run on), as well as with Test plan names, if such data exists in the source bundle.

If your result bundles contain result data for multiple destinations or test plans, you can generate an Allure report with all records, provided you merge the bundles from different destinations and/or test plans into a single bundle with the `xcresulttool merge` command first and then use the merged bundle to generate your Allure report.

![Xcode Destinations in Allure Report](/images/guides/xcresults/xcresults_09.png "Xcode Destinations in Allure Report")

If the source bundle contains test results for more than one destination, Allure displays the Device Details parameter in addition to the Device parameter.

Similarly, if the bundle contains test results for more than one test plan, Allure displays the Test Plan parameter.

## 4. Parameterized Tests (Swift Testing)

Parameterized testing is a native feature of Swift Testing that allows running the same test with different input values. XCTest does not have built-in parameterized test support.

```swift
struct Parameters {
    @Test(arguments: ["foo", ""], [1, 2])
    func twoParametersOneFail(Text text: String, Count count: Int) async throws {
        #expect(!text.isEmpty) // Fails for ("", 1) and ("", 2)
        #expect(count > 0)
    }
}
```

In Allure report each combination of parameters becomes a separate test result grouped under a single Suite. For each test result, parameter values are listed in the report.

![Xcode Parameterized Tests in Allure Report](/images/guides/xcresults/xcresults_14.png "Xcode Parameterized Tests in Allure Report")

**Example**: code [sample](https://github.com/allure-examples/allure3-xcresult/blob/main/XcresultSamplesSwiftTests/Parameters.swift) and [report](https://allure-examples.github.io/allure3-xcresult/main/).

## 5. Issue Tracking (Swift Testing) (XCTest)

Issue tracking is a native feature of Swift Testing that allows linking tests to known issues. XCTest does not have built-in issue tracking support, but just like with custom names, the [Activity naming convention](#_3-4-allure-api-metadata-naming-convention) can be used to add links to issues.

In Allure, if this metadata is given, it is transformed into clickable issue links.

**Swift Testing:**
```swift
@Test(.bug("https://github.com/allure-framework/allure3/issues/2", id: "2", "Issue #2"))
func bugUrlNameAndId() async throws {
}
```

**XCTest:**
```swift
func testIssueLink() throws {
    XCTContext.runActivity(named: "allure.issue.Issue 2:https://github.com/allure-framework/allure3/issues/2", block: { _ in })
}
```

![Xcode Issue Tracking in Allure Report](/images/guides/xcresults/xcresults_11.png "Xcode Issue Tracking in Allure Report")

## 6. Attachments (XCTest)

Attachments allow you to include additional data (text, screenshots, logs) with your test results for debugging and analysis. Swift Testing will support basic attachments in Swift 6.2, but currently only XCTest provides full attachment capabilities.

```swift
func testTextAttachment() throws {
    XCTContext.runActivity(named: "allure.description:The attachment is visible in the 'Multiple destinations' report only", block: { _ in })
    let attachment = XCTAttachment(string: "Lorem Ipsum")
    attachment.name = "A text attachment"
    self.add(attachment)
}

```

Text attachments can include logs, debug information, or any string data. You can optionally provide a name for better organization. Unnamed attachments get default names in Allure reports.

![Xcode Attachments in Allure Report](/images/guides/xcresults/xcresults_17.png "Xcode Attachments in Allure Report")

Unlike Allure 2, in Allure 3 attachments are displayed chronologically, in the order they were created.

Depending on type, attachments are handled differently. Images, for example, will be rendered within Allure report itself and can be conveniently downloaded.

**Example**: code [sample](https://github.com/allure-examples/allure3-xcresult/blob/main/XcresultSamplesXCTests/Attachments.swift) and [report](https://allure-examples.github.io/allure3-xcresult/main/).

## 7. UI Testing (XCTest)

UI testing is exclusively available through XCTest and provides capabilities for automating user interface interactions and capturing visual evidence.

Allure recognizes image and video attachments generated by the XCTest UI testing and stores them in the relevant test steps.

![Xcode UI Testing in Allure Report](/images/guides/xcresults/xcresults_13.png "Xcode UI Testing in Allure Report")

**Example**: code [samples](https://github.com/allure-examples/allure3-xcresult/tree/main/XcresultSamplesUITests) and reports ([screenshots](https://allure-examples.github.io/allure3-xcresult/ui-screenshots) and [recordings](https://allure-examples.github.io/allure3-xcresult/ui-recording)).

## 8. Build Errors

Allure processes build failures as well. If the source bundle contains a single run resulting in a build failure, it will be the only result in the Allure report. If the bundle has multiple runs, some with build failures and others with test results, build failures will be displayed alongside the test outcomes.

![Xcode Build Errors in Allure Report](/images/guides/xcresults/xcresults_10.png "Xcode Build Errors in Allure Report")

## Links

- [Samples project](https://github.com/allure-examples/allure3-xcresult) and [reports](https://allure-examples.github.io/allure3-xcresult/main)
- Old [xcresults CLI tool](https://github.com/eroshenkoam/xcresults)
