Skip to content
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

Dealing With Display Scales #128

Closed
xavierLowmiller opened this issue Dec 7, 2018 · 5 comments
Closed

Dealing With Display Scales #128

xavierLowmiller opened this issue Dec 7, 2018 · 5 comments

Comments

@xavierLowmiller
Copy link
Contributor

Question:

How do you deal with size classes on different devices?

Elaborate explanation:

We'd like to generate snapshots of views in different size classes.
To do this, we pass a UITraitCollection with different display scales to the .image function.

Consider the following test case:

func testPrimaryButtonStates() {
    // Given
    let frame = CGRect(x: 0, y: 0, width: 200, height: 48)
    let button = PrimaryButton(frame: frame)
    button.awakeFromNib()
    button.setTitle("PrimaryButton", for: .normal)

    // When
    button.testState = .enabled

    // Then
    assertSnapshot(matching: button, as: .image(traits: .init(displayScale: 2)), named: "enabled@2x")
    assertSnapshot(matching: button, as: .image(traits: .init(displayScale: 3)), named: "enabled@3x")
}

This test passes on Simulators with the same display scale (say iPhone 7 -> iPhone 8), but fails when the display scale changes (iPhone 7 -> iPhone X).
Since we run the tests on our CI on multiple devices, we can't guarantee the display scale to always be the same.

Here is a diff of the screenshots of one of the failing test cases:

screenshot 2018-12-07 at 13 19 34

@stephencelis
Copy link
Member

This unfortunately appears to be a limitation of how differently-scaled simulators render things 😞. Ideally, UIGraphicsImageRenderer would guarantee a consistent rendering given a view and a constant trait collection, but there are artifacts that can’t be accounted for. Filing a radar may help get this fixed in the future, but in the meantime you have to make one of the following choices:

  • Run tests in simulators of the same scale
  • Run tests in simulators of both scales, guarding assertions using UIScreen.main.scale
  • Introduce precision: to the assertion

Really wish there were a better solution here! Maybe in the future!

@xavierLowmiller
Copy link
Contributor Author

Thanks for the quick response!

I just checked how we dealt with this in the FBSnapshotTestCase stone age.
They append a @2x and @3x to the generated image name by default.

Would this be an option for this library, too?

@stephencelis
Copy link
Member

stephencelis commented Dec 7, 2018

@xavierLowmiller This is definitely a problem that could have a better solution, but for now you can encode this in the named argument:

assertSnapshot(matching: vc, as: .image, named: “@\(Int(UIScreen.main.scale))x”)

Not ideal, but a helper in your test suite could save you the extra work each time. We’ll try to address this better in the future, though!

@xavierLowmiller
Copy link
Contributor Author

Here's the radar: rdar://46554126

Thanks for your support!

@xavierLowmiller
Copy link
Contributor Author

Sadly, the radar was closed with "Behaving as intended": http://openradar.appspot.com/radar?id=4941361895702528....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants