Testing

Why Test?

Behave the way the user expects.

  • detect bug or functionality issues.
  • be confident the calculations are correct.
  • be confident subsequent changes work as it did before.

Helps define requirements of what you are looking to build.

  • helps developers hone in and focus on what is necessary

Others can easily understand.

  • convey the intent of the application clearly.
  • tests also act as documentation.

Backend can have bugs that you will never find out about until something goes wrong.

  • silent type mismatches.

Easy to modify or extend, refactor.

  • applications are never static (new feature and functionality) - ensures consistency on change.
  • address only what is necessary - getting to agreed test suite.

TDD

Writing test before writing code.

Rapidly define requirements as tests that must be satisfied by the code you later write.

  • Makes implementation highly predictable.
// react test import React from "react" import { render } from "@testing-library/react" import App from "./App" test("renders learn react link", () => { const { getByText } = render(<App />) const linkElement = getByText(/learn react/i) expect(linkElement).toBeInTheDocument() })

Run test via npm test.

Red Green Refactor

# Write a failing test (fail, stop)

# Write a success test (passing)
## functionality may not be complete, but working
null test → pass

stub required objects → test presence → pass

write functionality spec → test failure → create functionality in actual file → test → pass

Test Structure

Test structure should follow:

Setup
Method
Validation/Assertion

Boundaries

Avoid implementation of external dependencies in unit tests.

Using things like dependency injection (and shallow-mocking the dependencies), you can avoid relying on the actual implementations to run properly for the test to pass.

// external dependencies and its implementation tested import ( someExternalFunction ) func testTightCoupling(someParam: string) boolean { testValue := someParam // calling actual implementation (bad) someExternalFunction(testValue); // assertion } // shallow dependencies using mock return value const mockedServiceMethod = mock(someExternalFunction) func testLooseCoupling() boolean { testValue := someParam // calling mocked implementation mockedServiceMethod(testValue) }