End to end testing in React Native

I’ve been a professional React Native developer for just over a year now, previously working on a number of different freelance and contracting engagements.

I’m a single developer maintaining two different apps for my day job, which are in constant development. It’s easy to ‘lose your place’ when digging up a project from a month ago and let bugs slip in.

There’s no excuse for it unfortunately – it’s not OK to let bugs slip through because you didn’t keep good enough track.

For the most part, I’ve used Jest snapshot testing to render React Native components out to JSON snapshots, and then compare the differences. This is cumbersome, and basically requires as much test maintenance as code writing.

Sure, it makes sure that a bug can’t slip in to the document model without it passing through your eyes, but it’s also easy to get some snapshot fatigue when 10 snapshots update after a decent chunk of coding. In retrospect, I don’t think jest snapshot testing is that great for a mobile app.

Also, jest component snapshots don’t see fatal errors that’ll crash your mobile application. If you’ve ever made the mistake of outputting an ascii character *outside* of a <text /> component, the whole app comes crashing down. Jest snapshots? No worries, everything passing!

E2E testing is a good, fast solution to this problem. E2E testing, when carefully designed, can work through every screen of your application (including with dynamic data) and make inputs like tapping, dragging, and typing text. You can assert the UI visible state of various components while the E2E tests run, but that’s not the good stuff.

The good part about E2E testing is screenshot diffing. In my case, we set up a test harness (a fake server for the app to connect to, basically). Run through a sequence to connect the app to the fake server. Then visit every screen of the app and cycle through settings on each screen to capture a screenshot of nearly every possible state of the app. 

It’s very slow compared to snapshot testing – the full pipeline takes about 2 minutes. BUT – we’re running an actual release build of the app, processing actual user input, and running it through the actual code. If there’s a hard crash on the user profile screen because I’ve accidentally put in some white space.. The E2E tests are going to find it.

I’ve modified the CI pipeline to stash these screenshots as job artifacts too, so at any stage we can dig back to old branches and commits and see what the app looked like in its entirety.

The screenshots are instantly visually parseable to a user. It’s not a big JSON diff of View > View > View > View > SVG > G > G > Text, which now has another <G> because of an svg version bump. It’s just a text label highlighted red because it’s moved.

Now that I’ve stabilised onto a stack for E2E testing in React Native, I’ll do a quick write up next time about the pipeline that is working for me.