diff --git a/packages/reassure-measure/src/__tests__/measure-function.test.tsx b/packages/reassure-measure/src/__tests__/measure-function.test.tsx
index ade058e3..47e48046 100644
--- a/packages/reassure-measure/src/__tests__/measure-function.test.tsx
+++ b/packages/reassure-measure/src/__tests__/measure-function.test.tsx
@@ -41,3 +41,15 @@ test('measureFunctionInternal applies dropsWorst option', () => {
expect(results.meanCount).toBe(1);
expect(results.stdevCount).toBe(0);
});
+
+test('measureFunctionInternal supports "runs: quick-3" option', () => {
+ const fn = jest.fn(() => fib(5));
+ const results = measureFunctionInternal(fn, { runs: 'quick-3', warmupRuns: 1 });
+
+ expect(fn).toHaveBeenCalledTimes(4);
+ expect(results.runs).toBe(6);
+ expect(results.durations).toHaveLength(6);
+ expect(results.counts).toHaveLength(6);
+ expect(results.meanCount).toBe(1);
+ expect(results.stdevCount).toBe(0);
+});
diff --git a/packages/reassure-measure/src/__tests__/measure-helpers.test.ts b/packages/reassure-measure/src/__tests__/measure-helpers.test.ts
index 714e5ac5..63cd8f8b 100644
--- a/packages/reassure-measure/src/__tests__/measure-helpers.test.ts
+++ b/packages/reassure-measure/src/__tests__/measure-helpers.test.ts
@@ -7,7 +7,7 @@ test('processRunResults calculates correct means and stdevs', () => {
{ duration: 14, count: 2 },
];
- expect(processRunResults(input, 0)).toEqual({
+ expect(processRunResults(input, 3, 0)).toEqual({
runs: 3,
meanDuration: 12,
stdevDuration: 2,
@@ -20,13 +20,13 @@ test('processRunResults calculates correct means and stdevs', () => {
test('processRunResults applies warmupRuns option', () => {
const input = [
- { duration: 23, count: 1 },
+ { duration: 23, count: 1 }, // warmup run
{ duration: 20, count: 5 },
{ duration: 24, count: 5 },
{ duration: 22, count: 5 },
];
- expect(processRunResults(input, 1)).toEqual({
+ expect(processRunResults(input, 4, 1)).toEqual({
runs: 3,
meanDuration: 22,
stdevDuration: 2,
@@ -36,3 +36,22 @@ test('processRunResults applies warmupRuns option', () => {
counts: [5, 5, 5],
});
});
+
+test('processRunResults supports "runs: quick-3" option', () => {
+ const input = [
+ { duration: 100, count: 1 }, // warmup run
+ { duration: 1, count: 5 },
+ { duration: 6, count: 5 },
+ { duration: 29, count: 5 },
+ ];
+
+ expect(processRunResults(input, 'quick-3', 1)).toEqual({
+ runs: 6,
+ meanDuration: 9,
+ stdevDuration: 10,
+ durations: [29, 6, 6, 6, 6, 1],
+ meanCount: 5,
+ stdevCount: 0,
+ counts: [5, 5, 5, 5, 5, 5],
+ });
+});
diff --git a/packages/reassure-measure/src/__tests__/measure-render.test.tsx b/packages/reassure-measure/src/__tests__/measure-render.test.tsx
index a51c68b3..69a3ff9b 100644
--- a/packages/reassure-measure/src/__tests__/measure-render.test.tsx
+++ b/packages/reassure-measure/src/__tests__/measure-render.test.tsx
@@ -89,3 +89,27 @@ test('buildUiToRender does not wrap when no wrapper is passed', () => {
`);
});
+
+test('measureRender applies dropsWorst option', async () => {
+ const scenario = jest.fn(() => Promise.resolve(null));
+ const results = await measureRender(, { runs: 10, warmupRuns: 1, scenario });
+
+ expect(scenario).toHaveBeenCalledTimes(11);
+ expect(results.runs).toBe(10);
+ expect(results.durations).toHaveLength(10);
+ expect(results.counts).toHaveLength(10);
+ expect(results.meanCount).toBe(1);
+ expect(results.stdevCount).toBe(0);
+});
+
+test('measureRender supports "runs: quick-3" option', async () => {
+ const scenario = jest.fn(() => Promise.resolve(null));
+ const results = await measureRender(, { runs: 'quick-3', warmupRuns: 1, scenario });
+
+ expect(scenario).toHaveBeenCalledTimes(4);
+ expect(results.runs).toBe(6);
+ expect(results.durations).toHaveLength(6);
+ expect(results.counts).toHaveLength(6);
+ expect(results.meanCount).toBe(1);
+ expect(results.stdevCount).toBe(0);
+});
diff --git a/packages/reassure-measure/src/config.ts b/packages/reassure-measure/src/config.ts
index 88f91890..ceb030ca 100644
--- a/packages/reassure-measure/src/config.ts
+++ b/packages/reassure-measure/src/config.ts
@@ -4,7 +4,7 @@ export type Render = (component: React.ReactElement) => any;
export type Cleanup = () => void;
type Config = {
- runs: number;
+ runs: number | 'quick-3';
warmupRuns: number;
outputFile: string;
testingLibrary?: TestingLibrary;
diff --git a/packages/reassure-measure/src/measure-function.tsx b/packages/reassure-measure/src/measure-function.tsx
index 15a59b7a..7f4f89c2 100644
--- a/packages/reassure-measure/src/measure-function.tsx
+++ b/packages/reassure-measure/src/measure-function.tsx
@@ -5,7 +5,7 @@ import { type RunResult, processRunResults } from './measure-helpers';
import { showFlagsOuputIfNeeded, writeTestStats } from './output';
interface MeasureFunctionOptions {
- runs?: number;
+ runs?: number | 'quick-3';
warmupRuns?: number;
}
@@ -18,12 +18,13 @@ export async function measureFunction(fn: () => void, options?: MeasureFunctionO
export function measureFunctionInternal(fn: () => void, options?: MeasureFunctionOptions): MeasureResults {
const runs = options?.runs ?? config.runs;
+ const runCount = runs === 'quick-3' ? 3 : runs;
const warmupRuns = options?.warmupRuns ?? config.warmupRuns;
showFlagsOuputIfNeeded();
const runResults: RunResult[] = [];
- for (let i = 0; i < runs + warmupRuns; i += 1) {
+ for (let i = 0; i < runCount + warmupRuns; i += 1) {
const timeStart = getCurrentTime();
fn();
const timeEnd = getCurrentTime();
@@ -32,7 +33,7 @@ export function measureFunctionInternal(fn: () => void, options?: MeasureFunctio
runResults.push({ duration, count: 1 });
}
- return processRunResults(runResults, warmupRuns);
+ return processRunResults(runResults, runs, warmupRuns);
}
function getCurrentTime() {
diff --git a/packages/reassure-measure/src/measure-helpers.tsx b/packages/reassure-measure/src/measure-helpers.tsx
index 8713cf60..97c12367 100644
--- a/packages/reassure-measure/src/measure-helpers.tsx
+++ b/packages/reassure-measure/src/measure-helpers.tsx
@@ -6,10 +6,15 @@ export interface RunResult {
count: number;
}
-export function processRunResults(results: RunResult[], warmupRuns: number): MeasureResults {
+export function processRunResults(results: RunResult[], runs: number | 'quick-3', warmupRuns: number): MeasureResults {
results = results.slice(warmupRuns);
+
results.sort((first, second) => second.duration - first.duration); // duration DESC
+ if (runs === 'quick-3') {
+ results = [results[0], results[1], results[1], results[1], results[1], results[2]];
+ }
+
const durations = results.map((result) => result.duration);
const meanDuration = math.mean(durations) as number;
const stdevDuration = math.std(...durations);
diff --git a/packages/reassure-measure/src/measure-render.tsx b/packages/reassure-measure/src/measure-render.tsx
index e9b56c47..b25afe9f 100644
--- a/packages/reassure-measure/src/measure-render.tsx
+++ b/packages/reassure-measure/src/measure-render.tsx
@@ -12,7 +12,7 @@ logger.configure({
});
export interface MeasureOptions {
- runs?: number;
+ runs?: number | 'quick-3';
warmupRuns?: number;
wrapper?: React.ComponentType<{ children: React.ReactElement }>;
scenario?: (screen: any) => Promise;
@@ -27,6 +27,8 @@ export async function measurePerformance(ui: React.ReactElement, options?: Measu
export async function measureRender(ui: React.ReactElement, options?: MeasureOptions): Promise {
const runs = options?.runs ?? config.runs;
+ const runCount = runs === 'quick-3' ? 3 : runs;
+
const scenario = options?.scenario;
const warmupRuns = options?.warmupRuns ?? config.warmupRuns;
@@ -36,7 +38,7 @@ export async function measureRender(ui: React.ReactElement, options?: MeasureOpt
const runResults: RunResult[] = [];
let hasTooLateRender = false;
- for (let i = 0; i < runs + warmupRuns; i += 1) {
+ for (let i = 0; i < runCount + warmupRuns; i += 1) {
let duration = 0;
let count = 0;
let isFinished = false;
@@ -72,7 +74,7 @@ export async function measureRender(ui: React.ReactElement, options?: MeasureOpt
);
}
- return processRunResults(runResults, warmupRuns);
+ return processRunResults(runResults, runs, warmupRuns);
}
export function buildUiToRender(
diff --git a/test-apps/native/src/OtherTest.perf-test.tsx b/test-apps/native/src/OtherTest.perf-test.tsx
index bf3b09fe..d3729f8a 100644
--- a/test-apps/native/src/OtherTest.perf-test.tsx
+++ b/test-apps/native/src/OtherTest.perf-test.tsx
@@ -1,7 +1,9 @@
import React from 'react';
import { View, Text, Pressable } from 'react-native';
import { fireEvent, RenderAPI, screen } from '@testing-library/react-native';
-import { measurePerformance } from 'reassure';
+import { measurePerformance, configure } from 'reassure';
+
+configure({ runs: 'quick-3' });
import { SlowList } from './SlowList';
diff --git a/test-apps/native/src/SlowList.perf-test.tsx b/test-apps/native/src/SlowList.perf-test.tsx
index ddb4d15a..0986a15d 100644
--- a/test-apps/native/src/SlowList.perf-test.tsx
+++ b/test-apps/native/src/SlowList.perf-test.tsx
@@ -1,9 +1,11 @@
import * as React from 'react';
import { View, Text, Pressable } from 'react-native';
import { fireEvent, screen } from '@testing-library/react-native';
-import { measurePerformance } from 'reassure';
+import { measurePerformance, configure } from 'reassure';
import { SlowList } from './SlowList';
+configure({ runs: 'quick-3' });
+
const AsyncComponent = () => {
const [count, setCount] = React.useState(0);
diff --git a/test-apps/native/src/fib.perf-test.tsx b/test-apps/native/src/fib.perf-test.tsx
index 42480e0c..61023524 100644
--- a/test-apps/native/src/fib.perf-test.tsx
+++ b/test-apps/native/src/fib.perf-test.tsx
@@ -1,4 +1,6 @@
-import { measureFunction } from '@callstack/reassure-measure';
+import { configure, measureFunction } from '@callstack/reassure-measure';
+
+configure({ runs: 'quick-3' });
function fib(n: number): number {
if (n <= 1) {