# Reassure: performance tests that fail your CI when renders get slower

> Reassure measures how long your React Native or React components take to render, repeats the scenario to damp out runtime noise, applies statistical analysis to decide whether a change is significant, and posts a readable report to your pull request. The framing is deliberate: performance tests sit next to the tests you already have, not beside a profiler.

**callstack/reassure** — Performance testing companion for React and React Native

- Repository: https://github.com/callstack/reassure
- Website: https://callstack.github.io/reassure/
- Stars: 1,488 · Forks: 39
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/callstack-reassure

## The problem it names is a regression nobody notices until QA

The README is honest about why performance tooling is usually abandoned. You want your app to perform well and stay fast, so you profile, observe render patterns and apply memoization in the right places. All of that is manual, and it is easy to unintentionally introduce a performance regression that only gets caught during QA or, worse, by your users. The proposed symmetry is the idea worth taking: in the same way you write integration and unit tests that verify the app still works correctly, you can write performance tests that verify the app still works performantly. That framing is why the tool exists as a Jest citizen rather than as a profiler replacement. Profiling finds a problem once; this is aimed at the second week after the fix.

## Measurements are render count and render duration, compared statistically

The mechanism has four steps and the third is what makes it different from a stopwatch. Reassure measures the render characteristics of the scenario you provide, duration and count, and compares them to a stable version, which it calls the baseline. It repeats the scenario multiple times to reduce the impact of random variation in render times caused by the runtime environment. It then applies statistical analysis to determine whether the code changes are statistically significant. The output is a human-readable report summarizing the results, displayed on the CI or as a comment on your pull request. Repeating and analysing is what stops this from being a flaky assertion: a single slow run is noise, and a distribution compared properly is a signal.

## Install is a dev dependency beside Jest and a Testing Library

There is no framework to configure and no separate runner. The package goes into your app folder as a development dependency:

```sh
yarn add --dev reassure
```

```sh
npm install --save-dev reassure
```

You also need a working Jest setup and one of either React Native Testing Library or React Testing Library. Those are the only prerequisites, and the reason is stated in the README: Reassure is designed to reuse as much of your existing React Native Testing Library tests and setup as possible. It also auto-detects which Testing Library you have. If both are present it warns you and gives precedence to React Native Testing Library, and you can pin the choice explicitly in your Jest setup file:

```ts
configure({ testingLibrary: 'react-native' });
```

The `react` value is the alternative, and you can still override it in an individual test file.

## The file name is what makes Jest find your performance tests

Performance tests live in files with a .perf-test.js or .perf-test.tsx extension, and Jest discovers them through the standard testMatch option rather than a separate command. The default patterns are a __perf__ directory or a filename containing .perf or perf-test before the extension, and the README tells you how to deviate: if you pass a custom testMatch or testRegex, you may add it to the reassure measure script so your own glob is used. That detail is the escape hatch for teams whose Jest configuration is unusual, and it is the first thing to check if your perf tests appear to be skipped. The library also ships a measure script, referenced as reassure measure, which is what the CI step invokes.

## measureRenders covers mounting, and the scenario option covers the rest

The first test is short:

```ts
// ComponentUnderTest.perf-test.tsx
import { measureRenders } from 'reassure';
import { ComponentUnderTest } from './ComponentUnderTest';

test('Simple test', async () => {
  await measureRenders(<ComponentUnderTest />);
});
```

That measures render times of the component during mounting and the resulting synchronous effects. If your component has async logic, or you want to test an interaction, you pass the scenario option instead, and the example imports screen and fireEvent from the testing library and drives the component the way a user would. That distinction matters more than it looks: mounting only catches the initial render cost, while a scenario catches the cost of the update that actually regressed. The API also covers plain JavaScript: measureFunction and measureAsyncFunction measure execution of ordinary functions, each with its own options type, so a utility function that got slower is testable in the same suite as a screen.

## Configuration is a configure call plus a reset

Beyond the testing library choice, configuration is documented as a default configuration, a configure function and a resetToDefaults function, and the README also lists environmental variables as a configuration route. That is a small surface, which is appropriate: the defaults are meant to work. The reset function exists because configuration is global, and in a monorepo with several apps you want a way back rather than an accumulating set of overrides. The docs site under docs/ in the repository, published as a Docusaurus site, is where the full option list lives, including the options types for each measurement function. Configuration in the Jest setup file is the placement the README recommends for the testing library choice, which keeps the override global by default and local when a file needs to differ.

## Danger is how the report reaches the pull request

The reporting path is the part that determines whether anyone looks at the numbers. The root of the repository contains dangerfile.ts, and the README documents a CI script named reassure-tests.sh alongside instructions for scaffolding, creating and updating a Dangerfile and updating the CI configuration file. Danger posts the report as a comment on the pull request, so the reviewer sees the render comparison in the same place they see the diff. The repository also has test-apps/ wired into the workspace configuration, with the root package.json listing packages/* and test-apps/native as workspaces, so the library is exercised against a real app during its own tests. Scripts run through turbo, validate chains lint, dependency version consistency, typecheck and test, and releases go through changesets.

## Against a profiler or snapshot assertions on rendered output

The alternative tools answer different questions. A profiler tells you where the time went on one machine on one run, which is exactly what you need while diagnosing and useless as a regression gate, because the numbers move with the machine and there is nothing to compare against. Snapshot assertions tell you whether the output changed, not whether it got slower, and they cannot distinguish a necessary render from an accidental one. Reassure sits after the profiling stage: you have already fixed what you can measure, and now you want a gate. The cost is that the gate is statistical, so it needs a stable baseline and a stable runner, which is why the documentation includes a section on assessing CI stability. If your CI machine is shared and noisy, this tool will tell you about the machine.

## Conclusion

Reassure fits a team with React Native or React tests already in Jest, because it reuses the same React Native Testing Library or React Testing Library setup and adds perf-test files beside the existing ones, so the cost of starting is a dev dependency and a CI step rather than a new harness. Skip it if your app is not React based, and think carefully about a shared CI machine, since the tool works by repeating a scenario to reduce environmental noise and a noisy runner produces false significance. Before enabling it in CI, run the measure script locally until the baseline is stable and read the assessing CI stability section, because a regression test that fails on noise gets disabled within a week. The newest release is 1.6.0 from 2026-07-22, the licence is MIT, and the docs are a Docusaurus site under docs/ in the repository.

## FAQ

### How do I install Reassure and write a performance test?

Install it as a development dependency with yarn add --dev reassure or npm install --save-dev reassure, alongside a working Jest setup and either React Native Testing Library or React Testing Library. Then create a file with a .perf-test.js or .perf-test.tsx extension and call await measureRenders(<YourComponent />) inside a Jest test.

### How does Reassure decide if a performance change is significant?

It measures render duration and count for the scenario, repeats the scenario multiple times to reduce random variation from the runtime environment, compares against a stable version and applies statistical analysis. The report is shown on CI or posted to the pull request.

### Can Reassure measure something other than component renders?

Yes. Alongside measureRenders with its options type, the API includes measureFunction and measureAsyncFunction with their own options types, so ordinary JavaScript function execution can be measured in the same suite.

## Sources

- [callstack/reassure on GitHub](https://github.com/callstack/reassure)
- [License: MIT](https://github.com/callstack/reassure/blob/main/LICENSE)
- [Project website](https://callstack.github.io/reassure/)
- [README](https://github.com/callstack/reassure/blob/main/README.md)
- [Releases](https://github.com/callstack/reassure/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/callstack-reassure
