Our journey through React unit testing
Vincent Voyer
@zeroload
github.com/vvo
algolia 💻
react newbie
Goal
expect(testing).toBe('easy')
The boring bullet point list
- Context
- Unit testing?
- Unit testing in React community
- Available solutions
- Shallow rendering
- Tooling
- Going further
- Questions
- This bullet intentionally left useless
Context
algolia/instantsearch.js (alpha)
instantsearch.js
A library of widgets to build high performance instant search experiences using Algolia
instantsearch.js
Based on React
instantsearch.js
Unit testing
basics
Test single units
Unit testing is not enough
—A Selenium user
Unit testing = fun
Testing units ≠ The application is working
You still need Selenium
AKA e2e, functional integration testing
It's not unit testing 🆚 functional testing
You need both
State of unit testing
in the React community
Why?
React unit testing
Available solutions
Real dom testing
import React from 'react';
import {findDOMNode} from 'react-dom';
import {renderIntoDocument} from 'react-addons-test-utils';
import jsdom from 'mocha-jsdom';
import expect from 'expect';
class Label extends React.Component {
render() {
return <span>Hello {this.props.name}</span>;
}
}
class Button extends React.Component {
render() {
return <div><Label name={this.props.name} /></div>;
}
}
describe('Real dom test', () => {
jsdom({useEach: true});
it('works', () => {
let component = renderIntoDocument(<Button name="John" />);
let DOMNode = findDOMNode(component);
expect(
DOMNode.querySelector('span')
.textContent
).toEqual('Hello John');
});
});
+ Not bound to any specific tool
+ You can use jQuery
- Not really unit testing
- Renders the full tree
import React from 'react';
import {
renderIntoDocument,
findRenderedDOMComponentWithTag
} from 'react-addons-test-utils';
import jsdom from 'mocha-jsdom';
import expect from 'expect';
class Label extends React.Component {
render() {
return <span>Hello {this.props.name}</span>;
}
}
class Button extends React.Component {
render() {
return <div><Label name={this.props.name} /></div>;
}
}
describe('Real Test Utilities', () => {
jsdom({useEach: true});
it('works', () => {
let component = renderIntoDocument(<Button name="John" />);
expect(
findRenderedDOMComponentWithTag(component, 'span')
.textContent
).toEqual('Hello John');
});
});
+ Test .props, refs, key
- Not really unit testing
- Renders the full tree
- Lots of assertions to do
import React from 'react';
import expect from 'expect';
import {createRenderer} from 'react-addons-test-utils';
class Label extends React.Component {
render() {
return <span>Hello {this.props.name}</span>;
}
}
class Button extends React.Component {
render() {
return <div><Label name={this.props.name} /></div>;
}
}
describe('Shallow rendering', () => {
it('works', () => {
let renderer = createRenderer();
renderer.render(<Button name="John" />);
let actualElement = renderer.getRenderOutput();
let expectedElement = <div><Label name="John" /></div>;
expect(actualElement).toEqual(expectedElement);
});
});
+ Unit!
+ render() one level deep
- Some limitations:
- no refs
- no TestUtils.simulate
Testing on* handlers
import React from 'react';
import expect from 'expect';
import {createRenderer} from 'react-addons-test-utils';
class Label extends React.Component {
render() {
return <span>Hello {this.props.name}</span>;
}
}
class Button extends React.Component {
render() {
return <div onClick={this.props.click}><Label name={this.props.name} /></div>;
}
}
describe('Shallow rendering on* handlers', () => {
it('works', () => {
let renderer = createRenderer();
let hasClicked = false;
let click = () => hasClicked = true;
renderer.render(<Button name="John" click={click} />);
renderer.getRenderOutput().props.onClick();
expect(hasClicked).toBe(true);
});
});
Tooling
__tests__
without
with
+ mocha
+ jsdom
+ expect(-jsx)
= npm run test:watch
algolia/react-unit-test-talk
What do we use and recommend
- Shallow rendering
- Regular test utilities and jsdom when needed
- mocha + jsdom + expect + expect-jsx + babel-plugin-rewire
Going further
- shallow rendering + refs?
- shallow rendering + simulate?
- testing state?
- Unit tests using real browsers
- E2E using real browsers
End
Questions?
Sources
- algolia/react-unit-test-talk
- What’s the prefered way to test React.js components?
- Unit testing React components without a DOM
- Testing React on Jsdom
- Test Utilities
- Approaches to testing React components - an overview
- Testing React Components
- Testing Components, The Easy Way
- bruderstein/unexpected-react-shallow
- algolia/expect-jsx
- algolia/react-element-to-jsx-string
- tape-jsx-equals
- jquense/teaspoon
Our journey through React component unit testing
By Vincent Voyer
Our journey through React component unit testing
- 57,464