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

[NTV-648] Agnostic Snapshot Testing Between M1 and Intel #1794

Merged
merged 13 commits into from
Feb 22, 2023

Conversation

msadoon
Copy link
Contributor

@msadoon msadoon commented Feb 16, 2023

📲 What

We were having trouble using FBSnapshotTestCase to record agnostically between Intel and M1 builds. This is an issue because we cannot have a cross platform build between these two types of machines and have snapshots on one machine pass on another.

Example: A screenshot recorded on M1 will pass on M1 builds but not on Intel machines.

So a developer creating a page on Intel will not be able to push up a screenshot test that will pass on an M1 machine.

Also CI currently supports Intel based machines.

Even more technical detail is noted in this older PR.

🤔 Why

The thinking here is that we cannot use the existing screenshots because they are in a different directory and were recorded on Intel machines with a different dependency.

It's not even a matter of perceptualPrecision* as was noted in the older PR above. Some screenshots will pass with 0.98 perceptual precision, (image cannot be considered different by the human eye at that percentage), but others are different by more than 50%. So it's hard to reuse some pre-recorded images from FBSnapshotTestCase with others from SnapshotTesting.

It makes sense to re-record everything in SnapshotTesting as it provides agnostic screenshot testing across Intel and M1 and smartly puts screenshots in the folder of the view that is recorded.

SnapshotTesting is also very flexible in that it allows us to take snapshots of anything.

Another benefit is cleaning out our old _64 screenshots folder, which had a lot of outdated, unused screenshots.

Yet another benefit is putting the screenshots in a directory local to the view they record, making it easier to access them via XCode (Find in Folder), but not included in the .pbx file which would bloat the project and slow down XCode.

*As screens were verified on Intel for recordings on M1 we found that some snapshots did require a perceptualPrecision of 0.98. That is completely acceptable as you can see from this post, the human eye cannot tell the difference between two images at that match rate.
Also, this post by one of the creators of SnapshotTesting does a great job plainly explaining the difference between regular per-pixel matching and perceptual precision.

FBSnapshotTestCase only did pixel by pixel matching, not perceptual precision matching. SnapshotTesting does both.

🛠 How

Manual labour.

Found every FBSnapshotVerifyView function call and replace with assertSnapshot.

Also imported SnapshotTesting into every test file.

Ran the tests, they got recorded.

Validated some snapshots that were iffy because they recorded vc.view which failed to run the assertSnapshot, instead used parent.view or vc with those tests to record with assertSnapshot.

🏎 How do we write tests now?

We still record on iPhone 8, min iOS 14.5, this is enforced in the preferredSimulatorCheck that is setup in TestCase.
Tests will fail to record and run if the schema for Kickstarter-Framework-iOS is set to anything other than iPhone 8.

We're now using something like:

        assertSnapshot(
          matching: parent.view,
          as: .image(perceptualPrecision: 0.98),
          named: "lang_\(language)_device_\(device)"
        )

Important thing to remember is perceptualPrecision which is set to 0.98 to account for differences in SnapshotTesting recording between Intel and M1.

Everything else should work as before.

🏎 Performance

New SnapshotTesting library is definitely slower (built first, then run test suite after pre-build.)
Intel test run time with FBSnapshotTest

fbsst

Intel test run time with SnapshotTesting
Screen Shot 2023-02-16 at 6 18 19 PM

So oddly, this new library comes with a significant performance cost on Intel.

However the reverse is true on M1.

SnapshotTesting
Screenshot 2023-02-16 at 6 30 43 PM

FBSnapshotTest (granted some tests did fail, unlike the other runs, but the entire suite still ran with no early exits.)
Screenshot 2023-02-16 at 6 38 00 PM

Looks like a significant improvement in running on M1

✅ Acceptance criteria

  • Ensure recordings of snapshots on M1 are passing on Intel
  • Ensure recordings of snapshots on Intel pass on M1

