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

Jest asserts beyond equals

Marabesi
August 24, 2021

Jest asserts beyond equals

Testing with jest is an activity that developers do to keep the application maintainable and time proof. Therefore, learning a testing framework can be a consuming task, often it has many features to master. The assertion API usually is one of the most important ones, as this is the one that the developer uses the most during the TDD flow.

The gist of the assertion API is to compare values, as such the equals matcher is the most used. Being one of the most used can also point to a lack of knowledge in the different assertions that the testing framework offers.

This presentation aims to cover different assertions, to avoid using always toEqual and make the test case more expressive. For each example, I try to first depict how it would be with toEqual, then I show another way using a different assertion.

Marabesi

August 24, 2021
Tweet

More Decks by Marabesi

Other Decks in Programming

Transcript

  1. JEST JEST ASSERTS ASSERTS BEYOND BEYOND EQUALS EQUALS 1

  2. ABOUT ME ABOUT ME Software craftsperson at Software craftsperson at

    Codurance Codurance Oriented to software testing ( Oriented to software testing ( ) ) Testable Testable @MatheusMarabesi 🐦 @MatheusMarabesi 🐦 marabesi.com 💻 marabesi.com 💻
  3. 2 . 1

  4. AGENDA 📖 AGENDA 📖 1. Background 2. Assertion smells 3.

    Assertion API 4. Exploring assertions 5. Wrapping up 3
  5. This talk is based on my own journey . .

    . 4 . 1
  6. Testing (TDD) 4 . 2

  7. Framework (Jest) 4 . 3

  8. toEqual toEqual, usually is the first assertion used ❗ ,

    usually is the first assertion used ❗ 5 . 1
  9. And, it's something like . . . 🤔 5 .

    2
  10. test('assert some value', () => { const myVar = 'some

    val' expect(myVar).toEqual('some val') ✅ }) 5 . 3
  11. test('light is on', () => { const off = false

    expect(off === false).toEqual(true) ✅ }) 5 . 4
  12. test('it has two users', () => { const users =

    [ { name: 'jhon'}, { name: 'maria' } ] expect(users.length).toEqual(2) ✅ }) 5 . 5
  13. ASSERTION SMELLS ASSERTION SMELLS 6 . 1

  14. WHEN TEST DRIVEN DEVELOPMENT GOES WRONG WHEN TEST DRIVEN DEVELOPMENT

    GOES WRONG By Continuous Delivery By Continuous Delivery When Test Driven Development Goes Wrong When Test Driven Development Goes Wrong 6 . 2
  15. expect(myVar).equals('some val') ✅ const myVar = 'some val' 1 2

    3 4 5 const off = false 6 7 expect(off === false).equals(true) ✅ 8 9 10 const users = [ 11 { name: 'jhon'}, 12 { name: 'maria' } 13 ] 14 15 expect(users.length).equals(2) ✅ 16 expect(off === false).equals(true) ✅ const myVar = 'some val' 1 2 expect(myVar).equals('some val') ✅ 3 4 5 const off = false 6 7 8 9 10 const users = [ 11 { name: 'jhon'}, 12 { name: 'maria' } 13 ] 14 15 expect(users.length).equals(2) ✅ 16 expect(users.length).equals(2) ✅ const myVar = 'some val' 1 2 expect(myVar).equals('some val') ✅ 3 4 5 const off = false 6 7 expect(off === false).equals(true) ✅ 8 9 10 const users = [ 11 { name: 'jhon'}, 12 { name: 'maria' } 13 ] 14 15 16 6 . 3
  16. IS THERE A MORE EXPRESSIVE IS THERE A MORE EXPRESSIVE

    WAY? 🤔 WAY? 🤔 7
  17. MEETING THE ASSERTION API MEETING THE ASSERTION API 5️⃣ 5️⃣

    8 . 1
  18. Primitive assertions 🧱 8 . 2

  19. Modifiers 🪣 8 . 3

  20. Callbacks 📱 8 . 4

  21. Async 🏹 8 . 5

  22. Timers ⏰ 8 . 6

  23. Primitive assertions 🧱 Primitive assertions 🧱 Modifiers 🪣 Modifiers 🪣

    Callbacks 📱 Callbacks 📱 Async 🏹 Async 🏹 Timers ⏰ Timers ⏰ 8 . 7
  24. PRIMITIVE ASSERTIONS 🧱 PRIMITIVE ASSERTIONS 🧱 test('it returns a number',

    () => { const isNumber = number => number expect(typeof isNumber(2)).toEqual('number') }) test('it returns a number', () => { const isNumber = number => number expect(isNumber(2)).toEqual( expect.any(Number) ) }) 9 . 1
  25. test('expected is greater than the desired', () => { const

    expected = 10 const actual = 3 expect(expected > actual).toEqual(true) }) test('expected is greater than the desired', () => { const expected = 10 const actual = 3 expect(actual).toBeGreaterThan(expected) }) 9 . 2
  26. ARRAYS 🧱 ARRAYS 🧱 test('list three fruits', () => {

    const expectedFruits = ['banana', 'mango', 'watermelon'] expect(expectedFruits[0]).toEqual('banana') expect(expectedFruits[1]).toEqual('mango') expect(expectedFruits[2]).toEqual('watermalo') }) test('list three fruits', () => { const expectedFruits = ['banana', 'mango', 'watermelon'] const actualFruits = () => ['banana', 'mango', 'watermelon'] expect(expectedFruits).toEqual( expect.arrayContaining(actualFruits) ) }) 10 . 1
  27. test('list with three numbers', () => { const myList =

    [1, 2, 3] expect(myList.length).toEqual(3) }) test('list with three numbers', () => { const myList = [1, 2, 3] expect(myList).toHaveLength(3) }) 10 . 2
  28. MODIFIERS 🪣 MODIFIERS 🪣 11 . 1

  29. test('light is on', () => { const isOff = false

    expect(!isOff).toBe(true) }) test('light is on', () => { const isOff = false expect(isOff).not.toBe(true) }) 11 . 2
  30. CALLBACKS 📱 CALLBACKS 📱 12 . 1

  31. test('callback has been invoked', done => { callAsyncFunc(() => {

    expect(true).toEqual(true) done() }) }) 12 . 2
  32. 12 . 3

  33. test('callback has been invoked', () => { const result =

    jest.fn() callAsyncFunc(result) expect(result).toHaveBeenCalled() }) 12 . 4
  34. ASYNC 🏹 ASYNC 🏹 13 . 1

  35. test('my async test', done => { callAsyncFunc(). then((value) => {

    expect(value).toBe(true) done() }) }) test('my async test', async () => { await expect(callAsyncFunc()).resolves.toEqual(true) }) test('my async test', async () => { await expect(callAsyncFunc()).rejects.toEqual(false) }) 13 . 2
  36. TIMERS ⏰ TIMERS ⏰ 14 . 1

  37. Eradicating Non-Determinism in Tests - Asynchronous Behavior Eradicating Non-Determinism in

    Tests - Asynchronous Behavior Martin Fowler, 2011 14 . 2
  38. function callAsyncFunction() { return setTimeout(() => { return Promise.resolve(true) },

    1000) } test('assert after some time', done => { callAsyncFunc(). then((value) => { expect(value).toBe(true) done() }) }) 14 . 3
  39. describe('using fake timers', () => { beforeEach(() => { jest.useFakeTimers()

    }) afterEach(() => { jest.restoreAllMocks() }) }) 14 . 4
  40. test('should handle next scene', () => { const value =

    callAsyncFunc() jest.advanceTimersByTime(2000); expect(value).toBe(true) }) function callAsyncFunction() { return setTimeout(() => { return Promise.resolve(true) }, 1000) } 14 . 5
  41. Timer mocks Timer mocks 14 . 6

  42. WRAPPING UP 📔 WRAPPING UP 📔 15 . 1

  43. toEqual toEqual is usually used more than any assertion is

    usually used more than any assertion 15 . 2
  44. Using different assertions can improve Using different assertions can improve

    understading understading 15 . 3
  45. HAPPY TESTING 🤪 HAPPY TESTING 🤪 15 . 4

  46. Talk inspired by: Talk inspired by: 1. 2. 3. 4.

    Martin Fowler, Eradicating Non-Determinism in Tests (2011) jest extended Jest asserts beyond equals (2021) Jest timers and reactjs (2021) 15 . 5
  47. ABOUT ME ABOUT ME Software craftsperson at Software craftsperson at

    Oriented to software testing ( Oriented to software testing ( ) ) Codurance Codurance Testable Testable @MatheusMarabesi 🐦 @MatheusMarabesi 🐦 marabesi.com 💻 marabesi.com 💻
  48. 16 . 1