4. Writing Unit Tests
As discussed earlier, unit tests are important to help maintain code quality and reduce bugs. But how do we write them?
Getting Started
- Install Jest in your node project with
npm install --save-dev jest
- Create your test file (either in your
__tests__
folder or with file extension:.test.js
or.spec.js
) - Run your tests with
npm jest
Example 1: Palindromess
Write a function what checks if the provided string is the same forwards as it is backwards
- Ignore spacing and punctuation
Finished Function
export function isPalindrome(str) { const cleanedStr = str.toLowerCase().replace(/[\W_]/g, ''); return cleanedStr === cleanedStr.split('').reverse().join(''); }
Finished Tests
const isPalindrome = require('./isPalindrome'); test('returns true for a simple palindrome', () => { expect(isPalindrome('racecar')).toBe(true); }); test('returns false for a non-palindrome', () => { expect(isPalindrome('hello')).toBe(false); }); test('ignores spaces and punctuation', () => { expect(isPalindrome('A man, a plan, a canal, Panama')).toBe(true); });
Example 2: Factorials
Write a function that calculates the factorial of a number.
- Ensure a factorial of 0 properly returns 1
- Factorials of negative numbers should return `undefined`
Finished Function
export function factorial(n) { if (n < 0) { return undefined; } if (n === 0) { return 1; } return n * factorial(n - 1); }
Finished Tests
const factorial = require('./factorial'); test('calculates factorial of a positive number', () => { expect(factorial(5)).toBe(120); }); test('returns 1 for factorial of 0', () => { expect(factorial(0)).toBe(1); }); test('returns -1 for negative numbers', () => { expect(factorial(-3)).toBe(-1); });
Example 3: FizzBuzz
Write a function that to compute the proper FizzBuzz word.
- If a number is divisible by 3, return "Fizz"
- If a number is divisible by 5, return "Buzz"
- If a number is divisible by 3 and 5, return "FizzBuzz"
- Otherwise, return the provided number
Finished Function
export function fizzBuzz(number) { if (numnber % 3 == 0 && number % 5 == 0) { return 'FizzBuzz'; } if (numnber % 3 == 0) { return 'Fizz'; } if (numnber % 5 == 0) { return 'Buzz'; } return number.toString(); }
Finished Tests
const fizzBuzz = require('./fizzbuzz'); test('returns Fizz for multiples of 3', () => { expect(fizzBuzz(9)).toBe('Fizz'); }); test('returns Buzz for multiples of 5', () => { expect(fizzBuzz(10)).toBe('Buzz'); }); test('returns FizzBuzz for multiples of 3 and 5', () => { expect(fizzBuzz(15)).toBe('FizzBuzz'); }); test('returns the number if not divisible by 3 or 5', () => { expect(fizzBuzz(7)).toBe('7'); });
Example 4: Greeting Generator
Write a function that gets a greeting for a user based on the time of day.
- If it's currently before 12 PM, return "Good Morning"
- If it's between 12 and 6PM return "Good Afternoon"
- Otherwise, return "Good Evening"
Finished Function
function generateGreeting() { const currentHour = new Date().getHours(); if (currentHour < 12) { return 'Good morning!'; } else if (currentHour < 18) { return 'Good afternoon!'; } else { return 'Good evening!'; } }
Testable Function
// Function to get the current hour function getCurrentHour() { return new Date().getHours(); } // Function to generate the greeting based on the hour function getGreetingMessage(hour) { if (hour < 12) { return 'Good morning!'; } else if (hour < 18) { return 'Good afternoon!'; } else { return 'Good evening!'; } }
Finished Tests
const { getGreetingMessage } = require('./greeting'); // Test greeting message based on different times of day test('returns "Good morning!" for hours less than 12', () => { expect(getGreetingMessage(9)).toBe('Good morning!'); }); test('returns "Good afternoon!" for hours between 12 and 17', () => { expect(getGreetingMessage(15)).toBe('Good afternoon!'); }); test('returns "Good evening!" for hours greater than or equal to 18', () => { expect(getGreetingMessage(20)).toBe('Good evening!'); });