From c5bb31c46ea992f451bac6c76bf902582b8b119d Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 25 Jul 2025 08:53:45 -0700 Subject: [PATCH] Add 'testWithArg' to Fantom benchmarking API (#52831) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52831 # Changelog [Internal] - The corresponding `testWithArg` API is similar to the existing `test` one for the Fantom benchmarks, except it would allow to run the same test several times in a parametrized manner, with the set of parameters specified as an array (for now, of numbers). This allows to easily implement testing patterns such as we have in a View benchmark test, whereas we have a mostly duplicated test body doing a similar thing with 100, 1000, 1500 view component instances etc. Reviewed By: rubennorte Differential Revision: D78970312 fbshipit-source-id: 504b7aada648c7213ce698f088ac71d9fde8884b --- private/react-native-fantom/src/Benchmark.js | 74 ++++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/private/react-native-fantom/src/Benchmark.js b/private/react-native-fantom/src/Benchmark.js index fe352f7fa65..ae7c5fb78e3 100644 --- a/private/react-native-fantom/src/Benchmark.js +++ b/private/react-native-fantom/src/Benchmark.js @@ -35,9 +35,32 @@ type TestOptions = $ReadOnly<{ type SuiteResults = Array<$ReadOnly>; +type TestWithArgName = string | ((testArg: TestArgType) => string); + +type TestWithArgOptions = + | FnOptions + | ((testArg: TestArgType) => FnOptions); + +interface ParameterizedTestFunction { + ( + testArgs: $ReadOnlyArray, + name: TestWithArgName, + fn: (testArg: TestArgType) => void, + options?: TestWithArgOptions, + ): SuiteAPI; + only: ( + testArgs: $ReadOnlyArray, + name: TestWithArgName, + fn: (testArg: TestArgType) => void, + options?: TestWithArgOptions, + ) => SuiteAPI; +} + interface TestFunction { (name: string, fn: () => void, options?: FnOptions): SuiteAPI; only: (name: string, fn: () => void, options?: FnOptions) => SuiteAPI; + // `each` allows to run the same test multiple times with different arguments, provided as an array of values: + each: ParameterizedTestFunction; } interface SuiteAPI { @@ -45,15 +68,17 @@ interface SuiteAPI { verify(fn: (results: SuiteResults) => void): SuiteAPI; } +interface TestTask { + name: string; + fn: () => void; + options: TestOptions | void; +} + export function suite( suiteName: string, suiteOptions?: SuiteOptions = {}, ): SuiteAPI { - const tasks: Array<{ - name: string, - fn: () => void, - options: TestOptions | void, - }> = []; + const tasks: Array = []; const verifyFns = []; global.it(suiteName, () => { @@ -165,6 +190,45 @@ export function suite( return suiteAPI; }; + const testWithArg = ( + testArg: TestArgType, + name: TestWithArgName, + fn: (testArg: TestArgType) => void, + options?: TestWithArgOptions, + only?: boolean = false, + ): TestTask => { + const taskName = + typeof name === 'function' + ? name(testArg) + : `${name} [arg=${String(testArg)}]`; + const taskOptions = + typeof options === 'function' ? options(testArg) : options; + const taskFn = () => fn(testArg); + return {name: taskName, fn: taskFn, options: {...taskOptions, only}}; + }; + + // $FlowIssue[incompatible-type] + const testEach: ParameterizedTestFunction = ( + testArgs: $ReadOnlyArray, + name: TestWithArgName, + fn: (testArg: TestArgType) => void, + options?: TestWithArgOptions, + ): SuiteAPI => { + for (const testArg of testArgs) { + tasks.push(testWithArg(testArg, name, fn, options)); + } + return suiteAPI; + }; + + testEach.only = (testArgs, name, fn, options) => { + for (const testArg of testArgs) { + tasks.push(testWithArg(testArg, name, fn, options, true)); + } + return suiteAPI; + }; + + test.each = testEach; + const suiteAPI = { test, verify(fn: (results: SuiteResults) => void): SuiteAPI {