We're Building a Visual Regression Testing Library for React Native

January 13, 2022

It's called react-native-owl. It's open source and the first version with limited functionality is now available on NPM and GitHub at FormidableLabs/react-native-owl. The documentation can be found at https://formidable.com/open-source/react-native-owl/.

Introduction

So you've been building your app (whether that's a mobile app or web app), adding all the features over time, and looking to release it if you haven't already. But does it actually work as expected? How can we, as software engineers, confirm changes to our codebase haven't introduced any regressions? Writing tests that automatically test our code is a very important and ongoing process of software development. Depending on what you've been building you might choose different tools or even multiple ways of testing such as unit tests, end-to-end, integration tests, and, as you might have guessed it, visual regression is one of the many available options.

Visual demonstrator of a visual regression test

Visual example of a visual regression test

In case you are not familiar with visual regression testing, it is all about making sure the UI of your application hasn't unexpectedly changed. Imagine taking a screenshot of your application every time you make some changes to your codebase and then comparing it to the original one. Are there are any unexpected changes? Then your test suite will fail to prevent you from a "bad" merge.

Image of the React Native Owl

Today we are announcing react-native-owl, a visual regression testing library focused on React Native. This is a library that enables developers to introduce visual regression tests to their apps for iOS and Android (react-native-web is not currently supported while expo support is just around the corner). Being heavily inspired by Detox, an end-to-end testing and automation framework, we were able to come up with a similar API that will make setting up react-native-owl and running the tests locally and on your preferred CI service, seamless.

Image of different Formidable Mockups Preview

Features

Creating such a library can be quite challenging as it comes with lots of moving parts such as a CLI, the actual library, the HTML report, and of course the native client that enables interacting with the simulator.

CLI

We did borrow the convention of our two main commands from Detox, having a quite similar CLI where you can build your mobile app and then run the tests against that build. Next up, the react-native-owl configuration file comes in place where you can specify the path to your React Native project or even provide your own custom commands if required. Running the build command will basically run xcodebuild and the relevant gradle command for Android. Finally, the test command will do some further preparation and then use Jest to run your tests for files that end with the owl extension (ie. App.owl.tsx), generating an HTML report that will visualize any differences if any of your test cases fail.

yarn owl build --platform ios yarn owl test --platform ios

The core library

The library comes with an action (takeScreenshot) that enables taking a screenshot from the simulator while the app is running and stores it in the .owl/ directory along with the rest of the generated assets like baseline, latest and diff images, and the test run report.

As we are using Jest for the test runs, we also provide a custom matcher (.toMatchBaseline()) that will compare the screenshot with its baseline using Pixelmatch — a pixel-level image comparison library.

describe('App.tsx', () => { it('takes a screenshot of the home view', async () => { const screen = await takeScreenshot('homeview'); expect(screen).toMatchBaseline(); }); });

The Report

This would be the HTML report that will be generated if you have any failing tests and will show you a comparison between the baseline, the latest, and the diff image of these test cases. If you are running react-native-owl on your preferred CI, we suggest storing the output of the tests (.owl/) as an artifact so that you can download it if your tests fail. Then by viewing the generated report, you will be able to find the reason for the failure.

Image of different Formidable Mockups Preview

What's Next?

Building our library has been an exciting journey and we are looking forward to what's next as today we've only released a big portion of the ongoing work. Next, we will focus on building the native client, which will allow developers to interact with simulators, pressing on buttons, scrolling, typing, and more. We've seen the great work that has been done by Detox and we would love to build on it, utilizing it for all the aforementioned interactions with devices.

Related Posts

Why Choose React Native?

May 24, 2021
React Native unifies development teams by leveraging the same set of technologies on multiple platforms. Here are some of the key reasons why you might want to consider React Native for your next development project.

Ranked Choice Voting: The Mobile Challenge

November 19, 2024
While working on VoteHub, a mobile absentee ballot solution for U.S. elections, I was tasked with designing and prototyping an interface for a relatively new election contest type, rapidly gaining attention and adoption, called Ranked Choice Voting (RCV).

New Standards For A New Paradigm: Resolving Conflicts in Accessible Practices

July 23, 2024
Voting has a robust set of best practices that do not all translate cleanly to a mobile interface. Our team resolved these conflicts with care and worked these best practices into the foundations of the VoteHub mobile voting app by way of a custom component library.