ios-snapshot-test-case icon indicating copy to clipboard operation
ios-snapshot-test-case copied to clipboard

On failure, the reference image uses the wrong DPI, resulting in bizarre diff image

Open acecilia opened this issue 1 year ago • 2 comments

👋

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 the test_iconWithLabel.png recorded image
  • The diff_test_iconWithLabel.png contains the following very unexpected content: Screenshot 2023-10-03 at 17 18 40

Find all images attached here: Images.zip

acecilia avatar Oct 03 '23 16:10 acecilia

Similar thing (but not the same) reported in https://github.com/uber/ios-snapshot-test-case/issues/99#issuecomment-541766348

acecilia avatar Oct 03 '23 16:10 acecilia

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

roman-stetsenko-reed avatar Jan 03 '24 12:01 roman-stetsenko-reed

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
}

leonidmelnyk avatar Sep 26 '24 07:09 leonidmelnyk

I opened a PR with the fix https://github.com/uber/ios-snapshot-test-case/pull/198

leonidmelnyk avatar Sep 27 '24 11:09 leonidmelnyk