ºÝºÝߣ

ºÝºÝߣShare a Scribd company logo
An Existential Guide to
Testing React UIs
Who am I?
@bookstein
Artist: Alexandra Levasseur
Who am I?
@bookstein
Artist: Alexandra Levasseur
Where do I come from?
What is this all about?
¡ñ Unit tests
¡ñ Existentialism
Existential Testing Questions
¡ñ Should we write unit tests
for the UI?
¡ñ What matters to test?
¡ñ What should we not test?
Should we write unit tests for the UI?
My donation-tracking app
Very quick demo
The UI is not alone
Should we write unit tests for the UI?
YES
Let¡¯s get existential about tests
What matters to
test?
What matters to
not test?
Questions worth asking
There¡¯s no recipe
¡°Ten or twenty years from now we'll likely
have a more universal theory of which tests to
write, which tests not to write, and how to tell
the difference. In the meantime,
experimentation seems in order.¡±
- Kent Beck, test coverage guy
Artist: Andrew Baines
So why am I talking about this?
What matters to test?
The component to test
friend.js
1. Happy path
2. Behavior
3. Edge cases
1. Happy path
The DOM output you
expect
1. Happy path // Jest
1. Happy path // how do snapshots work?
capture markup
1. Happy path // how do snapshots work?
exports[`renders without crashing 1`] = `
<div className=¡±Friend¡±>
<div>
<h1>myFriendName</h1>
<p className=¡±Friend__Tags¡±>
Tags:
...
friend.test.js.snap
it('renders without crashing', () => {
const component = renderer.create(<Friend {...PROPS}
/>)
// ...
})
1. Happy path // snapshot test
friend.test.js
it('renders without crashing', () => {
const component = renderer.create(<Friend {...PROPS}
/>)
let tree = component.toJSON()
expect(tree).toMatchSnapshot()
})
1. Happy path // snapshot test
friend.test.js
1. Happy path // snapshot test
2. Behavior
What should it do?
2. Behavior // Enzyme
Traverse/manipulateWrap component
2. Behavior // User input
friend.js
it('calls the `remove` callback on click', () => {
const wrapper = shallow(<Friend {...PROPS}/>)
// ...
})
2. Behavior // User input
friend.test.js
const removeFriend = jest.fn()
// ...pass in removeFriend with PROPS
it('calls the `remove` callback on click', () => {
const wrapper = shallow(<Friend {...PROPS}/>)
// ...
})
2. Behavior // User input
friend.test.js
const removeFriend = jest.fn()
it('calls the `remove` callback on click', () => {
const wrapper = shallow(<Friend {...PROPS}/>)
wrapper.find(`.Friend_X¡¯).simulate(¡®click¡¯)
expect(removeFriend).toHaveBeenCalled()
})
2. Behavior // User input
friend.test.js
3. Edge cases
Bad things happen
3. Edge cases // Jest mocks
MocksSnapshots
3. Edge cases // Mock network error
friendsList.js
export const pushToDatabase = (data) => {
return firebase
.database()
.ref(¡®friends¡¯)
.push()
.set(data)
}
3. Edge cases // Mock network error
firebaseService.js
jest.mock(¡®../firebaseService¡¯, () => {
return {
pushToDatabase: jest.fn(),
}
})
3. Edge cases // Mock network error
friendsList.test.js
it('sets error state if Firebase returns err¡¯, (done) => {
firebaseService.pushToDatabase
.mockImplementationOnce(() => // ...
})
3. Edge cases // Mock network error
friendsList.test.js
it('sets error state if Firebase returns err¡¯, (done) => {
firebaseService.pushToDatabase
.mockImplementationOnce(() => Promise.reject(¡®you got an
error!¡¯))
// ...
})
3. Edge cases // Mock network error
friendsList.test.js
1. Happy path 2. Behavior 3. Edge cases
1. Happy path 2. Behavior 3. Edge cases
Don¡¯t wait to write tests!
A brand new test
// HAPPY PATH:
// component renders as we expect
// BEHAVIOR:
// what behavior does the component itself have?
// EDGE CASES:
// what failure cases should our component handle?
friendsList.test.js
Yay! Our UI is tested!
Artist: Rafal Olbinski
What matters to not test?
Not in a unit test
¡ñ server logic
Artist: Rene Magritte
Not in a unit test
¡ñ server logic
¡ñ 3rd party components
Not in a unit test
¡ñ server logic
¡ñ 3rd party components
¡ñ anything you can¡¯t
control
Edges
An example edge
class FriendsList {
componentDidMount() {
firebase.database()...on('child_added',
snapshot => {// update state})
}
friendsList.js
An example edge
firebase.database()friendsList.js
Let¡¯s move the edge
class FriendsList {
componentDidMount() {
firebase.database()...on('child_added',
snapshot => {// update state})
}
friendsList.js
Let¡¯s move the edge
import { listenForUpdates } from ¡®../firebaseService¡¯
class FriendsList {
componentDidMount() {
listenForUpdates(snapshot => // update state)
}
friendsList.js
So cutting-edge
Firebase
Service.
js
So cutting-edge
FAKE
Firebase
Service.
js
Tests should
influence
component
design
What to not test
¡ñ server logic
¡ñ 3rd party components
¡ñ things beyond the
edges
Artist: Rene Magritte
In summary
Should we write unit tests?
YES
What matters to test?
1. Happy path 2. Behavior 3. Edge cases
What matters to not test?
Social Justice Fund is awesome
@bookstein
/donation-tracking
Be in touch
¡ñ React development & testing
¡ñ Existential questions
¡ñ Social Justice Fund
Artists featured: Alexandra Levasseur,
Andrew Baines, Edvard Munch, Rene
Magritte, Rafal Olbinski, Salvador Dali
¡ñ React development & testing
¡ñ Existential questions
¡ñ Social Justice Fund
Thanks!
@bookstein
/donation-tracking

More Related Content

An existential guide to testing React UIs