Testing Practices and Principles

Kent C. Dodds

Utah

wife, 4 kids, & a dog

PayPal, Inc.

Please Stand...

if you are able ❤️ ♿️

What this talk is

  • Fundamentals behind tests and testing frameworks

  • Distinctions of different forms of testing

  • Writing unit and integration

  • Test doubles (mocks/stubs/etc.)

  • Use TDD to write new features and to find and fix bugs

  • Core principles of testing to ensure your tests give you the confidence you need

What this talk is not

  • Technology-specific
  • How to configure tools
  • Free of trade-offs
  • Long presentation
  • Covering all forms of testing

Setup

If you can, do it now, even if you've already done it...

git clone https://github.com/kentcdodds/testing-workshop.git

cd testing-workshop

npm run setup --silent

Logistics

Routine

  1. Demos 👨‍💻
  2. Exercises 💪 (pair programming!?)
  3. Elaboration and Feedback Form 📑
  4. ? Bonus 👨‍🎓 👩‍🎓
  5. ? Help others 👩‍🔬 👨‍🔬
  6. ? Make pull requests 🙏

Let's
Get
STARTED!

What kind of bugs are there?

Business Logic 🕷

Security 🕷

Accessibility 🐜

User Interface 🐞

Performance 🐛

Regression 🐞

Internationalization 🕷

Integration 🐜

Scaling 🐛

How do we prevent bugs?

  1. Static Types: Flow / TypeScript
  2. Linting: ESLint
  3. Testing: ??

What kinds of testing can we do?

Unit Testing

Regression Testing

Integration Testing

E2E Testing

Smoke Testing

Usability Testing

i18n Testing

Penetration Testing

User Acceptance Testing

Performance Testing

A/B Testing

a11y Testing

Stress Testing

Fuzz Testing

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

import {assertRoute} from '../utils'

describe('authentication', () => {
  it('should allow users to register', () => {
    const user = {username: 'bob', password: 'wiley'}
    cy
      .visitApp()
      .getByText('Register')
      .click()
      .getByLabelText('Username')
      .type(user.username)
      .getByLabelText('Password')
      .type(user.password)
      .getByText('Login')
      .click()

    cy.url().should('equal', 'http://localhost:3000/')
    cy.getByTestId('username-display').should('contain', user.username)
  })
})

🚗 Test Driven Development 🏎

Red

Green

Refactor

🐛 Fixing Bugs 🐜

Bug

Find Code

Write Test

Fix Test

The Testing Trophy

¢heap

💰🤑💰

🏎💨

🐢

Simple problems 👌

Big problems 😖

Resources

 

My blog/newsletter has a lot of content about testing too: blog.kentcdodds.com

Thank you!

Testing Practices and Principles

By Kent C. Dodds

Testing Practices and Principles

The goal of a test is to increase your confidence that the subject of your test is functioning the way it should be. Not all tests provide the same level of confidence (some provide very little confidence at all). If you’re not doing things correctly, you could be wasting your time and giving yourself a false sense of security (even worse than having no tests at all).

  • 10,321