Week 5 - Problem solving methods

Problem solving

Basic algorithms

Big O notation

Logging

Debugging

Unit testing

AI

Practice

Assignment

Back to core program

Software Testing

As you begin learning how to write JavaScript code, you quickly become comfortable creating functions and building small programs. After writing a piece of code, the natural thing every beginner does is test it manually. This usually means running your function with a few different inputs and checking the output by hand. For example, if you write a simple sum function, you might test it by calling it with values like sum(2, 3), sum(10, -2), or sum(0, 0) to see whether it behaves correctly.

Manual testing works well when your project is small. It only takes a moment to try a few examples and confirm that your code seems right. However, as your programs become more complex, manual testing becomes slow, repetitive, and difficult to manage. You may forget to test certain cases, overlook unexpected behavior, or miss a bug entirely. When different parts of your program start depending on each other, a tiny change in one place can break something somewhere else without you realizing it. This is why software testing becomes so important as your skills and projects grow.

Software testing exists to help developers verify that their code behaves correctly and continues to behave correctly as the application evolves. Testing makes your programs more reliable, easier to maintain, and safer to update. It helps you catch mistakes early, avoid regressions, and reduce the time spent debugging. Most importantly, testing gives you confidence to build more complex applications without the fear of accidentally breaking something that used to work.

Why we need to test our code

Even when your code looks correct, there is no guarantee that it will behave correctly in all situations. Bugs are a normal part of programming, and mistakes happen even to experienced developers. As your project grows, it becomes harder to keep track of what every function does and how different parts interact with each other. Without testing, a simple update can unintentionally introduce new bugs.

Testing solves this problem by acting as a safety net. It validates that your code works the way you think it does and continues to work even after making changes. When problems appear, tests help you find them early, before they spread into larger issues. Testing also makes collaboration easier because each developer can work independently, knowing that tests will catch unexpected interactions or breakages. Ultimately, testing is an essential part of writing code that is trustworthy, maintainable, and ready for real-world use.

What is a Unit Test?

A unit test is a very small, focused check that looks at one piece of your code at a time—usually a single function. The idea is simple: you take a function, give it some input, and see whether the output is what you expected. Instead of testing your whole program at once, you test each “unit” individually.

Here is a simple function we want to test:

function double(n) {
  return n * 2;
}

To understand whether this function works correctly, you would try different inputs and think about the expected results. For example, doubling 2 should give 4, doubling -3 should give -6, and doubling 0 should give 0. By checking these different situations, you confirm that the function behaves correctly in a variety of cases.

The purpose of a unit test is not to check everything at once, but to focus on one small behavior at a time. This makes it easier to find problems quickly because you always know exactly where to look when something goes wrong. As applications grow larger, having many small, well-tested units makes the entire system easier to build, understand, and maintain.

Test Automation

Manually testing your code is fine at first, but it quickly becomes inefficient as your project grows. You have to remember which scenarios to test, type them in repeatedly, and carefully check each result. This process becomes slow and error-prone, especially when many functions depend on each other.

Test automation removes this burden by letting the computer run your tests for you. Automated tests run in seconds, never forget a test case, and immediately alert you when something breaks. Instead of repeating the same checks by hand, you write tests once and let the testing tool handle the rest. This not only saves time but also brings consistency, reliability, and confidence to your development process. As your applications become larger, automation becomes essential for maintaining code quality.

Code Coverage

Code coverage is a tool that helps you understand how much of your code is being tested. It measures which lines, branches, and functions execute during your tests. For example, you might discover that your tests execute 70% of your code, while 30% is never touched. This information highlights areas where bugs may be hiding or where tests might be missing.

Although high coverage does not guarantee bug-free code, it does increase your confidence in the stability of your program. Low coverage, on the other hand, indicates that parts of your code may never have been validated and could fail unexpectedly. Code coverage is a valuable guide for improving the completeness and effectiveness of your testing.

Choosing Test Cases

Writing good tests means thinking beyond the most common or “happy path” scenarios. A robust function should behave correctly in a wide range of situations, including unusual or unexpected cases. When choosing test cases, developers consider typical inputs, extreme values, edge cases, and invalid inputs.

For example, a function that processes numbers should be tested with positive numbers, negative numbers, zero, very large numbers, and non-numeric values. Edge cases like an empty array, a missing parameter, or special characters often reveal bugs that normal inputs do not. By carefully selecting test cases, developers create more reliable tests and ensure their functions behave consistently in real-world situations.

Once you understand how to choose the right test cases, the next step is learning how to automate those tests. Instead of checking them manually, you can use a testing framework that runs all your test cases every time your code changes. One of the most popular and beginner-friendly tools for this in JavaScript is Vitest.

Unit Testing with Vitest

Unit testing is the practice of checking whether small, individual pieces of your code (usually functions) work the way you expect. Instead of waiting for bugs to appear later, tests help you catch mistakes early and make changes confidently.

Vitest is a fast, modern testing framework built for JavaScript. It works similarly to Jest and integrates well with modern tooling.

Testing is not about proving your code is perfect — it’s about proving your assumptions are correct.

Vitest is a modern, fast, and beginner-friendly testing framework designed for JavaScript and TypeScript. It lets you take all those test cases you planned—your typical inputs, edge cases, and error conditions—and turn them into automated tests that the computer can run for you. With Vitest, you write simple test files describing how your functions should behave, and Vitest repeatedly checks those behaviors every time you run your test suite.

Here is an example of a Vitest test:

import { test, expect } from "vitest";
import { sum } from "./sum.js";

test("adds two numbers", () => {
  expect(sum(2, 3)).toBe(5);
});

For more details on vitest, visit the official Vitest website: 🔗 https://vitest.dev/

Setting Up Vitest in a Simple JavaScript Project

The AAA Pattern: Arrange – Act – Assert

Example: Using the AAA pattern with a findMax function

Why the AAA pattern is helpful

Testing edge cases

Common matchers (expect methods)

Testing functions with different inputs

When tests fail

Organizing test files

Summary

Concept Meaning
Unit test Checks one small piece of logic
AAA pattern Clean structure for writing tests
expect() Asserts the result
toBe / toEqual Common matchers
Edge cases Rare but important situations
Vitest A modern, fast test framework

📚 Extra Reading (Videos)

Here are a few short videos to help you understand software testing better:

These are optional resources to deepen your understanding.


CC BY-NC-SA 4.0 Icons

*https://hackyourfuture.net/*

Found a mistake or have a suggestion? Let us know in the feedback form.