Watch the bar turn green with TDD

When there are bugs, there is probably nothing more pleasing than figure out a way to:

  • Write a failing unit test that reproduces that bug.
  • Fix it and watch the bar turn green again, forever and ever 😉
La imagen tiene un atributo ALT vacío; su nombre de archivo es image-19-600x606.png

If your goal is to stay green for all of your existing tests by using the Test Driven Development (TDD) approach, you need to mentally train yourself to:

  • Think about the behavior around the next pieces of functionalities that you need in your code, then start moving towards your end goal in tiny steps and you will end up seeing tangible progress every moment.
  • Write unit test first, they shouldn’t be written as an extra chore when you finally have the code already working, this is called Test-Driven Development.

If you are designing an application to expose your data sources as REST API endpoints or as a unique GraphQL endpoint, TDD will definitely help you to design and maintain your APIs better. So if you are a principled developer who writes the tests that exercise the API first, you will discover where the APIs get complex to use before you even write the code, and you will be free to redesign much more easily than if you only add the tests afterwards.

Test the UI

Thanks goodness Create-React-App comes with Jest as its test runner and jest-dom for improved assertions. In combination with a state of the art package called the react-testing-library you will enjoy testing any React Component behavior or any Function or Hook’s inputs and outputs.

RTL Principle:

“The more your tests resemble the way your software is used, the more confidence they can give you.”

Another cool friendly kid in the hood is:

First thing you need to ask is: why we would want to mock fetch requests?

Because you use fetch to allow your App to interact with the rest of world, using:

  • Client-side JavaScript to trigger a network request to some local or remote backend API.
  • Server-side JavaScript talks to other local or remote servers.

Because you want to make sure your code doesn’t depends of flaky externalities, you want to ensure to produce the exact same output given the same inputs.

Setup your test environment

Initial configuration:

...
  "jest": {
    "collectCoverageFrom": [
      "src/**/*.{js,jsx,ts,tsx}",
      "!src/**/index.{js,jsx,ts,tsx}",
      "!src/config/*",
      "!src/index.js",
      "!src/serviceWorker.js"
    ],
    "coverageThreshold": {
      "global": {
        "branches": 90,
        "functions": 90,
        "lines": 90,
        "statements": 90
      }
    },
    "coverageReporters": [
      "text-summary"
    ]
  }
...
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "test-changed": "npm test --watchAll=false",
    "test-coverage-text": "npm test -- --coverage --coverageReporters=\"text\" --watchAll",
    "test-coverage-text-summary": "npm test -- --coverage --coverageReporters=\"text-summary\" --watchAll",
    "eject": "react-scripts eject"
  }
...
  "devDependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "@testing-library/react-hooks": "^3.4.1",
    "jest-fetch-mock": "^3.0.3",
    "react-test-renderer": "^16.13.1"
  }
...

If your app uses a browser API that you need to mock in your tests or if you need a global setup before running your tests, add a src/setupTests.js to your project. It will be automatically executed before running your tests.

// https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom/extend-expect";

// https://github.com/jefflau/jest-fetch-mock
import fetchMock from "jest-fetch-mock";
fetchMock.enableMocks();

Code Sample

git clone https://github.com/josoroma/reactjs-challenge.git
How I like to Write Integration Tests in React - YouTube

Routes

Components

You should test components’ behavior only.

App

States

States.lazy

Toolbar

Custom Hooks (renderHook())

You should test functions’ inputs and outputs only.

SearchValue Dispatch Hook

SearchValue State Hook

Context Reducer Function

Service Function

Util Function

Happy hacking!!!

Tip: If you are a great team player and the project is going through a long maintenance process, you should probably start writing tests for untested code, just seeing the Coverage Report as a G.A.M.E.