swift-snapshot-testing
swift-snapshot-testing copied to clipboard
Parameterizing `scale` of image strategies
I'm really enjoying adding Snapshot testing to a side project of mine. So far I just have a dozen or so, all of the form: assertSnapshot(matching: vc, as: .image(on: .iPhoneX))
, so I was surprised when I found all of my tests failing because I had switched the target device that was running the tests, as I would not expect the fact that my tests are running on an iPhone 8 to matter for a snapshot specifying iPhone X. The source is:
public static func image(precision: Float) -> Diffing {
return Diffing(
toData: { $0.pngData()! },
fromData: { UIImage(data: $0, scale: UIScreen.main.scale)! }
...
)
}
I would suggest updating the function signature to public static func image(precision: Float, scale: CGFloat = UIScreen.main.scale) -> Diffing
, and allow ViewImageConfig
s such as iPhoneX
to pass their native scale. Happy to open a PR - I just wanted to open an issue first to see if this is a change you agree with, since it would in theory break consumers' tests that already have snapshots recorded at the wrong device scale.
+1 I've run into the same unexpected issue with switching sims.
From the README:
⚠️ Warning: Snapshots must be compared using a simulator with the same OS, device gamut, and scale as the simulator that originally took the reference to avoid discrepancies between images.
True that, I was aware of this, but if scale could be overriden, just like nevillco said, so that on: device
would run in device
's native scale, overriding it would be a more sane choice. It seems like (on: iPhoneX)
producing an image not matching iPhoneX scale is never a desired behaviour.
If it's not possible to override scale, perhaps trying to use device config of different scale than current device should fail?
Better yet, have an option to override scale or use simulator scale.
e.g. assertSnapshot(...., overrideScale: true)
With the list of devices, we could provide the scale variable
any updates here or a PR? Happy to help if needed, but I think this would be a very good addition.
Seems like parametrizing scale wouldn't work either.
I tried that and rendering of same fonts is still slightly different between 2x and 3x devices.
Seems like it is because rasterizing of fonts is slightly different in two cases.
I guess it is controlled by the selected simulator's runtime, either for 2x or 3x simulator and I didn't find a way to parametrize that in UIGraphicsImageRenderer
which is doing the actual rendering of a layer into UIImage.
What would probably work in this case is rendering views' layers into a UIGraphicsPDFRenderer
instead because it doesn't rasterize font while creating PDF.
But then we have to support PDF diffing for that.
UPD: doesn't work with UIGraphicsPDFRenderer too, because texts are also rasterized in PDF
hey @kirillsh, did you have any progress on it? I’m using the last release where it’s possible to pass the scale to create the images, but I’m facing the same issues you pointed here, since the images are scaled correctly, but when it has any text in it there are some diffs on the fonts when testing devices with a different scale. I played with some options, mainly on the properties regarding to fonts inside CGContext, but without success