Skip to Content
Course content

126: Testing with Vitest

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Imagine you're a chef preparing a complex sauce for a high-end dinner service. You wouldn't just pour the entire pot onto a plate and serve it to a customer to see if it tastes right, right? That's a recipe for a disaster. Instead, you use a tasting spoon. You take a tiny sample, check for salt, taste for acidity, and adjust. If the spoon tastes right, you can be reasonably confident the whole pot is good.

In our world, Vitest is that tasting spoon. Instead of booting up your entire application, clicking through the UI, and hoping you didn't break the checkout flow, you write a small, isolated test to verify one specific "flavor" of your code. If the test passes, you know that specific logic is sound without having to run the whole program.

Why we're using Vitest over the alternatives

You've probably heard of Jest. For years, it was the gold standard. But if you're using Vite for your build tool—which you are—Vitest is a no-brainer. It's designed to share the same configuration as your Vite project, meaning you don't have to spend three hours fighting with Babel or TypeScript transforms just to get your tests to run. It's incredibly fast and uses a syntax that's almost identical to Jest, so the skills are transferable.

Putting assertions to work

Let's look at a real scenario. Suppose you've written a utility function that calculates the final price of an item after applying a discount and tax. This is the kind of logic where a tiny typo—like a plus sign instead of a minus—can cost a company thousands of dollars.

// priceCalculator.js
export function calculateFinalPrice(price, discount, taxRate) {
  const discounted = price - (price * discount);
  return discounted + (discounted * taxRate);
}

To test this, we create a file ending in .test.js. Here is how I'd set up a suite to make sure this logic is bulletproof:

import { describe, it, expect } from 'vitest';
import { calculateFinalPrice } from './priceCalculator';

describe('calculateFinalPrice()', () => {
  it('should apply a 10% discount and 5% tax correctly', () => {
    const result = calculateFinalPrice(100, 0.10, 0.05);
    // 100 - 10 = 90. 90 + (90 * 0.05) = 94.5
    expect(result).toBe(94.5);
  });

  it('should return the original price if discount and tax are zero', () => {
    expect(calculateFinalPrice(100, 0, 0)).toBe(100);
  });

  it('should handle free items correctly', () => {
    expect(calculateFinalPrice(0, 0.10, 0.05)).toBe(0);
  });
});

Notice the pattern: describe groups our tests together, it describes the specific behavior we expect, and expect(...).toBe(...) is the actual check. If the value inside toBe doesn't match the result, Vitest will scream at you in the console, telling you exactly what it expected versus what it actually got.

Dealing with the "unpredictables"

The hardest part of testing isn't the math; it's the stuff you can't control, like API calls or the current date. I've spent way too many hours watching tests fail simply because it was a leap year or the server was down. This is where mocking comes in.

Vitest allows you to replace a real function with a "spy" or a "mock." If your function calls fetch() to get a user's profile, you don't actually want to hit the network every time you run a test. You can tell Vitest: "When this function is called, don't actually go to the internet; just pretend the server returned this specific JSON object." This keeps your tests fast, deterministic, and capable of running on a plane without Wi-Fi.




📋 Practical Task

Exercise: Validating a Password Strength Checker

You need to build and test a password validation utility. Your goal is to ensure that users aren't choosing passwords that are too simple, but also that the validator doesn't accidentally reject valid passwords.

The Requirements:

  • Create a function validatePassword(password) that returns true if the password is at least 8 characters long and contains at least one number, and false otherwise.
  • Write a Vitest test suite that covers the following scenarios:
    1. A password that is too short (e.g., "Pass1").
    2. A password that is long enough but has no numbers (e.g., "PasswordOnly").
    3. A password that meets all criteria (e.g., "SecurePass123").
    4. An empty string.

Success Criteria: Your test suite should run 4 tests, and all 4 must pass. Use describe and it blocks to keep your tests organized.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.