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

Testing, tEstIng, TeStInG or how to test React apps with generated input data

Testing, tEstIng, TeStInG or how to test React apps with generated input data

Olena Sovyn

April 25, 2020
Tweet

More Decks by Olena Sovyn

Other Decks in Programming

Transcript

  1. Olena Sovyn • Senior software engineer/tech lead/ notorious problem solver

    and mighty fighter of tech debt • Londoner • ❤ traveling and reading. Cooking better than 90% of the restaurants that provide take away https://frontendgirl.com/
  2. Testing describe('total time is equal', () => { it('40 min

    when yoga is selected', () => { ... }); it('15 min when drink coffee is selected', () => { ... }); it('5 min when brush teeth is selected', () => { ... }); it('20 min when cook breakfast is selected', () => { ... }); });
  3. Morning Routine Planner All possible variations [[true, true, true, true],

    [true, true, true, false], [true, true, false, true], [true, true, false, false], [true, false, true, true], [true, false, true, false], [true, false, false, true], [true, false, false, false], [false, true, true, true], [false, true, true, false], [false, true, false, true], [false, true, false, false], [false, false, true, true], [false, false, true, false], [false, false, false, true], [false, false, false, false]];
  4. Cartesian Product describe('total time is equal', () => { cartesian(...new

    Array(4).fill([true, false])).forEach( ([isYoga, isCoffee, areTeeth, isBreakfast]) => { it('...', () => { ... }); }); });
  5. Best explanation found with Google help “Property based testing is

    a technique widely used in the Haskell community. The idea consists in automatically generating inputs for testing a function.”
  6. Flux Reducer const reducer = (state = initialState, action) =>

    { switch action.type { case 'ACTION_1': { ... return state1; } case 'ACTION_2': { ... return state2; } default: { return state; } } }
  7. Unit tests for flux reducer describe('reducer', () => { it('will

    change state to state 1 on action 1', () => { expect(reducer(initialState, { type: 'ACTION_1', payload: payload1 })).toEqual(state1); }); it('will change state to state 2 on action 2', () => { expect(reducer(initialState, { type: 'ACTION_2', payload: payload2 })).toEqual(state2); }); });
  8. Unit tests for flux reducer describe('reducer', () => { it('will

    change state to state 1 on action 1', () => { expect(reducer(initialState, { type: 'ACTION_1', payload: payload1 })).toEqual(state1); }); it('will change state to state 2 on action 2', () => { expect(reducer(initialState, { type: 'ACTION_2', payload: payload2 })).toEqual(state2); }); });
  9. Flux Reducer const reducer = (state = initialState, action) =>

    { switch action.type { case 'ACTION_1': { ... return state1; } case 'ACTION_2': { ... return state2; } default: { return state; } } }
  10. Flux Reducer with annotations type State = { isOnSale: boolean,

    size: 'XS' | 'S' | 'M' | 'L' | 'XL', price: number } const reducer = (state: State = initialState, action: Action) => { switch action.type { case 'ACTION_1': { ... return state1; } case 'ACTION_2': { ... return state2; } default: { return state; } } }
  11. Flux Reducer with annotations type State = { isOnSale: boolean,

    size: 'XS' | 'S' | 'M' | 'L' | 'XL', price: number } const reducer = (state: State = initialState, action: Action) => { switch action.type { case 'ACTION_1': { ... return state1; } case 'ACTION_2': { ... return state2; } default: { return state; } } }
  12. State type type State = { isOnSale: boolean, size: 'XS'

    | 'S' | 'M' | 'L' | 'XL', price: number }
  13. State type const possibleValues = { isOnSale: [true, false], size:

    ['XS', 'S', 'M', 'L', 'XL'], price: [number1, number2, number3] }
  14. Testing describe('reducer', () => { it('will change state to state

    1 on action 1', () => { cartesian([true, false], ['XS', 'S', 'M', 'L', 'XL'], [number1, number2, number3] ).map((isOnSale, size, price) => ({ isOnSale, size, price })).forEach(stateSample => { expect(reducer(stateSample, { type: 'ACTION_1', payload: payload1 })).toEqual(state1); }) }); });
  15. Unit tests template generation ? type State = { isOnSale:

    boolean, size: 'XS' | 'S' | 'M' | 'L' | 'XL', price: number } parsing
  16. Unit tests template generation ? describe('reducer', () => { it('will

    change state to state 1 on action 1', () => { cartesian([true, false], ['XS', 'S', 'M', 'L', 'XL'], [number1, number2, number3] ).map((isOnSale, size, price) => ({ isOnSale, size, price })).forEach(stateSample => { ... }); }); }); generation