Docs
Storybook Docs

Test coverage

Watch a video tutorial on the Storybook channel

Test coverage is the practice of measuring whether existing tests fully cover your code. That means surfacing areas which aren't currently being tested, such as: conditions, logic branches, functions and variables.

Coverage tests examine the instrumented code against a set of industry-accepted best practices. They act as the last line of QA to improve the quality of your test suite.

Code instrumentation with the coverage addon

Storybook provides an official test coverage addon. Powered by Istanbul, which allows out-of-the-box code instrumentation for the most commonly used frameworks and builders in the JavaScript ecosystem.

Set up the coverage addon

Engineered to work alongside modern testing tools (e.g., Playwright), the coverage addon automatically instruments your code and generates code coverage data. For an optimal experience, we recommend using the test runner alongside the coverage addon to run your tests.

Run the following command to install the addon.

npm install @storybook/addon-coverage --save-dev

Update your Storybook configuration (in .storybook/main.js|ts) to include the coverage addon.

.storybook/main.js
export default {
  stories: [],
  addons: [
    // Other Storybook addons
    '@storybook/addon-coverage', //👈 Registers the addon
  ],
};

Start your Storybook with:

npm run storybook

Finally, open a new terminal window and run the test-runner with:

npm run test-storybook -- --coverage

Configure

By default, the @storybook/addon-coverage offers zero-config support for Storybook and instruments your code via istanbul-lib-instrument for Webpack, or vite-plugin-istanbul for Vite. However, you can extend your Storybook configuration file (i.e., .storybook/main.js|ts) and provide additional options to the addon. Listed below are the available options divided by builder and examples of how to use them.

.storybook/main.js
export default {
  stories: [],
  addons: [
    // Other Storybook addons
    {
      name: '@storybook/addon-coverage',
      options: {
        istanbul: {
          include: ['**/stories/**'],
          exclude: ['**/exampleDirectory/**'],
        },
      },
    },
  ],
};

| Vite options | Description | Type | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | | checkProd | Configures the plugin to skip instrumentation in production environments
options: { istanbul: { checkProd: true,}} | boolean | | cwd | Configures the working directory for the coverage tests.
Defaults to process.cwd()
options: { istanbul: { cwd: process.cwd(),}} | string | | cypress | Replaces the VITE_COVERAGE environment variable with CYPRESS_COVERAGE.
Requires Cypress's code coverage
options: { istanbul: { cypress: true,}} | boolean | | exclude | Overrides the default exclude list with the provided list of files or directories to exclude from coverage
options: { istanbul: { exclude: ['**/stories/**'],}} | Array<String> or string | | extension | Extends the default extension list with the provided list of file extensions to include in coverage
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}} | Array<String> or string | | forceBuildInstrument | Configures the plugin to add instrumentation in build mode
options: { istanbul: { forceBuildInstrument: true,}} | boolean | | include | Select the files to collect coverage
options: { istanbul: { include: ['**/stories/**'],}} | Array<String> or string | | nycrcPath | Defines the relative path for the existing nyc configuration file
options: { istanbul: { nycrcPath: '../nyc.config.js',}} | string | | requireEnv | Overrides the VITE_COVERAGE environment variable's value by granting access to the env variables
options: { istanbul: { requireEnv: true,}} | boolean |

| Webpack 5 options | Description | Type | | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | | autoWrap | Provides support for top-level return statements by wrapping the program code in a function
options: { istanbul: { autoWrap: true,}} | boolean | | compact | Condenses the output of the instrumented code. Useful for debugging
options: { istanbul: { compact: false,}} | boolean | | coverageVariable | Defines the global variable name that Istanbul will use to store coverage results
options: { istanbul: { coverageVariable: '__coverage__',}} | string | | cwd | Configures the working directory for the coverage tests.
Defaults to process.cwd()
options: { istanbul: { cwd: process.cwd(),}} | string | | debug | Enables the debug mode for additional logging information during the instrumentation process
options: { istanbul: { debug: true,}} | boolean | | esModules | Enables support for ES Module syntax
options: { istanbul: { esModules: true,}} | boolean | | exclude | Overrides the default exclude list with the provided list of files or directories to exclude from coverage
options: { istanbul: { exclude: ['**/stories/**'],}} | Array<String> or string | | extension | Extends the default extension list with the provided list of file extensions to include in coverage
options: { istanbul: { extension: ['.js', '.cjs', '.mjs'],}} | Array<String> or string | | include | Select the files to collect coverage
options: { istanbul: { include: ['**/stories/**'],}} | Array<String> or string | | nycrcPath | Defines the relative path for the existing nyc configuration file
options: { istanbul: { nycrcPath: '../nyc.config.js',}} | string | | preserveComments | Includes comments in the instrumented code
options: { istanbul: { preserveComments: true,}} | boolean | | produceSourceMap | Configures Instanbul to generate a source map for the instrumented code
options: { istanbul: { produceSourceMap: true,}} | boolean | | sourceMapUrlCallback | Defines a callback function invoked with the filename and the source map URL when a source map is generated
options: { istanbul: { sourceMapUrlCallback: (filename, url) => {},}} | function |

What about other coverage reporting tools?

Out of the box, code coverage tests work seamlessly with Storybook's test-runner and the @storybook/addon-coverage. However, that doesn't mean you can't use additional reporting tools (e.g., Codecov). For instance, if you're working with LCOV, you can use the generated output (in coverage/storybook/coverage-storybook.json) and create your own report with:

npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook

Troubleshooting

Run test coverage in other frameworks

If you intend on running coverage tests in frameworks with special files like Vue 3 or Svelte, you'll need to adjust your configuration and enable the required file extensions. For example, if you're using Vue, you'll need to add the following to your nyc configuration file (i.e., .nycrc.json or nyc.config.js):

.nyc.config.js
export default {
  // Other configuration options
  extension: ['.js', '.cjs', '.mjs', '.ts', '.tsx', '.jsx', '.vue'],
};

The coverage addon doesn't support optimized builds

If you generated a production build optimized for performance with the --test flag, and you're using the coverage addon to run tests against your Storybook, you may run into a situation where the coverage addon doesn't instrument your code. This is due to how the flag works, as it removes addons that have an impact on performance (e.g., Docs, coverage addon). To resolve this issue, you'll need to adjust your Storybook configuration file (i.e., .storybook/main.js|ts) and include the disabledAddons option to allow the addon to run tests at the expense of a slower build.

.storybook/main.js
export default {
  // Replace your-framework with the framework you are using (e.g., react-webpack5, vue3-vite)
  framework: '@storybook/your-framework',
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    '@storybook/addon-coverage',
  ],
  build: {
    test: {
      disabledAddons: ['@storybook/addon-docs', '@storybook/addon-essentials/docs'],
    },
  },
};

The coverage addon doesn't support instrumented code

As the coverage addon is based on Webpack5 loaders and Vite plugins for code instrumentation, frameworks that don't rely upon these libraries (e.g., Angular configured with Webpack), will require additional configuration to enable code instrumentation. In that case, you can refer to the following repository for more information.

Learn about other UI tests

Join the community

6,378 developers and counting
Open source software
Maintained by
Chromatic
Special thanks to Netlify and CircleCi