Write tests. Not too many. Mostly integration.

Kent C. Dodds

Utah

1 wife, 4 kids

PayPal, Inc.

@kentcdodds

Please Stand...

if you are able

What this talk is

  • Dissecting Guillermo's tweet
  • High level principles
  • Opinionated

What this talk is not

  • Bashing on other tools or methodologies
  • Full of gifs
  • 725 slides 😡

Let's
Get
STARTED!

The infamous tweet

(more than famous)

Write tests.

Why do we write tests?

Confidence!

Enhanced Workflows

Not too many.

Let's talk about "code coverage"

How much code coverage do you need?

Good question!

It dependsβ„’

Remember this?

Implementation Details

πŸ’‘

if your test does something that the consumer of your code doesn't then it's testing implementation details

πŸ’‘

πŸ’‘

if a refactor breaks your tests, then it's testing implementation details

πŸ’‘

Mostly integration.

The Testing Pyramid

The Gleb Pyramid

The Aaron Square

The Testing Dorito

Static Code Analysis

Unit tests

function sum(a, b) {
  return a + b
}

test('sum adds numbers', () => {
  expect(sum(1, 3)).toBe(4)
})

Integration tests

let api, server

beforeAll(async () => {
  server = await startServer()
  const {port} = server.address()
  api = axios.create({
    baseURL: `http://localhost:${port}/api`
  })
})

afterAll(() => server.close())

beforeEach(() => resetDb())

test('can register a user', async () => {
  const registerData = {username: 'bob', password: 'wiley'}
  const testUser = await api
    .post('auth/register', registerData)
    .then(response => response.data.user)
  expect(testUser.username).toBe(registerData.username)

  const readUserUnauthenticated = await api
    .get(`users/${testUser.id}`)
    .then(response => response.data.user)
  expect(readUserUnauthenticated).toEqual(testUser)
})

End-to-end tests

describe('authentication', () => {
  it('should allow users to register', () => {
    const user = {username: 'bob', password: 'wiley'}
    cy
      .visitApp()
      .getByTestId('register-link')
      .click()
      .getByTestId('username-input')
      .type(user.username)
      .getByTestId('password-input')
      .type(user.password)
      .getByTestId('login-submit')
      .click()

    cy
      .url()
      .should('equal', 'http://localhost:3000/')

    cy
      .getByTestId('username-display')
      .should('contain', user.username)
  })
})

The Testing Trophy

οΏ heap

πŸ’°πŸ€‘πŸ’°

πŸŽπŸ’¨

🐒

Simple problems πŸ‘Œ

Big problems πŸ˜–

Integration tests provide the best balance of:

  • οΏ heap
  • πŸŽπŸ’¨
  • πŸ˜–

But how? πŸ€”

Poke fewer holes in reality!

Test higher up your tree

πŸ‘ Thanks Guillermo! πŸ‘

Thank you!

πŸ™ kcd.im/write-tests-feedback πŸ™

resources on the next slide πŸ‘‰

Resources