Skip to content

Commit 92ebbb8

Browse files
committed
feat: add slowest tests report with average duration
1 parent 4533456 commit 92ebbb8

File tree

15 files changed

+177
-16
lines changed

15 files changed

+177
-16
lines changed

.github/workflows/build-and-test.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ jobs:
198198
flaky-rate-report: true
199199
fail-rate-report: true
200200
insights-report: true
201+
slowest-report: true
201202
annotate: false
202203
env:
203204
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

action.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ inputs:
7979
'Include the insights report showing test metrics and statistics.'
8080
required: false
8181
default: false
82+
slowest-report:
83+
description:
84+
'Include a report showing the top 10 slowest tests by average duration.'
85+
required: false
86+
default: false
8287
pull-request-report:
8388
description: 'Include the pull request report.'
8489
required: false

badges/coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

dist/index.js

Lines changed: 68 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/reports/insights-table.hbs

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/reports/slowest-table.hbs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/inputs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export function getCliInputs(args: Arguments): Inputs {
3131
customReport: args._.includes('custom'),
3232
communityReport: args._.includes('community'),
3333
insightsReport: args._.includes('insights'),
34+
slowestReport: args._.includes('slowest'),
3435
communityReportName: args.communityReportName || '',
3536
artifactName: args.artifactName || 'ctrf-report',
3637
annotate: args.annotate !== false,
@@ -87,6 +88,7 @@ export function getInputs(): Inputs {
8788
core.getInput('pull-request-report').toLowerCase() === 'true',
8889
commitReport: core.getInput('commit-report').toLowerCase() === 'true',
8990
insightsReport: core.getInput('insights-report').toLowerCase() === 'true',
91+
slowestReport: core.getInput('slowest-report').toLowerCase() === 'true',
9092
customReport: core.getInput('custom-report').toLowerCase() === 'true',
9193
communityReport: core.getInput('community-report').toLowerCase() === 'true',
9294
communityReportName: core.getInput('community-report-name'),

src/ctrf/enrichers.ts

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ function findSlowestTestByP95(
188188
): { name: string; duration: number } | undefined {
189189
if (!tests.length) return undefined
190190

191-
// Group tests by name to handle multiple runs of the same test
192191
const testGroups = tests.reduce(
193192
(groups, test) => {
194193
const name = test.name
@@ -201,20 +200,84 @@ function findSlowestTestByP95(
201200
{} as Record<string, number[]>
202201
)
203202

204-
// Calculate p95 duration for each test
205203
const testP95Durations = Object.entries(testGroups).map(
206204
([name, durations]) => ({
207205
name,
208206
duration: calculateP95Duration(durations)
209207
})
210208
)
211209

212-
// Find the test with the highest p95 duration
213210
return testP95Durations.reduce((slowest, current) => {
214211
return current.duration > slowest.duration ? current : slowest
215212
}, testP95Durations[0])
216213
}
217214

215+
/**
216+
* Calculates the average duration for each test across all runs and sorts them.
217+
* Returns only the top 10 slowest tests.
218+
*
219+
* @param tests - Array of tests to analyze
220+
* @param previousReports - Array of previous reports
221+
* @returns Array of tests with average durations, sorted by duration
222+
*/
223+
function calculateAndSortTestDurations(
224+
tests: CtrfTest[],
225+
previousReports: CtrfReport[]
226+
): CtrfTest[] {
227+
const testDurations: Record<string, number[]> = {}
228+
229+
tests.forEach(test => {
230+
if (!testDurations[test.name]) {
231+
testDurations[test.name] = []
232+
}
233+
if (test.duration) {
234+
testDurations[test.name].push(test.duration)
235+
}
236+
})
237+
238+
previousReports.forEach(report => {
239+
report.results.tests.forEach(test => {
240+
if (!testDurations[test.name]) {
241+
testDurations[test.name] = []
242+
}
243+
if (test.duration) {
244+
testDurations[test.name].push(test.duration)
245+
}
246+
})
247+
})
248+
249+
const testsWithAvg = tests.map(test => {
250+
const durations = testDurations[test.name] || []
251+
if (durations.length > 0) {
252+
const currentExtra = test.extra || {
253+
totalAttempts: 0,
254+
flakyRate: 0,
255+
flakyRateChange: 0,
256+
passedCount: 0,
257+
failedCount: 0,
258+
failRate: 0,
259+
failRateChange: 0,
260+
finalResults: 0,
261+
finalFailures: 0
262+
}
263+
test.extra = {
264+
...currentExtra,
265+
avgDuration: calculateP95Duration(durations)
266+
}
267+
}
268+
return test
269+
})
270+
271+
return testsWithAvg
272+
.filter(test => test.extra?.avgDuration !== undefined)
273+
.sort((a, b) => {
274+
const aDuration = a.extra?.avgDuration || 0
275+
const bDuration = b.extra?.avgDuration || 0
276+
return bDuration - aDuration
277+
})
278+
.slice(0, 10)
279+
}
280+
218281
/**
219282
* Enriches the CTRF report summary with overall metrics, including flaky and fail rates.
220283
*
@@ -282,6 +345,11 @@ export function enrichReportSummary(
282345
)
283346
const slowestTest = findSlowestTestByP95(report.results.tests)
284347

348+
report.results.tests = calculateAndSortTestDurations(
349+
report.results.tests,
350+
previousReports
351+
)
352+
285353
report.results.summary.extra = {
286354
...(report.results.summary.extra || {}),
287355
flakyRate,

src/github/core.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,12 @@ export function generateViews(inputs: Inputs, report: CtrfReport): void {
108108

109109
if (inputs.insightsReport) {
110110
core.info('Adding insights report to summary')
111-
addViewToSummary('', BuiltInReports.InsightsTable, report)
111+
addViewToSummary('### Insights', BuiltInReports.InsightsTable, report)
112+
}
113+
114+
if (inputs.slowestReport) {
115+
core.info('Adding slowest tests report to summary')
116+
addViewToSummary('### Slowest Tests', BuiltInReports.SlowestTable, report)
112117
}
113118

114119
if (inputs.customReport && inputs.templatePath) {

0 commit comments

Comments
 (0)