[Pitch] Image attachments in Swift Testing (Windows) (original) (raw)
August 29, 2025, 1:52pm 1
In ST-0014, we introduced the ability to attach an image to a test in Swift Testing and have the testing library automatically serialize it to a PNG, JPEG, or other image format. This proposal was intentionally limited to Apple platforms and Apple image types because image serialization is inherently platform-specific.
The natural next step for this feature is to extend it to other platforms. The next platform I propose adding support for is Windows:
import Testing
import WinSDK
@MainActor @Test
func `attaching an HBITMAP`() throws {
let bitmap: HBITMAP = ...
defer {
DeleteObject(bitmap)
}
Attachment.record(bitmap, named: "GDI bitmap", as: .png)
}
@MainActor @Test
func `attaching an IWICBitmapSource`() throws {
let bitmap: UnsafeMutablePointer<IWICBitmapSource> = ...
defer {
bitmap.lpVtbl.Release(bitmap)
}
Attachment.record(bitmap, named: "WIC bitmap", as: .jpeg)
}
Read the full proposal here.
Trying it out
To try this feature out, add a dependency to the main branch of swift-testing to your project:
...
dependencies: [
...
.package(
url: "https://github.com/swiftlang/swift-testing.git",
branch: "main"
),
]
Then, add two target dependencies to your test target:
.testTarget(
...
dependencies: [
...
.product(name: "Testing", package: "swift-testing"),
.product(name: "_Testing_ExperimentalImageAttachments", package: "swift-testing"),
]
Add the following imports to any source file that will attach an image to a test:
import WinSDK
@_spi(Experimental) import _Testing_WinSDK
Note: This extra product dependency and extra
importstatement are a side effect of how packages are built. They will not be required in the final implementation of this feature.
tristanlabelle (Tristan Labelle) August 29, 2025, 3:47pm 2
This is trickier on Windows because of the multiplicity of frameworks and general incompatibility between them. HBITMAP and IWICImageSource make sense as the most foundational types, but it’ll leave UWP and WinUI apps without an easy option (they use Windows.UI.Xaml.Media.ImageSource and Microsoft.UI.Xaml.Media.ImageSource respectively). Since the proposal mentions .NET interop, it should also mention WinRT, whether or not a solution is offered there (which is difficult because we don’t have standard Swift projections into WinRT).
I think excluding ID2D1Image makes sense since it can represent a rendering graph or an image in GPU memory.
So inasmuch as image attachments are useful/feasible on Windows, I think this proposal is scoped right.
grynspan (Jonathan Grynspan) August 29, 2025, 4:09pm 3
The absence of WinRT is just an oversight on my part, and I'll amend the proposal to mention it too. As far as I'm aware, there is no way to reference Windows.Graphics.Imaging.SoftwareBitmap from Swift, so there's no way for us to provide support for it. In the future, if Swift gains the ability to interact with WinRT types, we can certainly revisit.
tristanlabelle (Tristan Labelle) August 30, 2025, 2:06pm 4
there is no way to reference
Windows.Graphics.Imaging.SoftwareBitmapfrom Swift
You’re right that this class would be the best match, but not quite right that it can’t be referenced from Swift:
- My employer’s project: GitHub - thebrowsercompany/swift-winrt: Swift Language Projection for WinRT
- My own project: tristanlabelle/swift-winrt: A Swift Projection for WinRT APIs
so there's no way for us to provide support for it
That’s probably correct though! Either of these projects are far from being integratable in the Swift toolchain and would probably use a per-project code generation model anyways.
Also, one possible path for Swift to consume COM APIs like IWICImageSource would be to generate bindings from the Win32 metadata API description project, in which case that would probably not be source compatible with UnsafeMutablePointer<WinSDK.IWICImageSource>. This is the approach that Rust and C# take, although I Swift might prefer a language-level C++ interop approach.
grynspan (Jonathan Grynspan) August 30, 2025, 2:15pm 5
I should clarify that they can't be used from the Swift toolchain (at least, not at this time.) Improvements to C++ interop over time may help here.
I mention this in the Future directions section. If this comes to pass, we would make the necessary compatibility changes in Swift Testing of course.