⏰ TODO

  • Record tests for SetYourPasswordViewController and ResetYourFacebookPasswordViewController as they are missing.
  • Remove FBSnapshotTestCase completely from project
    • remove SPM package
    • embeds in targets,
    • schema variables like FB_REFERENCE_NAME_DIR,
    • _64 director
    • Left in preferred simulator check and used in setup for XCTestCase subclass.
    • Check if codecov includes screenshots, it’ll change after above steps if it does.

This is a huge commit. But only because it's a lot of files. The idea being it replaces everything in the `_64` folder which had our old tests that were references in the `FBSnapshotTestCase` dependency. These new screenshots are not going to be in one folder. They will be local to the view they represent, similar to the organization of the `Kickstarter-Framework-iOS` target file structure. It's more ordered than having one giant reference folder because if you need to check the snapshots, it's easier find any given views' subfolder in XCode. Opening that views subfolder in XCode will give you access to the screenshots in that folder, but through Finder. The image files themselves are not included in the XCode project, so it doesn't bloat our project either.
@msadoon msadoon self-assigned this Feb 16, 2023
@msadoon msadoon added the WIP label Feb 16, 2023
@msadoon msadoon added this to the release-5.7.0 milestone Feb 16, 2023
@nativeksr
Copy link
Collaborator

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

…dded perceptual precision to only those classes.

Tests now recorded on M1 pass 100% on Intel.
@codecov
Copy link

codecov bot commented Feb 17, 2023

Codecov Report

Merging #1794 (98135d5) into main (40d368f) will increase coverage by 0.23%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##             main    #1794      +/-   ##
==========================================
+ Coverage   85.23%   85.47%   +0.23%     
==========================================
  Files        1281     1282       +1     
  Lines      116753   117246     +493     
  Branches    30823    31037     +214     
==========================================
+ Hits        99519   100211     +692     
+ Misses      16160    15960     -200     
- Partials     1074     1075       +1     
Impacted Files Coverage Δ
...ies/Controller/ActivitiesViewControllerTests.swift 100.00% <100.00%> (ø)
...r/BackerDashboardProjectsViewControllerTests.swift 100.00% <100.00%> (ø)
...ools/Controller/BetaToolsViewControllerTests.swift 100.00% <100.00%> (ø)
...e/Controller/CancelPledgeViewControllerTests.swift 100.00% <100.00%> (ø)
...troller/CategorySelectionViewControllerTests.swift 100.00% <100.00%> (ø)
...il/Controller/ChangeEmailViewControllerTests.swift 95.45% <100.00%> (ø)
...Controller/ChangePasswordViewControllerTests.swift 87.50% <100.00%> (ø)
...ontrollers/CommentRepliesViewControllerTests.swift 100.00% <100.00%> (ø)
...ents/Controllers/CommentsViewControllerTests.swift 100.00% <100.00%> (ø)
...OS/Features/Signup/SignupViewControllerTests.swift 100.00% <0.00%> (ø)
... and 59 more

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

recorded on M1, should pass on CI and locally on Intel.
…t-test-case as dependency, updated TestCase class, removed project schema variables.
…er features. Mainly because we still cannot enforce a simulator to fail a record if its' not iPhone 8.

It'll just have to be common knowledge that iPhone is our recording simulator. Will update the readme. It's already kind of a guarantee because if we record with another simulator, we'd have failing tests one existing tests when the whole suite is run.
…heme is not iPhone 8 iOS 14.5. Same for recording.
@msadoon msadoon marked this pull request as ready for review February 21, 2023 20:36
@msadoon msadoon added needs review and removed WIP labels Feb 21, 2023
@msadoon msadoon requested a review from scottkicks February 21, 2023 20:36
@msadoon
Copy link
Contributor Author

msadoon commented Feb 21, 2023

@scottkicks suggest opening this one locally on xcode, the number of files will break the page (at least on mine). It's a huge number of file changes, so lmk if you have any questions with the way tests work now.

Copy link
Contributor

@scottkicks scottkicks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passed all tests on my M1!
Nice work. Really appreciate the thourough explanation

@msadoon msadoon merged commit 29008cd into main Feb 22, 2023
@msadoon msadoon deleted the ntv-648/snapshot-tests-agnostic branch February 22, 2023 18:27
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

Successfully merging this pull request may close these issues.

3 participants