Skip to content

Commit 724a965

Browse files
Merge pull request #1221 from gemini-testing/TESTPLANE-938.selectivity_report
feat(selectivity): add ability to save selectivity report
2 parents 1fe8eae + 7fe48ae commit 724a965

File tree

4 files changed

+332
-0
lines changed

4 files changed

+332
-0
lines changed

src/browser/cdp/selectivity/runner.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import _ from "lodash";
2+
import fs from "fs-extra";
23
import pLimit from "p-limit";
4+
import * as logger from "../../../utils/logger";
35
import type { Config } from "../../../config";
46
import type { BrowserConfig } from "../../../config/browser-config";
57
import type { MainRunner } from "../../../runner";
@@ -115,6 +117,17 @@ interface SelectivityRunnerOptions {
115117
shouldDisableSelectivity?: boolean;
116118
}
117119

120+
interface SelectivityBrowserStats {
121+
processedCount: number;
122+
skippedCount: number;
123+
}
124+
125+
interface SelectivityReport {
126+
totalProcessedCount: number;
127+
totalSkippedCount: number;
128+
perBrowserStats: Record<string, SelectivityBrowserStats>;
129+
}
130+
118131
export class SelectivityRunner {
119132
private readonly _config: Config;
120133
private readonly _runTestFn: (test: Test, browserId: string) => void;
@@ -123,6 +136,7 @@ export class SelectivityRunner {
123136
private readonly _testsToRun: [Test, string][] = [];
124137
private readonly _processingTestLimit = pLimit(16);
125138
private readonly _processingTestPromises: Array<Promise<void>> = [];
139+
private readonly _stats: Record<string, SelectivityBrowserStats> = {};
126140

127141
static create(...args: ConstructorParameters<typeof this>): SelectivityRunner {
128142
return new this(...args);
@@ -177,10 +191,19 @@ export class SelectivityRunner {
177191
return;
178192
}
179193

194+
this._stats[browserId] ||= {
195+
processedCount: 0,
196+
skippedCount: 0,
197+
};
198+
199+
this._stats[browserId].processedCount++;
200+
180201
const shouldDisableTest = await shouldDisableTestBySelectivity(browserConfig, test);
181202

182203
if (!shouldDisableTest) {
183204
this._testsToRun.push([test, browserId]);
205+
} else {
206+
this._stats[browserId].skippedCount++;
184207
}
185208
}),
186209
);
@@ -189,6 +212,10 @@ export class SelectivityRunner {
189212
async runNecessaryTests(): Promise<void> {
190213
await Promise.all(this._processingTestPromises);
191214

215+
const saveReportPromise = this._saveSelectivityReport().catch(reason => {
216+
logger.error("Couldn't save selectivity report. Reason:", reason);
217+
});
218+
192219
this._testsToRun.forEach(([test, browserId]) => {
193220
this._runTestFn(test, browserId);
194221
});
@@ -204,5 +231,46 @@ export class SelectivityRunner {
204231

205232
getHashReader(selectivity.testDependenciesPath, selectivity.compression).clearCache();
206233
});
234+
235+
await saveReportPromise;
236+
}
237+
238+
async _saveSelectivityReport(): Promise<void> {
239+
const browserReportPaths = Object.keys(this._stats).reduce((acc, browserId) => {
240+
const reportPath =
241+
process.env.TESTPLANE_SELECTIVITY_REPORT_PATH ||
242+
this._config.forBrowser(browserId).selectivity.reportPath;
243+
244+
if (reportPath) {
245+
acc[reportPath] ||= [];
246+
acc[reportPath].push(browserId);
247+
}
248+
249+
return acc;
250+
}, {} as Record<string, string[]>);
251+
252+
const promises = await Promise.allSettled(
253+
Object.keys(browserReportPaths).map(async reportPath => {
254+
const report: SelectivityReport = {
255+
totalProcessedCount: 0,
256+
totalSkippedCount: 0,
257+
perBrowserStats: {},
258+
};
259+
260+
for (const browserId of browserReportPaths[reportPath]) {
261+
report.totalProcessedCount += this._stats[browserId].processedCount;
262+
report.totalSkippedCount += this._stats[browserId].skippedCount;
263+
report.perBrowserStats[browserId] = this._stats[browserId];
264+
}
265+
266+
await fs.outputJson(reportPath, report, { spaces: 4 });
267+
}),
268+
);
269+
270+
const failedPromise = promises.find(promise => promise.status === "rejected");
271+
272+
if (failedPromise && "reason" in failedPromise) {
273+
throw failedPromise.reason;
274+
}
207275
}
208276
}

src/config/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ module.exports = {
136136
compression: "gz",
137137
disableSelectivityPatterns: [],
138138
mapDependencyRelativePath: null,
139+
reportPath: "",
139140
},
140141
};
141142

src/config/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ export interface CommonConfig {
411411
compression: SelectivityCompressionType;
412412
disableSelectivityPatterns: string[];
413413
mapDependencyRelativePath: null | SelectivityMapDependencyRelativePathFn;
414+
reportPath: string;
414415
};
415416

416417
timeTravel: TimeTravelConfig;

0 commit comments

Comments
 (0)