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