JavaScript > Testing and Debugging > Unit Testing > Writing test cases
Simple Calculator Unit Tests with Jest
This example demonstrates how to write unit tests for a simple calculator class using Jest, a popular JavaScript testing framework. It includes test cases for addition, subtraction, multiplication, and division, covering both positive and negative numbers, as well as edge cases like division by zero.
The Calculator Class
This code defines a Calculator
class with four basic arithmetic operations: add
, subtract
, multiply
, and divide
. The divide
method includes error handling for division by zero.
class Calculator {
add(a, b) {
return a + b;
}
subtract(a, b) {
return a - b;
}
multiply(a, b) {
return a * b;
}
divide(a, b) {
if (b === 0) {
throw new Error('Division by zero is not allowed.');
}
return a / b;
}
}
Jest Test Suite
This is the Jest test suite for the Calculator
class. It uses describe
blocks to group tests for each operation (addition, subtraction, multiplication, and division). beforeEach
is used to create a new Calculator instance before each test, ensuring each test runs in isolation. Each it
block represents a single test case with a specific assertion using expect
. The toThrow
matcher is used to verify that the divide
method throws an error when dividing by zero.
describe('Calculator', () => {
let calculator;
beforeEach(() => {
calculator = new Calculator();
});
describe('Addition', () => {
it('should add two positive numbers', () => {
expect(calculator.add(2, 3)).toBe(5);
});
it('should add a positive and a negative number', () => {
expect(calculator.add(2, -3)).toBe(-1);
});
});
describe('Subtraction', () => {
it('should subtract two positive numbers', () => {
expect(calculator.subtract(5, 2)).toBe(3);
});
it('should subtract a negative number from a positive number', () => {
expect(calculator.subtract(5, -2)).toBe(7);
});
});
describe('Multiplication', () => {
it('should multiply two positive numbers', () => {
expect(calculator.multiply(2, 3)).toBe(6);
});
it('should multiply a positive and a negative number', () => {
expect(calculator.multiply(2, -3)).toBe(-6);
});
});
describe('Division', () => {
it('should divide two positive numbers', () => {
expect(calculator.divide(6, 2)).toBe(3);
});
it('should handle division by zero', () => {
expect(() => calculator.divide(6, 0)).toThrow('Division by zero is not allowed.');
});
});
});
Concepts Behind the Snippet
This snippet demonstrates the fundamental concepts of unit testing: isolating units of code (in this case, the methods of the Calculator class) and verifying their behavior in different scenarios. It uses Jest, a popular testing framework, to write assertions and organize the tests. The goal is to ensure that each function behaves as expected and that any errors are caught early in the development process.
Real-Life Use Case Section
Unit testing is crucial in any software development project, especially when dealing with complex logic or critical calculations. Imagine building a financial application; you want to ensure that all calculations, like interest rates and loan amounts, are accurate. Writing unit tests for each function allows you to verify the correctness of the code and prevent costly errors in production.
Best Practices
Interview Tip
When discussing unit testing in an interview, emphasize the importance of writing tests early and often. Explain how unit tests help you catch bugs early, improve code quality, and make refactoring easier. Be prepared to discuss different testing frameworks and their pros and cons. Demonstrate your understanding of TDD principles.
When to Use Them
Use unit tests whenever you write new code, especially functions or methods that perform specific tasks. They are particularly valuable for code that is complex, critical, or likely to change over time. Also, run unit tests whenever you refactor existing code to ensure that you haven't introduced any regressions.
Memory Footprint
Unit tests generally have a minimal memory footprint during runtime. The testing framework itself may consume some memory, but the tests are designed to run quickly and efficiently. Focus on writing efficient code in the application itself to optimize memory usage.
Alternatives
Alternative testing frameworks to Jest include Mocha, Jasmine, and Ava. Integration tests are used to test the interactions between different parts of the system. End-to-end tests simulate real user interactions with the application.
Pros
Cons
FAQ
-
What is the purpose of the
beforeEach
block?
ThebeforeEach
block is used to set up the environment for each test. In this example, it creates a new instance of theCalculator
class before each test case, ensuring that each test runs in isolation. -
What is the difference between
toBe
andtoEqual
in Jest?
toBe
is used for strict equality comparisons (===
), whiletoEqual
is used for deep equality comparisons, meaning it compares the values of the properties of objects or arrays. -
How do I run these tests?
First, make sure you have Node.js and npm installed. Install Jest usingnpm install --save-dev jest
. Then, add a test script to yourpackage.json
file:"test": "jest"
. Finally, run the tests usingnpm test
.