This post is meant to be read in the context of its parent post "Lessons Learned on a React-Native Project". If you've stumbled on this particular page randomly, I'd recommend jumping over to that post and starting from there.

This was an area where I'd started off with Really Good Intentions™. I'd decided early on we were going to try snapshot testing for our components. We bootstrapped what we needed to, and set about adding some basic snapshots. At first things were... ok at best. Honestly, we never got in the habit of running the bloody snapshot tests (let alone integrating them into our CI pipeline, but that's a separate sort of stupid I'm saving for another post). So we noticed a few things happening:

  1. When we did remember to run the snapshots, they'd inevitably fail, because usually there'd be some sort of unrelated change which (correctly) produced different output.
  2. This cycle got us in the habit of when we made a change to a component, just running the update snapshot command. Meaning sometimes there would be valid failures that we missed, and didn't catch til run-time.
  3. Given the rate at which our components were changing, the snapshots usually ended up being substantially different than before, making it difficult to catch those subtle breaking changes.

Gross.

This also led to some other interesting tidbits of experience:

  1. The raw output of these test (especially the bigger components) wasn't really human-friendly.

    • Part of the catch of doing something like snapshot tests (a form of Approval Test), is that a human needs to manually review and check what's being changed to ensure it made sense. The more complex the output, the more likely a human is to glance at it and just say "yeah its fine".
    • There are prettiers specifically for React-Native snapshot tests that can help but they only go so far.
  2. Snapshot tests don't render the output of components you've referenced inside the component.

    • For example a <MyAwesomeButton/> component inside a <MyAwesomeView/> component will just render the output of <MyAwesomeView />, leaving just the element declaration of <MyAwesomeButton/> in the output. They're very much done in isolation of the rest of the UI components, which I'm kind of conflicted about. On the one hand, snapshot tests are really quick, because of the fact they're done in isolation of everything else. The trade-off for this is a lot of the time your bugs will come because of how these components interact with each other.
    • There is no easy answer here (to my knowledge at least), and the only thing I can think of is to use automated UI tests, which run on actual devices. Which then can be extremely slow, brittle, and come with a whole host of other problems I won't get into now. I really, really don't like automated UI tests.

I've still got a lot to learn in this area, and now I've got some time to breathe I'm going to spend some time looking into this. Once I've got something solid, I'll come back to this post and edit in the link here.

Next Section -> "If you've got native dev experience, you're at a huge advantage coming into React-Native"