-
Notifications
You must be signed in to change notification settings - Fork 129
Provide prose documentation for attachments. #1413
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
035bce0
99382f8
993612a
89bbb36
1dedd54
afcbc5b
9b956a0
9e32ed7
294ec65
e78a5be
a28d931
730ce2e
5386947
8899d4f
06411ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -17,6 +17,174 @@ Attach values to tests to help diagnose issues and gather feedback. | |||||||||
| 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 ``Attachment/record(_:named:sourceLocation:)``: | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a colon here to introduce a code sample/snippet is pretty standard practice. Compare this (previously-reviewed) article: https://developer.apple.com/documentation/testing/enablinganddisabling Since we're already doing it in other files, I'd prefer to remain consistent, but could I ask you to get a DevPubs verdict and, if changes are needed, we can apply them globally in another PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DevPubs verdict: We use the colon when we mention the snippet, such as "The following code example shows..." and "In the code below, X does Z....". If we don't mention the code, it isn't an introductory sentence and takes a period.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it sufficient to end the sentence(s) I have now and then add "For example:"? I do want to make sure it's clear that the following code is related to the preceding text and not just appearing out of nowhere. |
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| 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>`](https://developer.apple.com/documentation/swift/array), | ||||||||||
| [`ContiguousArray<UInt8>`](https://developer.apple.com/documentation/swift/contiguousarray), | ||||||||||
| [`ArraySlice<UInt8>`](https://developer.apple.com/documentation/swift/arrayslice), | ||||||||||
| or [`Data`](https://developer.apple.com/documentation/foundation/data) as | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| these types automatically conform to ``Attachable``. | ||||||||||
|
|
||||||||||
| You can also attach an instance of [`String`](https://developer.apple.com/documentation/swift/string) | ||||||||||
| or [`Substring`](https://developer.apple.com/documentation/swift/substring). The | ||||||||||
| testing library assumes that it should treat attached strings as UTF-8 text | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| files. If you want to save a string as an attachment using a different encoding, | ||||||||||
| convert it to [`Data`](https://developer.apple.com/documentation/foundation/data) | ||||||||||
| using [`data(using:allowLossyConversion:)`](https://developer.apple.com/documentation/swift/stringprotocol/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`](https://developer.apple.com/documentation/swift/encodable) or | ||||||||||
| [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding), | ||||||||||
| you can extend it to add conformance to ``Attachable``. When you import the | ||||||||||
| [Foundation](https://developer.apple.com/documentation/foundation) module, the | ||||||||||
| testing library automatically provides a default implementation of | ||||||||||
| ``Attachable`` to types that also conform to [`Encodable`](https://developer.apple.com/documentation/swift/encodable) | ||||||||||
| or [`NSSecureCoding`](https://developer.apple.com/documentation/foundation/nssecurecoding): | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| 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 only provides these default implementations if | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| your test target imports the [Foundation](https://developer.apple.com/documentation/foundation) | ||||||||||
| module. | ||||||||||
|
|
||||||||||
| ### Attach images | ||||||||||
|
|
||||||||||
| You can attach instances of the following system-provided image types to a test: | ||||||||||
|
|
||||||||||
| | Platform | Supported Types | | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| |-|-| | ||||||||||
| | macOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`NSImage`](https://developer.apple.com/documentation/appkit/nsimage) | | ||||||||||
| | iOS, watchOS, tvOS, and visionOS | [`CGImage`](https://developer.apple.com/documentation/coregraphics/cgimage), [`CIImage`](https://developer.apple.com/documentation/coreimage/ciimage), [`UIImage`](https://developer.apple.com/documentation/uikit/uiimage) | | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| | Windows | [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps), [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons), [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) (including its subclasses declared by Windows Imaging Component) | | ||||||||||
|
|
||||||||||
| When you attach an image to a test, you can specify the image format to use in | ||||||||||
| addition to a preferred name: | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| 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) | ||||||||||
grynspan marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| If you don't specify an image format when attaching an image to a test, the | ||||||||||
| testing library infers which format to use based on the preferred name you pass. | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| ### Attach other values | ||||||||||
|
|
||||||||||
| If you have a value that needs a custom encoded representation when you save it | ||||||||||
| as an attachment, implement ``Attachable/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: | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| 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`](https://developer.apple.com/documentation/swift/sendable), | ||||||||||
| the testing library avoids calling this function until it needs to save the | ||||||||||
| attachment. If your type does _not_ conform to [`Sendable`](https://developer.apple.com/documentation/swift/sendable), | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| 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 ``Attachable/estimatedAttachmentByteCount``. The testing | ||||||||||
| library uses the value of this property as a hint to optimize memory and disk | ||||||||||
| usage: | ||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| extension SalesReport: Attachable { | ||||||||||
| ... | ||||||||||
|
|
||||||||||
| var estimatedAttachmentByteCount: Int? { | ||||||||||
| return self.entries.count * 123 | ||||||||||
| } | ||||||||||
| } | ||||||||||
| ``` | ||||||||||
|
|
||||||||||
| You can also implement ``Attachable/preferredName(for:basedOn:)`` if you wish to | ||||||||||
| customize the name of the attachment when it is saved: | ||||||||||
|
Comment on lines
+152
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Holding for feedback on : vs . |
||||||||||
|
|
||||||||||
| ```swift | ||||||||||
| extension SalesReport: Attachable { | ||||||||||
| ... | ||||||||||
|
|
||||||||||
| borrowing func preferredName( | ||||||||||
| for attachment: borrowing Attachment<Self>, | ||||||||||
| basedOn suggestedName: String | ||||||||||
| ) -> String { | ||||||||||
| if suggestedName.lastIndex(of: ".") != nil { | ||||||||||
| // The name already contains a path extension, so do not append another. | ||||||||||
grynspan marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||
| 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 | ||||||||||
| ``Attachment/record(_:sourceLocation:)`` or | ||||||||||
| ``Attachment/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. | ||||||||||
grynspan marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
|
|
||||||||||
| ## Topics | ||||||||||
|
|
||||||||||
| ### Attaching values to tests | ||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,18 +15,6 @@ | |
| /// | ||
| /// - ``Trait/savingAttachments(if:)`` | ||
| /// | ||
| /// By default, the testing library saves your attachments as soon as you call | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file is all SPI. |
||
| /// ``Attachment/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 add an instance of this trait type to a test, any attachments that | ||
| /// test records are stored in memory until the test finishes running. The | ||
| /// testing library then evaluates the instance's condition and, if the | ||
|
|
@@ -228,18 +216,6 @@ extension Trait where Self == AttachmentSavingTrait { | |
| /// - Returns: An instance of ``AttachmentSavingTrait`` that evaluates the | ||
| /// closure you provide. | ||
| /// | ||
| /// By default, the testing library saves your attachments as soon as you call | ||
| /// ``Attachment/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 add this trait to a test, any attachments that test records are | ||
| /// stored in memory until the test finishes running. The testing library then | ||
| /// evaluates `condition` and, if the condition is met, saves the attachments. | ||
|
|
@@ -266,18 +242,6 @@ extension Trait where Self == AttachmentSavingTrait { | |
| /// - Returns: An instance of ``AttachmentSavingTrait`` that evaluates the | ||
| /// closure you provide. | ||
| /// | ||
| /// By default, the testing library saves your attachments as soon as you call | ||
| /// ``Attachment/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 add this trait to a test, any attachments that test records are | ||
| /// stored in memory until the test finishes running. The testing library then | ||
| /// evaluates `condition` and, if the condition is met, saves the attachments. | ||
|
|
@@ -305,18 +269,6 @@ extension Trait where Self == AttachmentSavingTrait { | |
| /// - Returns: An instance of ``AttachmentSavingTrait`` that evaluates the | ||
| /// closure you provide. | ||
| /// | ||
| /// By default, the testing library saves your attachments as soon as you call | ||
| /// ``Attachment/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 add this trait to a test, any attachments that test records are | ||
| /// stored in memory until the test finishes running. The testing library then | ||
| /// evaluates `condition` and, if the condition is met, saves the attachments. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.