Should I test that?

Should I test the production build?

Verdict

Yes

Yes, run one smoke test in CI against the production build: serve the built output, open each top-level route in a headless browser and fail on any script error; keep the unit tests on the source.

Why

Yes, test the production build minimally, with one smoke test of the built output. The typical case is a single-page web app whose bundler minifies and splits the code only in the production build, while unit tests run against the source. Blast radius is users, because customers load that bundle, and Change frequency is regularly, because a bundler upgrade or a build config edit changes the output about once a month. Detectability is same-day, because a blank page or a chunk that fails to load reaches error reports within hours. Reversibility is trivial, since a redeploy serves the previous bundle, and Test cost is moderate: the test builds the app, serves it and opens pages in a headless browser.

When the decision changes
WhenDecisionWhy
The build output is a library on npm that other projects importTest minimally: before each release, install the npm pack tarball in a fixture project and import every entry point from ESM and CommonJSReversibility moves to with-effort, because npm keeps the broken version and consumers must install a patch; the decision holds because consumers hit the import error at once and report it
Saved documents store constructor.name as the type of each shapeTest: against the production build, save a document and assert each shape's type, and give each class a fixed type stringDetectability moves to eventually and Reversibility to with-effort, because minified names save without an error and old documents need a repair script
The bundle holds the checkout, and a script error only in the production build stops ordersTest mandatory: before each release, an end-to-end test places an order against the production build in the payment provider's test modeBlast radius rises to money and Reversibility to costly, because orders lost while the checkout was broken stay lost
A static site of a few pages, where each pull request gets a preview deployment that its author opens before mergeDo not add a smoke test; open every page of the preview before mergeDetectability moves to immediately, because a broken page shows on the preview in front of the author of the change
The build serves a content dashboard that only staff useDo not test the build; staff report a broken page, and a redeploy of the previous bundle fixes itBlast radius falls to internal, because no customer sees the failure

What breaks if you don't test

Unit tests import the source, so they never run the code that the minifier and the tree shaker produce. Every unit test passes when a wrong base path sends lazy chunks to a 404, or when webpack drops a CSS import from a package that declares sideEffects: false. Customers get a blank or unstyled page after the deploy, and the first report comes from a user or the error tracker.

What you lose if you over-test

Running the whole unit suite against the minified bundle breaks every test that imports an internal module, because the bundle exports only its entry points. A long end-to-end suite on the production build repeats what the unit tests already checked, and each of its tests breaks when a label or a route changes.

How to test

Keep the unit tests on the source, and add one CI job after them. Serve the built output with vite preview, Vite's static server for dist, or any static file server, and let Playwright's webServer option start it. Open each top-level route, fail on any pageerror or failed chunk request, and check one element per page.

When the answer changes

  • The build output is a package that other projects install.
  • Code reads class or function names at runtime.
  • Every pull request gets a preview deployment that its author opens.

Real incident + Code example

The shapes that changed after a release

On a diagram editor I worked on, saved documents stored this.constructor.name as each shape's type. Unit tests and the dev server ran unminified code, so every check saw Rectangle. The production build renamed the classes, as MDN warns minifiers do, and documents saved in production stored types such as t. In the next release the minifier gave those letters to other classes, and old documents opened with the wrong shapes. A user reported it eleven days later, and we wrote a repair script from the previous build's source map. We gave each class a fixed static type and added this test, which Playwright runs against the production build:

import { test, expect } from '@playwright/test';

test('production build saves shape types by name', async ({ page }) => {
  const errors: string[] = [];
  page.on('pageerror', (error) => errors.push(error.message));
  await page.route('**/api/documents', (route) => route.fulfill({ status: 201 }));

  await page.goto('/editor/new');
  await page.getByRole('button', { name: 'Rectangle' }).click();
  const [save] = await Promise.all([
    page.waitForRequest('**/api/documents'),
    page.getByRole('button', { name: 'Save' }).click(),
  ]);

  expect(save.postDataJSON().shapes[0].type).toBe('Rectangle');
  expect(errors).toEqual([]);
});

The assertion fails on the minified build that stored t, and on the dev server it passes with or without the fix.

FAQ

Should I test a minified production build?

Yes, run one smoke test in CI against the minified production build, and keep the unit tests on the source. Minification renames functions and classes, so only a test of the built output sees failures that the renaming causes.

In CI, should tests be run against src or dist?

Run the unit tests against src, and run one smoke test against dist after the build. Unit tests on src reach internal modules, while the smoke test checks the files you deploy.

Should /dist/ be included in Jest tests?

No, add <rootDir>/dist/ to Jest's testPathIgnorePatterns. When the compiler writes test files into dist, Jest otherwise runs each test twice. Test the built output with a separate smoke test.