Writing automated tests is a non-negotiable skill for professional development. Testing ensures your code works as expected, prevents regressions (bugs reappearing), and makes complex refactoring safe. Unit testing focuses on testing the smallest units of code—individual functions or methods—in isolation.
1. Why Test?
Confidence: Ensures changes won't break existing features.
Documentation: Tests serve as executable examples of how code should be used.
Design: Thinking about testability often leads to better, more modular code design.
2. Testing Frameworks (Jest)
A testing framework provides the structure, tools, and reporting mechanisms for running tests. Jest (developed by Facebook) is the most popular choice for modern JavaScript and React.
Key Jest Terminology
Term | Description |
describe() | Groups related tests together into a Test Suite. |
test() or it() | Defines a single, individual Test Case. |
expect() | The value being tested. |
matcher | The function that compares the tested value against an expected value (e.g., .toBe() , .toEqual() ). |
Export to Sheets
3. Writing a Simple Unit Test
Imagine you have a file named math.js
with a simple function:
JavaScript
// math.jsexport function add(a, b) {
return a + b;
}
You create a corresponding test file named math.test.js
:
JavaScript
// math.test.jsimport { add } from './math';
// 1. Group the tests
describe('The add function', () => {
// 2. Define the first test case
test('should correctly add two positive numbers', () => {
// Arrange (Setup) and Act (Call the function)
const result = add(5, 7);
// Assert (Check the result using expect and a matcher)
expect(result).toBe(12); // .toBe() checks strict equality
});
// 3. Define another test case
test('should handle negative numbers', () => {
expect(add(-1, 5)).toBe(4);
});
// 4. Test for array/object equality (requires a different matcher)
test('should return correct object when adding properties', () => {
const result = add({ val: 1 }, { val: 2 });
// NOTE: This will fail if not using an object-friendly matcher
// expect(result).toEqual({ val: 1, val: 2 }); // Use .toEqual() for objects/arrays
});
});
4. Common Matchers
Matcher | Description |
.toBe(value) | Checks for strict equality (=== ) (best for primitives). |
.toEqual(object) | Checks for deep equality of objects or arrays. |
.toBeFalsy() | Checks if the value is falsy (false , 0 , '' , null , undefined , NaN ). |
.toBeTruthy() | Checks if the value is truthy. |
.toThrow() | Checks if a function throws an error. |
.toContain(item) | Checks if an array or string contains a specific item. |
Export to Sheets
5. Setup and Teardown
For tests that require complex setup (like initializing a database connection or creating a dummy DOM element), Jest provides hooks:
beforeEach()
: Runs before every test()
in the current describe
block.
afterEach()
: Runs after every test()
in the current describe
block (for cleanup).
beforeAll()
: Runs once before all test()
cases.
afterAll()
: Runs once after all test()
cases.
By integrating unit testing, you equip yourself with the professional discipline needed to write reliable and scalable JavaScript code.