iOS Snapshot Testing
Learn how iOS snapshot testing works and how to use it for view-based testing, to make sure users of your app are seeing what you want them to see.
Join the DZone community and get the full member experience.Join For Free
Writing user interface tests is always a bit complicated, and many developers end up leaving views without testing or dedicating a lot of time and effort to the development of tests. Apple has its own native support for UI testing but does not support view-based testing. This lack of functionality makes many people skip the part of writing tests. Therefore, we at Apiumhub decided to write an article about iOS snapshot testing.
View-based testing means verifying that what the user sees is exactly what we (as developers) want them to see. Thanks to this testing, we can guarantee that in different states or versions, our views are shown as expected.
How Does a Snapshot Test Work?
The snapshot test takes a capture of a UIView or CALayer and uses the
renderInContext method, which makes a capture of the view and compares it with the reference image stored in our repository. The test fails if both images do not match, and delivers a third capture showing the differences.
The library was created by Facebook (FBSnapshotTestCase) and has now been renamed iOSSnapshotTestCase and is maintained by Uber.
The first step, as explained on their GitHub page, is to add the library to our Podfile.
Then, we edit the scheme of our target to add the directory where our reference captures will be saved. To do this, we add an environment variable with the key
Optionally, we can also add the key
IMAGE_DIFF_DIR to indicate the directory where the differential captures that will be generated will be saved in case our tests fail.
To see the implementation, we will test a simple viewcontroller that will change the visual aspect depending on a state.
The view of the two states:
We configure our test class by making it a subclass of FBSnapshotTestCase instead of XCTestCase.
We define our tests by instantiating the ViewController, assigning the status, and calling the
First of all, we must execute the tests with the recordMode activated to save the reference images. For this, we introduce inside the method
setUp () recordMode = true.
When executing the tests with recordMode activated, Fail will exit. This is normal because you do not et have another image with which to make the comparison.
Then, we comment or eliminate the line of recordMode to launch the tests again and see what happens.
From now on, if the visual aspect of the view changes in the wrong way, our tests will notify us about this issue.
For example, if we inadvertently change the dimension of the icons, the test will generate a differential image with the changes.
I have increased the size of the icon for the 20px test, and the change can be seen in the image.
Run Views in an Isolated Way
Thanks to snapshot testing and the uncoupled views, we can instantiate and execute a certain ViewController in the simulator. This is very useful for accelerating the process of views creation and thus reducing development time.
didFinishLaunchingWithOptions, we check if we are running tests, and in that case, we assign the flat and empty
UIViewController to the
In our test class, we use an
XCTWaiter with a high timeout and assign the controller to the
rootViewController to execute.
Finally, in the test, we call the
In this way, we can execute the typical view within a long flow of screens of our app in a simple way.
Published at DZone with permission of Bruno Basas. See the original article here.
Opinions expressed by DZone contributors are their own.