Snapshot Testing

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 2 min

Snapshot Testing

Snapshot testing is a specific type of testing provided by tools like Jest and Vitest. Instead of writing manual assertions (e.g., expect(element).toHaveTextContent('Hello')), a snapshot test captures the entire rendered output of your component and saves it to a file.

On subsequent test runs, it compares the new output against the saved “snapshot” file. If they differ, the test fails.

How it works

  1. The First Run: When you run a snapshot test for the very first time, the test runner renders your component, converts the Virtual DOM into a serialized string, and saves it in a __snapshots__ directory.

    // Component: <Badge status="active" />
    // The generated snapshot file might look like this:
    exports[`Badge Component matches snapshot`] = `
    <span class="badge badge-active">
      Active
    </span>
    `;
  2. Subsequent Runs: If another developer changes the component’s output (e.g., changing the class to badge badge-green), the test runner will compare the new output to the saved string. They won’t match, so the test fails, warning the developer that the UI has changed.

  3. Updating Snapshots: If the UI change was intentional, the developer runs the tests with an “update” flag (e.g., jest -u). The test runner deletes the old snapshot and saves the new one.

The Controversy of Snapshot Testing

When Snapshot Testing was first introduced, it became wildly popular because it was incredibly easy to write. You didn’t have to think about assertions; you just wrote expect(tree).toMatchSnapshot() and got 100% test coverage instantly.

However, the React community has largely turned against widespread snapshot testing for several reasons:

  1. False Positives (Test Fatigue): Snapshots are extremely brittle. If you change a generic CSS class name on a wrapper <div>, 50 different snapshot tests might fail. Developers get so used to snapshots failing for trivial reasons that they blindly press “Update Snapshots” (jest -u) without actually looking at what broke. This defeats the entire purpose of a test.
  2. Lack of Intent: A snapshot test doesn’t explain why the component looks the way it does. A standard test (expect(button).toBeDisabled()) clearly communicates the developer’s intent. A snapshot just says “it looks like this massive block of text.”
  3. Huge PRs: Snapshot files can be massive, cluttering up Pull Requests and making code reviews difficult.

When to use Snapshot Testing

Today, Snapshot testing is generally discouraged for standard React UI components. You should use React Testing Library to assert specific behaviors instead.

Good use cases for Snapshots:

  • Testing functions that output large, complex JSON objects or configuration files.
  • Testing a core, highly-reusable Design System component (like a highly complex generic Table component) where any change to the HTML structure is critical and must be strictly audited.

Interview Questions

Q: What are the primary downsides of Snapshot testing?
A: They are notoriously fragile. Any minor, intentional UI change (like adding a CSS padding class or fixing a typo) will instantly “break” the snapshot. Over time, developers get “snapshot fatigue” and blindly press “Update Snapshot” without checking what changed, rendering the tests completely useless.