Temporal
Course Description
Ship code with confidence! Learn the basics of testing and apply Test-Driven Development techniques to your workflow. Create automated tests for DOM elements and user interactions. Use mocks and spies to control your environment and test more complex code. Gain practical experience writing unit and integration tests while exploring common testing tools.
This course and others like it are available as part of our Frontend Masters video subscription.
Preview
CloseCourse Details
Published: October 29, 2024
Learning Paths
Topics
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 200+ In-depth courses
- 18 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 15 minutes
- Steve Kinney begins the course by sharing the benefits of testing and providing the code for a basic test. Prerequisites are also discussed. Students do not need any previous testing experience but should be comfortable with JavaScript and NPM.
- Steve provides links to the course website and the GitHub repository containing examples used throughout the course. Students should clone the repo and run `npm install` in the root directory. Vitest, the primary testing tool used in this course, is introduced, and some additional testing tools are discussed.
Testing Basics
Section Duration: 53 minutes
- Steve runs an example test and explains the structure. Tests use a specific API to verify code works as expected. When a test fails, an error is thrown in the test. The terminal provides instant feedback, automatically re-running tests as they change and displaying the results.
- Steve introduces test-driven development as the add() function is tested. First, a test is written to verify the correct result is returned when two numbers are passed to the add() function. The test fails initially because the function is not yet implemented. After the test is written, the add() function is implemented, and the tests pass.
- Students are instructed to write tests for the subtract, multiply, and divide functions. After writing the tests, the functions should be implemented.
- Steve walks through some general guidelines for writing tests. Tests can be easy to write. The more difficult challenge is thinking through the edge cases that must also be tested. For example, what if two strings are passed to the add() function?
- Steve writes additional tests to ensure the add() function can handle unintended input. These tests check for valid input and an expected result. If string values can be converted to numbers, the function should still return the sum. If the result is NaN, the function should throw an error.
- Students are instructed to write tests for the subtract, multiply, and divide functions to handle different types of input. After writing each test, the function implementations should be updated so the tests pass.
Testing Equality
Section Duration: 39 minutes
- Steve explains the options for testing equality. Functions like toBe, toEqual, and toStrictlyEqual behave differently depending on the data type in the comparison. Other functions can provide more flexible comparisons by only checking if properties are contained on a datatype.
- Steve shares techniques for testing random or indeterminant values. These values include random numbers, unique user ids (uuid), and dates or times. Strategies include only testing the type or testing the value has the correct format.
- Students are instructed to write unit tests for the Character class. The tests include verifying a character has a first name, last name, and role, as well as testing the levelUp method correctly increases the characters level.
- Steve discusses testing asynchronous code and demonstrates how the beforeEach hook allows developers to consolidate repeated code that is used at the start of each test.
Testing the DOM
Section Duration: 1 hour, 1 minute
- Steve explains that DOM testing is more difficult because DOM APIs are unavailable in the Node.js runtime. Libraries like Happy DOM solve this problem by providing a JavaScript implementation of a web browser without its graphical user interface.
- Steve uses Happy DOM to create some simple tests for a button element. The tests verify a button element is created and ensure the label is changed when the button is clicked.
- Steve introduces Testing Library which provides additional utility methods for testing DOM elements and events. An added benefit of Testing Library is the built-in selectors find elements the way users and screen readers do, so you are encouraged to write more accessible code.
- Steve walks through the accident counter project, a basic counter application built with React. Two initial tests are written using the Testing Library APIs. One test highlights the utility methods for checking if a button is disabled.
- Students are instructed to implement the remaining tests in the accident counter project. This lesson includes the solutions for testing "days" is displayed when the count is zero and ensuring the count is incremented when the increment button is clicked.
- Steve continues the solution for the Accident Counter exercise. This lesson includes the tests for displaying "day" when the count is 1 and decrementing the count when the decrement button is clicked.
- Steve outlines other helpful methods available in Testing Library for querying DOM elements.
Stubs, Spies, and Mocks
Section Duration: 1 hour, 9 minutes
- Steve introduces Test Doubles, which includes testing tools like stubs, mocks, and spies. These tools are useful for "faking" data or dynamic areas of an application to control the testing environment.
- Steve demonstrates how spies track whether a function was called, how many times it was called, and with what arguments. They can also verify that a function was triggered under the right conditions. Spies do not modify the function’s original behavior unless explicitly configured.
- Steve explains mocks replace the actual implementation of a function and configure how it behaves in different test cases. Like spies, mocks keep track of how many times a function was called and with what arguments. Mocks combine the benefits of both stubs and spies, making them useful in more complex testing scenarios.
- Students are instructed to spy on the alert() function to ensure it's called with the correct message when the "Trigger Alert" button is clicked. This lesson also includes a solution using dependency injection.
- Steve explores how to mock dependencies in components. Using stubs and mocks allows developers to control the environment, however, mocking too many dependencies can lead to unrealistic testing scenarios. Refactoring code to use dependency injection is a better solution for creating more testable code.
- Steve demonstrates the methods provided by Vitest for mocking dates and times. These methods are useful for testing how UI elements behave in time-based situations like showing the time since a specific update or an interaction that need to occur after a specific time.
End-To-End Testing
Section Duration: 26 minutes
- Steve introduces end-to-end testing with Playwright. Playwright launches a headless browser and tests a URL with the same interactions a user would. The methods provided from Playwright can check the page title, find elements on the page, click buttons, and more.
- Steve demonstrates how to write Playwright tests for testing the accident counter project. The tests launch the application, then locates and clicks the increment button. While this test is simple, it ensures the UI elements are there and are functional.
- Steve introduces Mock Service Worker. The JavaScript Service Worker API can intercept network requests. The Mock Service Worker library leverages this capability, allowing mock network requests to be created and used in place of real backend APIs.
Wrapping Up
Section Duration: 3 minutes
- Steve wraps up the course with some final thoughts about testing. Getting to a comfortable level of test coverage for a team can be difficult if an application is already in production, but the combination of improved testing and refactoring difficult-to-test code will help.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops