Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Testing React Applications
Max Stoiber
March 01, 2017
Technology
3
170
Testing React Applications
Max Stoiber
March 01, 2017
Tweet
Share
More Decks by Max Stoiber
See All by Max Stoiber
mxstbr
3
250
mxstbr
1
84
mxstbr
2
230
mxstbr
2
310
mxstbr
0
300
mxstbr
3
670
mxstbr
1
290
mxstbr
4
350
Other Decks in Technology
See All in Technology
kotatsu360
2
830
xecus
0
170
adhorn
0
340
pohjus
1
740
hanacchi
0
140
hikiaki
0
180
andoshin11
0
140
conciergeu
0
120
binarymist
0
1.3k
opdavies
0
1.7k
mii3king
0
400
myajiri
0
300
Featured
See All Featured
matthewcrist
73
7.5k
philnash
9
580
smashingmag
283
47k
davidbonilla
70
3.6k
frogandcode
128
20k
mojombo
358
62k
lara
172
9.6k
reverentgeek
27
2k
dougneiner
119
7.9k
shlominoach
176
7.5k
edds
56
9.4k
paulrobertlloyd
71
3.6k
Transcript
Let’s talk about testing
Which types of testing are there?
Unit Testing
Unit
Function Components Actions Reducers
Why should you test?
Catch some bugs before they happen
None
Executable Documentation
Write Better Code
// add.js export function add(x, y) { return x +
y; }
// add.test.js import { add } from './add.js'; describe('add()', ()
=> { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
// add.test.js import { add } from './add.js'; describe('add()', ()
=> { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
// add.test.js import { add } from './add.js'; describe('add()', ()
=> { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
// add.test.js import { add } from './add.js'; describe('add()', ()
=> { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
// add.test.js import { add } from './add.js'; describe('add()', ()
=> { it('adds two numbers', () => { expect(add(2, 3)).toEqual(5); }); it('doesnt add the third number', () => { expect(add(2, 3, 5)).toEqual(add(2, 3)); }); });
Max Stoiber – @mxstbr – mxstbr.com
// add.js export function add(x, y) { return x +
y; }
// add.js export function add(x, y) { return x +
y; x * y; }
None
Max Stoiber – @mxstbr – mxstbr.com
None
Redux
NavBar !"" NavBar.react.js # React component # !"" NavBar.actions.js #
Actions !"" NavBar.constants.js # Constants !"" NavBar.reducer.js # Reducer # !"" NavBar.actions.test.js # Actions tests $"" NavBar.reducer.test.js # Reducer tests
Actions
// NavBar.actions.js export function toggleNav() { return { type: "TOGGLE_NAV"
}; }
// NavBar.actions.test.js import { toggleNav } from './NavBar.actions'; describe('NavBar actions',
() => { });
describe('NavBar actions', () => { describe('toggleNav', () => { it('should
return the correct constant', () => { expect(toggleNav()).toEqual({ type: "TOGGLE_NAV" }); }); }); });
describe('NavBar actions', () => { describe('toggleNav', () => { it('should
return the correct constant', () => { expect(toggleNav()).toEqual({ type: "TOGGLE_NAV" }); }); }); }); export function toggleNav() { return { type: "TOGGLE_NAV" }; }
describe('NavBar actions', () => { describe('toggleNav', () => { it('should
return the correct constant', () => { expect(toggleNav()).toEqual({ type: "TOGGLE_NAV" }); }); }); });
None
Reducers
// NavBar.reducer.js const initialState = { open: false }; export
default function NavBarReducer(state = initialState, action) { switch (action.type) { case "TOGGLE_NAV": return { …state, open: !state.open }; default: return state; } }
// NavBar.reducer.js const initialState = { open: false }; export
default function NavBarReducer(state, action) { switch (action.type) { case "TOGGLE_NAV": return Object.assign({}, state, { open: !state.open }); default: return state; } }
describe('NavBarReducer', () => { it('returns the initial state', () =>
{ expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
describe('NavBarReducer', () => { it('returns the initial state', () =>
{ expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
describe('NavBarReducer', () => { it('returns the initial state', () =>
{ expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
describe('NavBarReducer', () => { it('returns the initial state', () =>
{ expect(NavBarReducer(undefined, {})).toEqual({ open: false }); }); it('handles the toggleNav action', () => { expect(NavBarReducer(undefined, toggleNav())).toEqual({ open: true }); }); });
None
Why Jest?
1. Performance 2. Snapshot Testing 3. Constant improvements
Components
const Button = (props) => ( <button className="btn" onClick={props.onClick} >
{props.children} </button> );
Jest Snapshot Testing
// Button.test.js import React from 'react'; import renderer from 'react-test-renderer';
import Button from './Button.react'; describe('<Button />', () => { it('should render a button with a classname', () => {}); it('should attach an onclick handler passed in', () => {}); it('should render its children', () => {}); });
// Button.test.js import React from 'react'; import renderer from 'react-test-renderer';
import Button from './Button.react'; describe('<Button />', () => { it('should render a button with a classname', () => {}); it('should attach an onclick handler passed in', () => {}); it('should render its children', () => {}); }); const Button = (props) => ( <button className="btn" onClick={props.onClick} > {props.children} </button> );
// Button.test.js describe('<Button />', () => { it('should render a
button with a classname', () => { const tree = renderer.create( <Button></Button> ).toJSON(); expect(tree).toMatchSnapshot(); }); it('should attach an onclick handler passed in', () => {}); it('should render its children', () => {}); });
// Button.test.js.snap exports[`<Button /> should render a button with a
classname 1`] = ` <button className="btn" onClick={undefined} /> `;
// Button.test.js describe('<Button />', () => { it('should render a
button with a classname', () => {}); it('should attach an onclick handler passed in', () => { const tree = renderer.create( <Button onClick={() => {}}></Button> ).toJSON(); expect(tree).toMatchSnapshot(); }); it('should render its children', () => {}); });
// Button.test.js describe('<Button />', () => { it('should render a
button with a classname', () => {}); it('should attach an onclick handler passed in', () => { const tree = renderer.create( <Button onClick={() => {}}></Button> ).toJSON(); expect(tree).toMatchSnapshot(); }); it('should render its children', () => {}); });
exports[`<Button /> should attach an onclick handler passed in 1`]
= ` <button className="btn" onClick={[Function]} /> `;
exports[`<Button /> should attach an onclick handler passed in 1`]
= ` <button className="btn" onClick={[Function]} /> `;
// Button.test.js describe('<Button />', () => { it('should render a
button with a classname', () => {}); it('should attach an onclick handler passed in', () => {}); it('should render its children', () => { const tree = renderer.create( <Button>Some text</Button> ).toJSON(); expect(tree).toMatchSnapshot(); }); });
// Button.test.js describe('<Button />', () => { it('should render a
button with a classname', () => {}); it('should attach an onclick handler passed in', () => {}); it('should render its children', () => { const tree = renderer.create( <Button>Some text</Button> ).toJSON(); expect(tree).toMatchSnapshot(); }); });
exports[`<Button /> should render its children 1`] = ` <button
className="btn" onClick={undefined}> Some text </button> `;
exports[`<Button /> should render its children 1`] = ` <button
className="btn" onClick={undefined}> Some text </button> `;
Quickest Testing Ever
Coverage
None
None
Let’s do some testing! git checkout 6-testing npm install npm
run test