Daniela Matos de Carvalho
Software Engineer @Dashlane, mother, photographer amateur, former @requirelx organiser, prev @YLDio, @zpx_interactive
Tests
We break down our app into smaller pieces
Components
Tests may PASS or FAIL
Tests may PASS or FAIL
...but we also want to know what failed
Write useful tests
1. Find the bug
2. Reproduce it
3. Find the cause
4. Solve it!
Unit Tests with Jest
describe("A suite", function() {
it("contains spec with an expectation", function() {
expect(true).toBe(true);
});
});
In real life we get an actual function
with Jest we get a mock of the function
BUT
Zoo.getAnimals()
Tests are mocked to
guarantee isolation
Zoo.getAnimals()
jest.dontMock('Zoo');
describe("Zoo.getAnimals()", function() {
it("should contain more than 0 animals", function() {
//...
});
});
var getAnimals = function(callback){
setTimeout(function(){
callback(['monkey', 'bird', 'lion']);
}, 0);
}
jest.dontMock('Zoo');
describe("Zoo.getAnimals()", function() {
it("should contain animals", function() {
var Zoo = require('Zoo');
let mockCallback = jest.genMockFunction();
Zoo.getAnimals();
jest.runAllTimers();
expect(mockCallback)
.toBeCalledWith(['monkey', 'bird', 'lion']);
});
});
Jest with React
React.addons.TestUtils
simple helpers for writing test cases
React.addons.TestUtils
Simulate
Simulate.{eventName}(DOMElement element, object eventData)
Examples
let node = React.findDOMNode(this.refs.input);
React.addons.TestUtils.Simulate.click(node);
React.addons.TestUtils.Simulate.change(node,
{target: {value: 'Hello, world'}});
React.addons.TestUtils.Simulate.keyDown(node, {key: "Enter"});
React.addons.TestUtils
renderIntoDocument
ReactComponent renderIntoDocument(ReactElement instance)
Example
let label = <Label>label testing</Label>;
React.addons.TestUtils.renderIntoDocument(label);
React.addons.TestUtils
class PartyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
txt: this.props.children
}
}
handleClick() {
this.setState({
txt: 'Lets have a party!'
});
}
render() {
return (<div>
<p ref="party" onClick={this.handleClick.bind(this)}>{this.state.txt}</p>
</div>);
}
};
Example - PartyComponent
React.addons.TestUtils
jest.dontMock('../PartyComponent.jsx');
import * as addons from 'react/addons';
import React from 'react';
var PartyComponent = require('../PartyComponent.jsx');
let TestUtils = React.addons.TestUtils;
describe("PartyComponent Test", function(){
let partyComponent, domNode;
beforeEach(function() {
let myComponent = <PartyComponent>No party at all</PartyComponent>;
partyComponent = TestUtils.renderIntoDocument(myComponent);
domNode = React.findDOMNode(partyComponent.refs.party);
});
it("Check Text Assignment", function () {
expect(domNode).toBeDefined();
expect(domNode.textContent).toBe("No party at all");
});
it("Click", function () {
TestUtils.Simulate.click(partyComponent.refs.party);
expect(domNode.textContent).toBe("Lets have a party!");
});
});
Example 1 - PartyComponent
React.addons.TestUtils
Other relevant utils...
let vodoo = TestUtils.renderIntoDocument(<Vodoo />);
expect(TestUtils.findRenderedDOMComponentWithClass(vodoo,
'fake').getDOMNode().innerHTML).toBe('Vodoo content!');
ReactComponent findRenderedDOMComponentWithClass(ReactComponent tree, string className)
let checkbox = TestUtils.renderIntoDocument(<Checkbox />);
let input = TestUtils.findRenderedDOMComponentWithTag(checkbox, 'input');
ReactComponent findRenderedDOMComponentWithTag(ReactComponent tree, string tagName)
import Button from "../Button";
let menu = TestUtils.renderIntoDocument(<Menu />);
let btn = TestUtils.findRenderedComponentWithType(menu, Button);
ReactComponent findRenderedComponentWithType(ReactComponent tree, function componentClass)
React.addons.TestUtils
Other relevant utils...
let vodoo = TestUtils.renderIntoDocument(<Vodoo />);
let array = TestUtils.scryRenderedDOMComponentsWithClass(vodoo, 'fake');
array scryRenderedDOMComponentsWithClass(ReactComponent tree, string className)
let checkbox = TestUtils.renderIntoDocument(<Checkbox />);
let array = TestUtils.scryRenderedDOMComponentsWithTag(checkbox, 'input');
array scryRenderedDOMComponentsWithTag(ReactComponent tree, string tagName)
import Button from "../Button";
let menu = TestUtils.renderIntoDocument(<Menu />);
let buttons = TestUtils.scryRenderedComponentsWithType(menu, Button);
array scryRenderedComponentsWithType(ReactComponent tree, function componentClass)
React.addons.TestUtils
Other relevant utils... conditionals!
boolean isElement(ReactElement element)
boolean isElementOfType(ReactElement element, function componentClass)
boolean isDOMComponent(ReactComponent instance)
boolean isCompositeComponent(ReactComponent instance)
boolean isCompositeComponentWithType(ReactComponent instance, function componentClass)
React.addons.TestUtils
Other relevant utils...
array findAllInRenderedTree(ReactComponent tree, function test)
import Button from "../Button";
let menu = TestUtils.renderIntoDocument(<Menu />);
let menuComponents = TestUtils.findAllInRenderedTree(menu, function (elem) {
return TestUtils.isCompositeComponentWithType(elem, Button);
});
expect(menuComponents.length).to.be(2);
React.addons.TestUtils
Other relevant utils...
object mockComponent(function componentClass, string? mockTagName)
replaced by Shallow Rendering
React.addons.TestUtils
Shallow Rendering
ReactShallowRenderer createRenderer()
shallowRenderer.render(ReactElement element)
ReactComponent shallowRenderer.getRenderOutput()
React.addons.TestUtils
Shallow Rendering
ReactShallowRenderer createRenderer()
shallowRenderer.render(ReactElement element)
ReactComponent shallowRenderer.getRenderOutput()
<div>
<span>React is awesome</span>
<OtherComponent hello="world" />
</div>
let result = renderer.getRenderOutput();
expect(result.type).toBe('div');
expect(result.props.children).toEqual([
<h1>React is awesome</h1>,
<OtherComponent hello="world" />
]);
shallowRenderer.getRenderOutput()
Tests
"Jest is slow"
"Jest is slow"
JSX is slow
JSX JS
JSX is slow
Possible solutions
- cache
- execute a JSX compiler on entire code base, save the results in a folder and run tests there
Let's try this!
{ /* Tests */ }
1. Exercices
#08-tests
By Daniela Matos de Carvalho
Software Engineer @Dashlane, mother, photographer amateur, former @requirelx organiser, prev @YLDio, @zpx_interactive