-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathmeasure.ts
147 lines (127 loc) · 4.8 KB
/
measure.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import { mkdirSync, rmSync, existsSync, writeFileSync } from 'fs';
import { resolve } from 'path';
import { spawnSync } from 'child_process';
import type { CommandModule } from 'yargs';
import { compare, formatMetadata } from '@callstack/reassure-compare';
import type { PerformanceMetadata } from '@callstack/reassure-compare';
import { logger } from '@callstack/reassure-logger';
import { applyCommonOptions, CommonOptions } from '../options';
import { getGitBranch, getGitCommitHash } from '../utils/git';
import { configureLoggerOptions } from '../utils/logger';
const RESULTS_DIRECTORY = '.reassure';
const RESULTS_FILE = '.reassure/current.perf';
const BASELINE_FILE = '.reassure/baseline.perf';
interface MeasureOptions extends CommonOptions {
baseline?: boolean;
compare?: boolean;
branch?: string;
commitHash?: string;
testMatch?: string;
}
export async function run(options: MeasureOptions) {
configureLoggerOptions(options);
const measurementType = options.baseline ? 'Baseline' : 'Current';
const metadata: PerformanceMetadata = {
branch: options?.branch ?? (await getGitBranch()),
commitHash: options?.commitHash ?? (await getGitCommitHash()),
};
logger.log(`\n❇️ Running performance tests:`);
logger.log(` - ${measurementType}: ${formatMetadata(metadata)}\n`);
mkdirSync(RESULTS_DIRECTORY, { recursive: true });
const outputFile = options.baseline ? BASELINE_FILE : RESULTS_FILE;
rmSync(outputFile, { force: true });
const header = { metadata };
writeFileSync(outputFile, JSON.stringify(header) + '\n');
const defaultPath = process.platform === 'win32' ? 'node_modules/jest/bin/jest' : 'node_modules/.bin/jest';
const testRunnerPath = process.env.TEST_RUNNER_PATH ?? defaultPath;
// NOTE: Consider updating the default testMatch to better reflect
// default patterns used in Jest and allow users to also place their
// performance tests into specific /__perf__/ directory without the need
// of adding the *.perf-test. prefix
// ---
// [ **/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)" ]
// ---
// GH: https://github.com/callstack/reassure/issues/363
const defaultTestMatch = '**/*.perf-test.[jt]s?(x)';
const testMatch = options.testMatch || defaultTestMatch;
const defaultArgs = `--runInBand --testMatch "<rootDir>/${testMatch}"`;
const testRunnerArgs = process.env.TEST_RUNNER_ARGS ?? defaultArgs;
const nodeArgs = [
'--jitless',
'--expose-gc',
'--no-concurrent-sweeping',
'--max-old-space-size=4096',
testRunnerPath,
testRunnerArgs,
];
logger.verbose('Running tests using command:');
logger.verbose(`$ node ${nodeArgs.join(' \\\n ')}\n`);
const spawnInfo = spawnSync('node', nodeArgs, {
shell: true,
stdio: 'inherit',
env: {
...process.env,
REASSURE_OUTPUT_FILE: outputFile,
REASSURE_SILENT: options.silent.toString(),
REASSURE_VERBOSE: options.verbose.toString(),
},
});
logger.log();
if (spawnInfo.status !== 0) {
logger.error(`❌ Test runner (${testRunnerPath}) exited with error code ${spawnInfo.status}`);
process.exitCode = 1;
return;
}
if (existsSync(outputFile)) {
logger.log(`✅ Written ${measurementType} performance measurements to ${outputFile}`);
logger.log(`🔗 ${resolve(outputFile)}\n`);
} else {
logger.error(`❌ Something went wrong, ${measurementType} performance file (${outputFile}) does not exist\n`);
return;
}
if (options.baseline) {
logger.log("Hint: You can now run 'reassure' to measure & compare performance against modified code.\n");
return;
}
if (options.compare) {
if (existsSync(BASELINE_FILE)) {
compare();
} else {
logger.log(
`Baseline performance file does not exist, run 'reassure --baseline' on your baseline code branch to create it.\n`
);
return;
}
}
}
export const command: CommandModule<{}, MeasureOptions> = {
command: ['measure', '$0'],
describe: 'Gather performance measurements by running performance tests',
builder: (yargs) => {
return applyCommonOptions(yargs)
.option('baseline', {
type: 'boolean',
default: false,
describe: 'Save measurements as baseline instead of current',
})
.option('compare', {
type: 'boolean',
default: true,
describe: 'Outputs performance comparison results',
})
.option('branch', {
type: 'string',
describe: 'Branch name of current code to be included in the report',
})
.option('commit-hash', {
type: 'string',
describe: 'Commit hash of current code to be included in the report',
})
.option('testMatch', {
type: 'string',
default: undefined,
describe: 'Run performance tests for a specific test file',
});
},
handler: (args) => run(args),
};