---
title: Attachments
framework: testing
role: collectionGroup
role_heading: API Collection
path: testing/attachments
---

# Attachments

Attach values to tests to help diagnose issues and gather feedback.

## Overview

Overview Attach values such as strings and files to tests. Implement the Attachable protocol to create your own attachable types. Attach data or strings If your test produces encoded data that you want to save as an attachment, you can call record(_:named:sourceLocation:). struct SalesReport { ... }

@Test func `sales report adds up`() async throws {   let salesReport = await generateSalesReport()   try salesReport.validate()   let bytes: [UInt8] = try salesReport.convertToCSV()   Attachment.record(bytes, named: "sales report.csv") } You can attach an instance of Array<UInt8>, ContiguousArray<UInt8>, ArraySlice<UInt8>, or Data because these types automatically conform to Attachable. You can also attach an instance of String or Substring. The testing library treats attached strings as UTF-8 text files. If you want to save a string as an attachment using a different encoding, convert it to Data using data(using:allowLossyConversion:) and attach the resulting data instead of the original string. Attach encodable values If you have a value you want to save as an attachment that conforms to either Encodable or NSSecureCoding, you can extend it to add conformance to Attachable. When you import the Foundation module, the testing library automatically provides a default implementation of Attachable to types that also conform to Encodable or NSSecureCoding. import Testing import Foundation

struct SalesReport { ... } extension SalesReport: Encodable, Attachable {}

@Test func `sales report adds up`() async throws {   let salesReport = await generateSalesReport()   try salesReport.validate()   Attachment.record(salesReport, named: "sales report.json") } important: The testing library provides these default implementations only if your test target imports the Foundation module. Attach transferable values If you have a value you want to save as an attachment that conforms to Transferable, you can create an instance of Attachment from it when you import the Core Transferable module. import Testing import CoreTransferable

struct SalesReport { ... } extension SalesReport: Encodable, Attachable {}

@Test func `sales report adds up`() async throws {   let salesReport = await generateSalesReport()   try salesReport.validate()   let attachment = try await Attachment(exporting: salesReport)   Attachment.record(attachment) } important: The testing library provides this Attachment initializer only if your test target imports the Core Transferable module. When you create an attachment from a transferable value, the testing library calls the value’s exported(as:) function. By default, the testing library calls the value’s exportedContentTypes(_:) function and uses the first returned content type that conforms to UTType.data. If you want to use a different format for the attachment, you can pass another content type supported by the attachable value when you create the attachment. let attachment = try await Attachment(exporting: salesReport, as: .pdf) Attach files and directories If you have a file you want to save as an attachment, you can attach it using its file URL. The testing library needs to read or map the file before attaching it to your test, and those operations can fail, so you need to explicitly create an instance of Attachment before you record it. import Foundation

@Test func `sales report adds up`() async throws {   let salesReport = await generateSalesReport()   try salesReport.validate()   let salesReportURL = try salesReport.save()   let attachment = try await Attachment(contentsOf: salesReportURL)   Attachment.record(attachment) } You can also attach a directory to a test using its file URL. When you attach a directory to a test, the testing library creates a ZIP file containing the directory’s contents, then attaches that ZIP file in place of the directory. Attach images You can attach instances of the following system-provided image types to a test:  |   |   |   |   |  When you attach an image to a test, you can specify the image format to use in addition to a preferred name. struct SalesReport { ... }

@Test func `sales report adds up`() async throws {   let salesReport = await generateSalesReport()   let image = try salesReport.renderTrendsGraph()   Attachment.record(image, named: "sales report", as: .png) } If you don’t specify an image format when attaching an image to a test, the testing library selects the format to use based on the preferred name you pass. Attach other values If you have a value that needs a custom encoded representation when you save it as an attachment, implement withUnsafeBytes(for:_:). The implementation of this function calls its body argument and passes the encoded representation of self or, if a failure occurs, throws an error representing that failure. struct SalesReport { ... }

extension SalesReport: Attachable {   borrowing func withUnsafeBytes<R>(     for attachment: borrowing Attachment<Self>,     _ body: (UnsafeRawBufferPointer) throws -> R   ) throws -> R {     let bytes = try salesReport.convertToCSV() // might fail to convert to CSV     try bytes.withUnsafeBytes { buffer in // rethrows any error from `body`       try body(buffer)     }   } } If your type conforms to Sendable, the testing library avoids calling this function until it needs to save the attachment. If your type  doesn’t conform to Sendable, the testing library calls this function as soon as you record the attachment. Customize attachment behavior If you can reliably estimate in advance how large the encoded representation will be, implement estimatedAttachmentByteCount. The testing library uses the value of this property as a hint to optimize memory and disk usage. extension SalesReport: Attachable {   ...

var estimatedAttachmentByteCount: Int? {     return self.entries.count * 123   } } You can also implement preferredName(for:basedOn:) if you want to customize the name of the attachment when saving it. extension SalesReport: Attachable {   ...

borrowing func preferredName(     for attachment: borrowing Attachment<Self>,     basedOn suggestedName: String   ) -> String {     if suggestedName.contains(".") {       // The name already contains a path extension, so don't append another.       return suggestedName     }

// Append ".csv" to the name so the resulting file opens as a spreadsheet.     return "\(suggestedName).csv"   } } Inspect attachments after a test run ends By default, the testing library saves your attachments as soon as you call record(_:sourceLocation:) or record(_:named:sourceLocation:). You can access saved attachments after your tests finish running: When using Xcode, you can access attachments from the test report. When using Visual Studio Code, the testing library saves attachments to .build/attachments by default. Visual Studio Code reports the paths to individual attachments in its Tests Results panel. When using Swift Package Manager’s swift test command, you can pass the --attachments-path option. The testing library saves attachments to the specified directory. If you do not pass the --attachments-path option, the testing library does not save any attachments you record.

## Topics

### Attaching values to tests

- [Attachment](testing/attachment.md)
- [Attachable](testing/attachable.md)
- [AttachableWrapper](testing/attachablewrapper.md)

### Attaching images to tests

- [AttachableAsImage](testing/attachableasimage.md)
- [AttachableImageFormat](testing/attachableimageformat.md)
- [init(_:named:as:sourceLocation:)](testing/attachment/init(_:named:as:sourcelocation:).md)
- [record(_:named:as:sourceLocation:)](testing/attachment/record(_:named:as:sourcelocation:).md)
