Code coverage with Storybook test runner
Get story coverage to find missing edge cases
Apps are more complex, multi-state, and personalized than ever. That yields thousands of UI permutations which need to be tested for bugs. But how do you ensure your tests cover every state of a UI component?
Code coverage scans your code for untested edge cases. That helps you write more comprehensive tests and increases confidence in UI.
I'm excited to share that Storybook test runner now generates coverage reports. Read on to learn more:
- ๐งฉ Easy to setup via addon
- โ React, Preact, Vue, Svelte, Web components & HTML support
- ๐งฐ Babel and Vite compatible
- โ๏ธ Customizable to your project's needs
Use stories to test components
Before diving into coverage reports, let's take a moment to recap how you can test component behavior using Storybook.
While writing stories for a component, you also capture its test cases. Each story describes one component state. You supply props and mock data to render that variation in isolation. That acts as the initial state for your test.
You can then attach a play function to the story to simulate user behavior (e.g., clicks and inputs) and run assertions. Finally, use Storybook test runner to execute the tests.
// AccountForm.stories.ts
import { within, userEvent } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
import { AccountForm } from './AccountForm';
const meta = { component: AccountForm };
export default meta;
export const VerificationSuccess = {
args: {
passwordVerification: true,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.type(canvas.getByTestId('email'), 'michael@chromatic.com');
await userEvent.type(canvas.getByTestId('password1'), 'k32904nยฃ#1kjad');
await userEvent.type(canvas.getByTestId('password2'), 'k32904nยฃ#1kjad');
await userEvent.click(canvas.getByTestId('submit'));
await expect(
canvas.getByText(
'Everything is perfect. Your account is ready and we should probably get you started!'
)
).toBeInTheDocument();
},
};
Powered by Jest & Playwright
The test runner is powered by Jest and Playwright to verify that stories render without errors and that all assertions pass.
Generate code coverage reports with Storybook test runner
Bugs often sneak through even if you have the best test automation. That doesn't mean there's a flaw in your test suite but that the tests are incomplete. Your code has multiple logic branches and conditions so it's easy to miss test cases for a few of them.
Code coverage makes it easier to spot untested edge cases. It lets you see which lines of your code are tested. This helps you to write more relevant tests and improve the quality of your test suite.
Let's go ahead and set up code coverage for Storybook test runner in two steps.
1. Instrument the code
Instrumenting your code allows Storybook to track your lines of code and figure out which ones are covered by tests. Istanbul is the goto instrumentation library in the JavaScript ecosystem. With Storybook, you can use the @storybook/addon-coverage
to set up Istanbul instrumentation for your project.
The coverage addon offers out-of-the-box support for React, Preact, HTML, Web components, Svelte and Vue. It detects whether you're using Babel or Vite and configures Istanbul instrumentation accordingly.
To use it, install @storybook/addon-coverage
:
yarn add -D @storybook/addon-coverage
And register it in your .storybook/main.js
file:
// .storybook/main.js
module.exports = {
// ...rest of your code here
addons: [
"@storybook/addon-coverage",
]
};
Manually configuring Istanbul
The addon is configured to work for most projects by default. However, you can pass in an options object to customize it to your project's needs.
You can control what files to include or exclude in the coverage report. Or set the working directory, which is especially useful when working in a monorepo.
Some frameworks, such as Angular, do not use Babel or Vite. In that case you have to manually instrument your code. Check out ย Storybook coverage recipes repository for more such recipes and examples.
2. Run tests with the coverage flag
Now that you've set up the instrumentation, you're ready to use the test runner. First, start your Storybook:
yarn storybook
Then, run Storybook test runner in a separate terminal, with the --coverage
flag:
yarn test-storybook --coverage
The test runner will report the results in the CLI and generate a coverage/storybook/coverage-storybook.json
file which can be used by nyc
(the Istanbul command line interface).
Use alternative coverage reporters
By default, the test runner gives you a text report. However, you can use the output coverage-storybook.json
file to generate other types of reports.
One example is a lcov report which gives you a more detailed, interactive coverage summary that you can access via the browser.
To generate the lcov report, run the following:
npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook
nyc
is a dependency of the test runner, so you'll already have it in your project. Note, if you use Vue or Svelte, you'll have to configure nyc
to include .vue
or .svelte
files in the report.
It outputs the HTML files in the coverage
folder. Open the coverage/storybook/lcov-report/index.html
file in your browser to view the report.
Additionally, you can use tools like Codecov to automate code coverage reporting. Codecov will automatically detect the coverage files and visualize coverage progress over time.
Send us feedback
The coverage addon is experimental, and we need your help to stabilize it. Try it on your project and report any bugs or suggestions to improve it. Join us in Storybook Discordโs #testing channel or contribute via GitHub.
You can learn more about code coverage in the test runner documentation.
Coverage tracks test suite health
Stories are the starting point for component testing. You can quickly isolate a component and capture all its states and variations as stories. Then use Storybook test runner to simulate interactions and verify component behavior.
The code coverage addon gives you valuable insights about your test suite. It tracks which components are being tested and alerts you to edge cases you might have missed.