Testing

The Technical Bits

Behavior-Driven Testing

  • Both Cypress and Jest/Vitest use behavior-driven concepts.
  • Behavior-driven Development (BDD)
  • "it should ..." sentences label each test rather than method names
  • Usually has Given (preconditions), When (initial actions), and Then (expected results) structure
  • A testing framework collects the tests, runs them, counts successes and failures, and reports results

Describing Tests

  • Label tests with descriptive texts rather than function names
describe('sorting the list of users', function() {
  it('sorts in descending order by default', function() {
    ...
  });
});

Expected Values

  • Matcher methods on expect() describe expected results
expect(isLeapYear(2000)).toBe(true);

Cypress

  • Home page
  • Emphasizes simple to write and read tests
  • Only works with web apps
  • Talks to the app. Does not directly call your React functions.

Unit Testing Concepts

  • Test a unit, i.e., a single class or component, not the whole system.
  • Tests are independent. They can run in any order or even in parallel.
  • Common setup actions, e.g., connect to test DB, are in a setup method run before every test.
  • Common cleanup actions are in a tear down method run after every test.

Jest / Vitest

Unit (Jest/Vitest) vs E2E (Cypress)

E2EUnit
E2E tests interact with the app interface, just as a user does. Unit tests interact with the app code. They call app functions, look at app data structures.
E2E tests can slow, waiting for server, browser, and network responses. Unit tests should blazingly fast, fractions of a second.
A well-tested app will have hundreds of E2E tests. A well-tested app will have thousands of unit tests.

What to Unit Test

  • Code that sends data to a database
    • bugs here can corrupt all data permanently
  • Code with AND / OR / NOT logic on two or more variables
    • automation needed to test all combinations on all changes to code
  • Behavior involving several steps and/or change in time and space

What Not to Unit Test

  • Private internal functions
  • Simple setters and getters
  • Logging functions like toString

Tips

Unit Tests: The Challenge

  • Unit tests
    • should be numerous, fast, automated
    • should test only the unit, not other classes
    • should not cross module boundaries
  • So how can you unit test
    • network calls
    • database updates
    • modules that don't exist yet

Solution: Mock Objects

  • Mocks let you test that code calls another object correctly and uses the results correctly
    • A mock is a spy that records calls to it
    • A mock is a stub that imitates an object's responses
  • Mock libraries provide tools for making mocks in just a few steps
  • Mocks are also very useful for "Plan B" demos!!

Mocking Modules

Readings: Mock Objects

Thanks to Hakim El Hattab for RevealJS