Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Testing React.js Applications

Max Stoiber
January 15, 2016

Testing React.js Applications

Max Stoiber

January 15, 2016
Tweet

More Decks by Max Stoiber

Other Decks in Technology

Transcript

  1. Testing React.js Applications
    Max Stoiber - @mxstbr

    View full-size slide

  2. Max Stoiber
    Max Stoiber – @mxstbr – mxstbr.com
    Freelance Front-End Developer
    @mxstbr

    View full-size slide

  3. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  4. TYPES
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  5. SYSTEM TESTING
    Max Stoiber – @mxstbr – mxstbr.com
    STRESS TESTING
    PERFORMANCE TESTING
    USABILITY TESTING
    UNIT TESTING

    View full-size slide

  6. Max Stoiber – @mxstbr – mxstbr.com
    UNIT TESTING
    UNIT TESTING
    SYSTEM TESTING
    STRESS TESTING
    PERFORMANCE TESTING
    USABILITY TESTING

    View full-size slide

  7. Max Stoiber – @mxstbr – mxstbr.com
    UNIT

    View full-size slide

  8. Max Stoiber – @mxstbr – mxstbr.com
    FUNCTION
    COMPONENT
    ACTIONS
    STORES

    View full-size slide

  9. WHY?
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  10. CATCH BUGS BEFORE THEY HAPPEN
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  11. EXECUTABLE DOCUMENTATION
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  12. SAVE TIME
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  13. WRITE BETTER CODE
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  14. HOW?
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  15. MOCHA
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  16. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  17. MJACKSON/EXPECT
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  18. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  19. Max Stoiber – @mxstbr – mxstbr.com
    // add.js
    export function add(x, y) {
    return x + y;
    }

    View full-size slide

  20. Max Stoiber – @mxstbr – mxstbr.com
    // add.test.js
    import { add } from './add.js';
    import expect from 'expect';
    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));
    });
    });

    View full-size slide

  21. Max Stoiber – @mxstbr – mxstbr.com
    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));
    });
    });

    View full-size slide

  22. Max Stoiber – @mxstbr – mxstbr.com
    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));
    });
    });

    View full-size slide

  23. Max Stoiber – @mxstbr – mxstbr.com
    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));
    });
    });

    View full-size slide

  24. Max Stoiber – @mxstbr – mxstbr.com
    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));
    });
    });

    View full-size slide

  25. Max Stoiber – @mxstbr – mxstbr.com
    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));
    });
    });

    View full-size slide

  26. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  27. Max Stoiber – @mxstbr – mxstbr.com
    // add.js
    export function add(x, y) {
    return x + y;
    }

    View full-size slide

  28. Max Stoiber – @mxstbr – mxstbr.com
    // add.js
    export function add(x, y) {
    return x + y; x * y;
    }

    View full-size slide

  29. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  30. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  31. REDUX
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  32. 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
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  33. ACTIONS
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  34. Max Stoiber – @mxstbr – mxstbr.com
    // NavBar.actions.js
    import { TOGGLE_NAV } from './NavBar.constants.js';
    export function toggleNav() {
    return { type: TOGGLE_NAV };
    }

    View full-size slide

  35. Max Stoiber – @mxstbr – mxstbr.com
    // NavBar.actions.test.js
    import { toggleNav } from './NavBar.actions';
    import { TOGGLE_NAV } from './NavBar.constants';
    import expect from ‘expect';
    describe('NavBar actions', () => {
    });

    View full-size slide

  36. Max Stoiber – @mxstbr – mxstbr.com
    describe('NavBar actions', () => {
    describe('toggleNav', () => {
    it('should return the correct constant', () => {
    expect(toggleNav()).toEqual({
    type: TOGGLE_NAV
    });
    });
    });
    });

    View full-size slide

  37. Max Stoiber – @mxstbr – mxstbr.com
    describe('NavBar actions', () => {
    describe('toggleNav', () => {
    it('should return the correct constant', () => {
    expect(toggleNav()).toEqual({
    type: TOGGLE_NAV
    });
    });
    });
    });

    View full-size slide

  38. Max Stoiber – @mxstbr – mxstbr.com
    describe('NavBar actions', () => {
    describe('toggleNav', () => {
    it('should return the correct constant', () => {
    expect(toggleNav()).toEqual({
    type: TOGGLE_NAV
    });
    });
    });
    });

    View full-size slide

  39. Max Stoiber – @mxstbr – mxstbr.com
    describe('NavBar actions', () => {
    describe('toggleNav', () => {
    it('should return the correct constant', () => {
    expect(toggleNav()).toEqual({
    type: TOGGLE_NAV
    });
    });
    });
    });

    View full-size slide

  40. Max Stoiber – @mxstbr – mxstbr.com
    describe('NavBar actions', () => {
    describe('toggleNav', () => {
    it('should return the correct constant', () => {
    expect(toggleNav()).toEqual({
    type: TOGGLE_NAV
    });
    });
    });
    });

    View full-size slide

  41. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  42. REDUCER
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  43. Max Stoiber – @mxstbr – mxstbr.com
    // NavBar.reducer.js
    import { TOGGLE_NAV } from ‘./NavBar.constants.js';
    const initialState = {
    open: false
    };
    export default function NavBarReducer(state = initialState, action) {
    switch (action.type) {
    case TOGGLE_NAV:
    return Object.assign({}, state, {
    open: !state.open
    });
    default:
    return state;
    }
    }

    View full-size slide

  44. Max Stoiber – @mxstbr – mxstbr.com
    // NavBar.reducer.test.js
    import expect from 'expect';
    import NavBarReducer from './NavBar.reducer';
    import { TOGGLE_NAV } from './NavBar.constants';
    import { toggleNav } from './NavBar.actions';
    describe('NavBarReducer', () => {
    it('returns the initial state', () => {});
    it('handles the toggleNav action', () => {});
    });

    View full-size slide

  45. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  46. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  47. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  48. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  49. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  50. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  51. Max Stoiber – @mxstbr – mxstbr.com
    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
    });
    });
    });

    View full-size slide

  52. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  53. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  54. AIRBNB/ENZYME
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  55. AIRBNB/ENZYME
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  56. Max Stoiber – @mxstbr – mxstbr.com
    // Button.react.js
    import React from 'react';
    class Button extends React.Component {
    render() {
    return (
    onClick={this.props.onClick}>
    { this.props.children }

    );
    }
    }
    export default Button;

    View full-size slide

  57. Max Stoiber – @mxstbr – mxstbr.com
    Click me!

    View full-size slide

  58. Max Stoiber – @mxstbr – mxstbr.com
    Click me!

    View full-size slide

  59. Max Stoiber – @mxstbr – mxstbr.com
    // Button.test.js
    import Button from './Button.react';
    import expect from 'expect';
    import { shallow } from 'enzyme';
    import React from 'react';
    describe('', () => {
    it('renders a ', () => {});
    it('renders text', () => {});
    it('handles clicks', () => {});
    });

    View full-size slide

  60. Max Stoiber – @mxstbr – mxstbr.com
    // Button.test.js
    import Button from './Button.react';
    import expect from 'expect';
    import { shallow } from 'enzyme';
    import React from 'react';
    describe('', () => {
    it('renders a ', () => {});
    it('renders text', () => {});
    it('handles clicks', () => {});
    });

    View full-size slide

  61. SHALLOW RENDERING
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  62. ONE LEVEL DEEP
    Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  63. Max Stoiber – @mxstbr – mxstbr.com

    Title


    View full-size slide

  64. Max Stoiber – @mxstbr – mxstbr.com

    Title


    NORMAL RENDERING

    View full-size slide

  65. Max Stoiber – @mxstbr – mxstbr.com

    Title


    SHALLOW RENDERING

    View full-size slide

  66. Max Stoiber – @mxstbr – mxstbr.com
    // Button.test.js
    import Button from './Button.react';
    import expect from 'expect';
    import { shallow } from 'enzyme';
    import React from 'react';
    describe('', () => {
    it('renders a ', () => {});
    it('renders text', () => {});
    it('handles clicks', () => {});
    });

    View full-size slide

  67. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders a ', () => {
    const renderedComponent = shallow(

    );
    expect(
    renderedComponent.find("button").node
    ).toExist();
    });
    });

    View full-size slide

  68. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders a ', () => {
    const renderedComponent = shallow(

    );
    expect(
    renderedComponent.find("button").node
    ).toExist();
    });
    });

    View full-size slide

  69. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders a ', () => {
    const renderedComponent = shallow(

    );
    expect(
    renderedComponent.find("button").node
    ).toExist();
    });
    });

    View full-size slide

  70. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders a ', () => {
    const renderedComponent = shallow(

    );
    expect(
    renderedComponent.find("button").node
    ).toExist();
    });
    });

    View full-size slide

  71. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders text', () => {
    const text = "Click me!";
    const renderedComponent = shallow(
    { text }
    );
    expect(
    renderedComponent.contains(text)
    ).toEqual(true);
    });
    });

    View full-size slide

  72. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders text', () => {
    const text = "Click me!";
    const renderedComponent = shallow(
    { text }
    );
    expect(
    renderedComponent.contains(text)
    ).toEqual(true);
    });
    });

    View full-size slide

  73. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders text', () => {
    const text = "Click me!";
    const renderedComponent = shallow(
    { text }
    );
    expect(
    renderedComponent.contains(text)
    ).toEqual(true);
    });
    });

    View full-size slide

  74. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders text', () => {
    const text = "Click me!";
    const renderedComponent = shallow(
    { text }
    );
    expect(
    renderedComponent.contains(text)
    ).toEqual(true);
    });
    });

    View full-size slide

  75. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('renders text', () => {
    const text = "Click me!";
    const renderedComponent = shallow(
    { text }
    );
    expect(
    renderedComponent.contains(text)
    ).toEqual(true);
    });
    });

    View full-size slide

  76. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('handles clicks', () => {
    const onClickSpy = expect.createSpy();
    const renderedComponent = shallow(

    );
    renderedComponent.find('button').simulate('click');
    expect(onClickSpy).toHaveBeenCalled();
    });
    });

    View full-size slide

  77. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('handles clicks', () => {
    const onClickSpy = expect.createSpy();
    const renderedComponent = shallow(

    );
    renderedComponent.find('button').simulate('click');
    expect(onClickSpy).toHaveBeenCalled();
    });
    });

    View full-size slide

  78. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('handles clicks', () => {
    const onClickSpy = expect.createSpy();
    const renderedComponent = shallow(

    );
    renderedComponent.find('button').simulate('click');
    expect(onClickSpy).toHaveBeenCalled();
    });
    });

    View full-size slide

  79. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('handles clicks', () => {
    const onClickSpy = expect.createSpy();
    const renderedComponent = shallow(

    );
    renderedComponent.find('button').simulate('click');
    expect(onClickSpy).toHaveBeenCalled();
    });
    });

    View full-size slide

  80. Max Stoiber – @mxstbr – mxstbr.com
    describe('', () => {
    it('handles clicks', () => {
    const onClickSpy = expect.createSpy();
    const renderedComponent = shallow(

    );
    renderedComponent.find('button').simulate('click');
    expect(onClickSpy).toHaveBeenCalled();
    });
    });

    View full-size slide

  81. Max Stoiber – @mxstbr – mxstbr.com

    View full-size slide

  82. @mxstbr
    Max Stoiber – @mxstbr – mxstbr.com
    HTTPS://GITHUB.COM/MXSTBR/REACT-TESTING

    View full-size slide