Intro to Cavy
Cavy is an end-to-end testing framework that integrates with React Native using
refs. The test suite runs as an app, using a root
Tester component provided by Cavy. The root of your application is passed as a child to the Tester, and your test cases are passed as a prop.
Test cases are written as functions. They take in a
spec object that provides methods for declaring tests and interacting with the UI.
If you follow Cavy’s README, getting set up is quick. It should feel very comfortable to anyone who’s familiar with React development.
When first using Cavy, you’ll see that tests are reported in your debugger, but not reported to the screen. This is probably fine for local testing, but it’s not robust enough for running tests in CI. Thankfully, the team behind Cavy also created cavy-cli, which allows reporting.
In case you missed it in the Cavy docs (as I did), when using cavy-cli, you’ll want to set the Tester’s
sendReport prop to
This will enable test reporting in your terminal, as you’d expect from just about any other testing framework.
It’s very easy to get started with Cavy, but it isn’t without challenges. Here are a few of the issues I’ve run into, along with some suggestions on how to deal with them.
Running your app without Cavy
If you follow the docs, you can set up your testing. However, you probably won’t be able to launch your app without the tests running, since the test component is now the root of your app. There are a number of ways you can remedy this:
- Use environment variables to determine the root component of your app. This is pretty easy to set up, but because Cavy is still included, it’ll increase the size of your built app, which isn’t great.
- Create separate index files (perhaps index.test.js and index.app.js), and copy them to index.js as part of the build process.
- Use different index.js files for different build variants (testing vs. production). This is probably the cleanest solution.
Using refs means no FunctionComponents
I’m typically a big fan of using
FunctionComponents whenever possible; they’re a bit cleaner to look at than class-based
Components, and they emphasize that the component has no state, which often makes the component cleaner.
Cavy relies on
refs to identify components. But
FunctionComponents don’t have refs, so there’s a bit of a challenge there. Possible solutions include:
- Write all components as class-based
- Use a function to convert
Components. The cavy team suggests using recompose, but it doesn’t appear to be actively maintained anymore.
No support for TypeScript
If you’re using TypeScript, you’ll find that there are currently no type definitions. This means you’ll probably want to provide your own type definitions. Because Cavy’s very simple, this shouldn’t be too hard, but it does add overhead.
Cavy offers a nice solution for end-to-end testing of React Native apps. It’s quick to start and easy to use. It does come with some challenges, but they are not difficult to overcome.