Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

An existential guide to testing React UIs

111 views

Published on

See https://github.com/bookstein/donation-tracking for code.

Published in: Software
  • Be the first to comment

An existential guide to testing React UIs

  1. 1. An Existential Guide to Testing React UIs
  2. 2. Who am I? @bookstein Artist: Alexandra Levasseur
  3. 3. Who am I? @bookstein Artist: Alexandra Levasseur
  4. 4. Where do I come from?
  5. 5. What is this all about? ● Unit tests ● Existentialism
  6. 6. Existential Testing Questions ● Should we write unit tests for the UI? ● What matters to test? ● What should we not test?
  7. 7. Should we write unit tests for the UI?
  8. 8. My donation-tracking app
  9. 9. Very quick demo
  10. 10. The UI is not alone
  11. 11. Should we write unit tests for the UI? YES
  12. 12. Let’s get existential about tests
  13. 13. What matters to test? What matters to not test?
  14. 14. Questions worth asking
  15. 15. 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
  16. 16. So why am I talking about this?
  17. 17. What matters to test?
  18. 18. The component to test friend.js
  19. 19. 1. Happy path 2. Behavior 3. Edge cases
  20. 20. 1. Happy path The DOM output you expect
  21. 21. 1. Happy path // Jest
  22. 22. 1. Happy path // how do snapshots work? capture markup
  23. 23. 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
  24. 24. it('renders without crashing', () => { const component = renderer.create(<Friend {...PROPS} />) // ... }) 1. Happy path // snapshot test friend.test.js
  25. 25. 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
  26. 26. 1. Happy path // snapshot test
  27. 27. 2. Behavior What should it do?
  28. 28. 2. Behavior // Enzyme Traverse/manipulateWrap component
  29. 29. 2. Behavior // User input friend.js
  30. 30. it('calls the `remove` callback on click', () => { const wrapper = shallow(<Friend {...PROPS}/>) // ... }) 2. Behavior // User input friend.test.js
  31. 31. 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
  32. 32. 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
  33. 33. 3. Edge cases Bad things happen
  34. 34. 3. Edge cases // Jest mocks MocksSnapshots
  35. 35. 3. Edge cases // Mock network error friendsList.js
  36. 36. export const pushToDatabase = (data) => { return firebase .database() .ref(‘friends’) .push() .set(data) } 3. Edge cases // Mock network error firebaseService.js
  37. 37. jest.mock(‘../firebaseService’, () => { return { pushToDatabase: jest.fn(), } }) 3. Edge cases // Mock network error friendsList.test.js
  38. 38. it('sets error state if Firebase returns err’, (done) => { firebaseService.pushToDatabase .mockImplementationOnce(() => // ... }) 3. Edge cases // Mock network error friendsList.test.js
  39. 39. 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
  40. 40. 1. Happy path 2. Behavior 3. Edge cases
  41. 41. 1. Happy path 2. Behavior 3. Edge cases
  42. 42. Don’t wait to write tests!
  43. 43. 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
  44. 44. Yay! Our UI is tested! Artist: Rafal Olbinski
  45. 45. What matters to not test?
  46. 46. Not in a unit test ● server logic Artist: Rene Magritte
  47. 47. Not in a unit test ● server logic ● 3rd party components
  48. 48. Not in a unit test ● server logic ● 3rd party components ● anything you can’t control
  49. 49. Edges
  50. 50. An example edge class FriendsList { componentDidMount() { firebase.database()...on('child_added', snapshot => {// update state}) } friendsList.js
  51. 51. An example edge firebase.database()friendsList.js
  52. 52. Let’s move the edge class FriendsList { componentDidMount() { firebase.database()...on('child_added', snapshot => {// update state}) } friendsList.js
  53. 53. Let’s move the edge import { listenForUpdates } from ‘../firebaseService’ class FriendsList { componentDidMount() { listenForUpdates(snapshot => // update state) } friendsList.js
  54. 54. So cutting-edge Firebase Service. js
  55. 55. So cutting-edge FAKE Firebase Service. js
  56. 56. Tests should influence component design
  57. 57. What to not test ● server logic ● 3rd party components ● things beyond the edges Artist: Rene Magritte
  58. 58. In summary
  59. 59. Should we write unit tests? YES
  60. 60. What matters to test? 1. Happy path 2. Behavior 3. Edge cases
  61. 61. What matters to not test?
  62. 62. Social Justice Fund is awesome
  63. 63. @bookstein /donation-tracking Be in touch ● React development & testing ● Existential questions ● Social Justice Fund
  64. 64. 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

×