Using `XCTAttachment` To Debug Failing Tests

August 14, 2021

Over the past few years we have gained wonderful improvements to the XCTest framework. One such improvement is the ability to attach resources (files, images, etc) to a test result using XCTest/XCTAttachment.

A Quick Introduction

The XCTAttachment is a class representing data attached to a test run, and is useful when debugging failing tests. Attachments are added to an XCTest/XCTActivity using the add(_ attachment: XCTAttachment) function. The XCTest/XCTestCase, which all tests inherit from, adopts the XCTActivity protocol, making it super easy to add attachments.

There are lots of initializers for attaching raw data, files, images, etc., and the XCTAttachment.h header does a nice job documenting the API.

Here's a simple example showing how to attach JSON data to a test.

func testDoSomething() throws {
    let customer = Customer(firstName: "Brian", lastName: "Coyner")
    let json = try JSONEncoder().encode(customer)
    
    add(XCTAttachment(data: json, uniformTypeIdentifier: UTType.json.identifier))
    
    // perform assertions here
}

If the test fails, then the JSON data is attached to the test run.

Viewing The Attachments

You can view the test run results in Xcode's Report navigator view.

Xcode Test Result

There's even a QuickLook option.

Xcode Test Result

Attachment Lifetime

An attachment has a lifetime property controlling whether the attachment gets attached to the test run. The default is deleteOnSuccess, but the value can be set to keepAlways. I have yet to come up with a use case for using the keepAlways option.

Here's the same example from above but with the lifetime property set to keepAlways.

func testDoSomething() throws {
    let customer = Customer(firstName: "Brian", lastName: "Coyner")
    let json = try JSONEncoder().encode(customer)
    
    let attachment = XCTAttachment(data: json, uniformTypeIdentifier: UTType.json.identifier)
    attachment.lifetime = .keepAlways
    add(attachment)
    
    // perform assertions here
}
Xcode Test Result

Other Attachment Properties

An attachment has an optional name. The attachment's file is named using the name property. If a name is not set, then the attachment's file name is derived using the type identifer.

There's also a userInfo dictionary allowing you to add metadata describing the attachment. However, as of Xcode 12.5, the test result package does not appear to include the metadata.

Wrapping Up

The XCTAttachment is a nice tool to have when debugging tests. Be sure to take a look at the XCTAttachment documentation for additional notes and examples.