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, in Apiumhub we decided to write an article about iOS snapshot testing. 

 

iOS snapshot testing

 

View-based 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.

 

Snapshot Test. How does it 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 deliver a third capture showing the differences.

 

Configuration

The library was created by Facebook (FBSnapshotTestCase) and has now been renamed to iOSSnapshotTestCase and is maintained by uber.

The first step, as they explain 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 FB_REFERENCE_IMAGE_DIR.

spanshot testing

 

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.

 

Implementation

To see the implementation we will test a simple viewcontroller that will change the visual aspect depending on a state.

ios testing implementation

 

The view of the two states:

snapshot testing configuration

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 FBSnapshotVerifyView method.

viewController ios

First of all, we must execute the tests with the recordMode activated to save the reference images. For this we introduce inside the method of setUp () recordMode = true.

recordmode ios

When executing the tests with recordMode activated, Fail will exit. It is normal because you do not have another image yet with which to make the comparison.

recordmode ios test

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.

icon mobile app ios

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 the snapshot testing and to having the uncoupled views, we can instantiate and execute a certain ViewController in the simulator. It is very useful for accelerating the process of views creation and thus reducing development time.

In our didFinishLaunchingWithOptions we check if we are running tests and in that case, we assign the flat and empty UIViewController to the rootViewController.

doing ios testing mobile app

In our test class, we use an XCTWaiter with a high timeout and assign the controller to the rootViewController to execute.

rootViewController

Finally, in the test we call the debugViewController method.

In this way, we can execute the typical view that is within a long flow of screens of our app in a simple way.

If you are interested in receiving more tips for iOS snapshot testing or movile development in general, I highly recommend you to subscribe to our monthly newsletter here

 

If you found this article about iOS snapshot testing interesting, you might like…

 

iOS Objective-C app: sucessful case study

Mobile app development trends of the year

Banco Falabella wearable case study 

Mobile development projects 

Viper architecture advantages for iOS apps 

Why Kotlin ? 

Software architecture meetups

Pure MVP in Android 

Java vs Kotlin: comparisons and examples