Testing React and React Native
Unit testing
We use Mocha for testing React apps, Chai for assertions and Sinon.js for mocking.
All services and utilities should be tested. They are straight forward to test with mocha because they are functions most of the time.
It’s important to test Redux reducers and async actions creators. Simple action creators are usually tested when testing reducers.
Component testing
In order to make component testing easier, we use Enzyme. Enzyme is a JavaScript Testing utility for React that makes it easier to assert, manipulate, and traverse React Components. Enzyme provides shallow rendering functionality which allows rendering only the component under test. Dependent components are not rendered.
Automated acceptance testing
Acceptance tests that run on a browser, a simulator or a real device are slow and brittle. For these reasons, we tend to keep them to the minimum. We only test the main flows of the app.
Web
See Rails Feature tests or Node.js Feature tests depending on which environment is used for back-end.
Mobile
We use Calabash for React Native apps testing. Main points over other testing frameworks are that it’s actively maintained, works without issues on both Android and iOS.
Calabash setup
Calabash setup is not trivial, but there are lots of resources that help to make it work:
- Check x-platform-example for information about how to reuse cucumber features for Android and iOS runtimes.
- Check iOS and Android links about setting up Calabash.
- React Native does not allow easily adding new configurations for iOS. See this tutorial.
Writing Calabash tests
Calabash uses Cucumber framework for defining features:
Feature: TODO-app
Scenario: Add-TODO
Given I'm in TODO-app
And I click Add TODO
Then I fill title with "My first TODO"
And I fill text with "My first TODO description"
And I click Save
Then I should see "My first TODO"
Structure
Unit and component tests
To make it easier to find relevant tests and make imports shorter, we co-locate test files with the code being tested. We add *.spec.js
to the filename and place test files in spec
directory in the same folder as the code which is being tested.
app/
└── components
├── MessageInput.js
└── spec
└── MessageInput.spec.js
Automated acceptance tests
We place tests into features
directory in app root. features
directory also contains iOS and Android support files, common helpers and step definitions:
features/
├── android
│ ├── step_definitions
│ │ └── steps.rb
│ └── support
├── helpers
│ └── steps.rb
├── ios
│ ├── step_definitions
│ │ └── steps.rb
│ └── support
├── first.feature
├── second.feature
└── step_definitions
└── media_editor.rb