ios-snapshot-test-case
ios-snapshot-test-case copied to clipboard
On failure, the reference image uses the wrong DPI, resulting in bizarre diff image
👋
I am using latest version 8.0. I have configured the following:
fileNameOptions = .none
When recording, the framework generates the image correctly. The generated image is:
-
test_iconWithLabel.png
, 600 × 200 pixels, 144 pixels/inch
When having a test failure in the same image, these are the generated failure diff images:
-
diff_test_iconWithLabel.png
, 1200 × 400 pixels, 144 pixels/inch -
failed_test_iconWithLabel.png
, 600 × 200 pixels, 144 pixels/inch -
reference_test_iconWithLabel.png
, 600 × 200 pixels, 72 pixels/inch
As you can see:
- The DPI of the
reference_test_iconWithLabel.png
image does not match the DPI of thetest_iconWithLabel.png
recorded image - The
diff_test_iconWithLabel.png
contains the following very unexpected content:
Find all images attached here: Images.zip
Similar thing (but not the same) reported in https://github.com/uber/ios-snapshot-test-case/issues/99#issuecomment-541766348
Yeah, same for me.
Looks like library ignore reference image resolution and use suffix to decide if it 72 or 144
No issue if fileNameOptions
has .screenScale
The problem is that the captured test image has size
with scale 2
when the reference image that is loaded from a file has size * 2
with scale 1
.
The quick solution looks like:
// Copied '[UIImage fb_diffWithImage:]' method with a fix for image scale.
// https://github.com/facebookarchive/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/Categories/UIImage%2BDiff.m#L35
@objc dynamic private func swizzled_fb_diff(
with image: UIImage?
) -> UIImage? {
guard let image = image else { return nil }
let scaleFactor = scale / (max(scale, image.scale))
let imageScaleFactor = image.scale / (max(scale, image.scale))
let scaledSize = size.applying(.identity.scaledBy(x: scaleFactor, y: scaleFactor))
let imageScaledSize = image.size.applying(.identity.scaledBy(x: imageScaleFactor, y: imageScaleFactor))
let imageSize = CGSize(
width: max(scaledSize.width, imageScaledSize.width),
height: max(scaledSize.height, imageScaledSize.height)
)
UIGraphicsBeginImageContextWithOptions(imageSize, true, 0)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
draw(in: CGRect(origin: .zero, size: scaledSize))
context.setAlpha(0.5)
context.beginTransparencyLayer(auxiliaryInfo: nil)
image.draw(in: CGRect(origin: .zero, size: imageScaledSize))
context.setBlendMode(.difference)
context.setFillColor(UIColor.white.cgColor)
context.fill(CGRect(origin: .zero, size: scaledSize))
context.endTransparencyLayer()
let returnImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return returnImage
}
I opened a PR with the fix https://github.com/uber/ios-snapshot-test-case/pull/198