Skip to content

Commit

Permalink
Merge pull request #38 from SonicGarden/kzkn-20241223
Browse files Browse the repository at this point in the history
[review] feat: Reporting top N slowest examples
  • Loading branch information
aki77 authored Dec 24, 2024
2 parents dd93155 + 4ddc955 commit 34294b5
Show file tree
Hide file tree
Showing 18 changed files with 497 additions and 9 deletions.
76 changes: 75 additions & 1 deletion __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test('Parse multiple rspec json results', async () => {
path.resolve(__dirname, '../.dummy_results-*.json')
)
await run()

expect(reportSummary).toHaveBeenCalledWith({
examples: [
{
Expand All @@ -25,6 +26,79 @@ test('Parse multiple rspec json results', async () => {
}
],
success: false,
summary: '27 examples, 1 failure, 1 pending'
summary: '27 examples, 1 failure, 1 pending',
totalTime: 0.35526800000000003,
slowExamples: [
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 11,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq true',
runTime: 0.044519
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 11,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq true',
runTime: 0.044519
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 37,
description:
'ActiveRecord::Validations::BlobValidator with size_range option 1.4MB is expected to eq true',
runTime: 0.038474
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 10,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq false',
runTime: 0.016242
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 10,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq false',
runTime: 0.016242
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 36,
description:
'ActiveRecord::Validations::BlobValidator with size_range option 1.4MB is expected to eq false',
runTime: 0.015013
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 39,
description:
"ActiveRecord::Validations::BlobValidator with size_range option 1.4MB should translate the validation error according to it's locale",
runTime: 0.015001
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 80,
description:
'ActiveRecord::Validations::BlobValidator with content_type option symbol is expected to eq true',
runTime: 0.011655
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 54,
description:
'ActiveRecord::Validations::BlobValidator with content_type option regexp is expected to eq true',
runTime: 0.009849
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 68,
description:
'ActiveRecord::Validations::BlobValidator with content_type option array is expected to eq false',
runTime: 0.00981
}
]
})
})
75 changes: 74 additions & 1 deletion __tests__/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,79 @@ test('Parse rspec result json', async () => {
message: '\\nexpected: true\\n got: false\\n\\n(compared using ==)'
}
],
success: false
success: false,
totalTime: 0.294507,
slowExamples: [
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 11,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq true',
runTime: 0.044519
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 37,
description:
'ActiveRecord::Validations::BlobValidator with size_range option 1.4MB is expected to eq true',
runTime: 0.038474
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 10,
description:
'ActiveRecord::Validations::BlobValidator presence: true has_one_attached is expected to eq false',
runTime: 0.016242
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 36,
description:
'ActiveRecord::Validations::BlobValidator with size_range option 1.4MB is expected to eq false',
runTime: 0.015013
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 39,
description:
"ActiveRecord::Validations::BlobValidator with size_range option 1.4MB should translate the validation error according to it's locale",
runTime: 0.015001
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 80,
description:
'ActiveRecord::Validations::BlobValidator with content_type option symbol is expected to eq true',
runTime: 0.011655
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 54,
description:
'ActiveRecord::Validations::BlobValidator with content_type option regexp is expected to eq true',
runTime: 0.009849
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 68,
description:
'ActiveRecord::Validations::BlobValidator with content_type option array is expected to eq false',
runTime: 0.00981
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 71,
description:
'ActiveRecord::Validations::BlobValidator with content_type option array is expected to eq false',
runTime: 0.009572
},
{
filePath: 'spec/activestorage/validator/blob_spec.rb',
lineNumber: 55,
description:
'ActiveRecord::Validations::BlobValidator with content_type option regexp is expected to eq false',
runTime: 0.009186
}
]
})
})
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ inputs:
description: "Set this if want to comment report to pull request"
default: "true"
required: false
profileTitle:
description: "Title for profile"
default: "# Slowest examples"
required: false
runs:
using: "node20"
main: "dist/index.js"
124 changes: 123 additions & 1 deletion dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39139,6 +39139,7 @@ const fast_glob_1 = __importDefault(__nccwpck_require__(6581));
const parse_1 = __nccwpck_require__(1539);
const report_summary_1 = __nccwpck_require__(4353);
const report_comment_1 = __nccwpck_require__(2389);
const profile_comment_1 = __nccwpck_require__(4683);
async function run() {
try {
const globPath = core.getInput('json-path', { required: true });
Expand All @@ -39161,6 +39162,9 @@ async function run() {
if (core.getInput('comment') === 'true' && github.context.issue.number) {
await (0, report_comment_1.reportComment)(result);
}
if (github.context.issue.number) {
await (0, profile_comment_1.reportProfileComment)(result);
}
}
catch (error) {
if (error instanceof Error) {
Expand Down Expand Up @@ -39220,17 +39224,119 @@ async function parse(resultPaths) {
lineNumber: line_number
};
});
const slowExamples = [...allExamples]
.sort((a, b) => b.run_time - a.run_time)
.slice(0, 10)
.map(({ file_path, line_number, full_description, run_time }) => {
return {
description: full_description,
filePath: file_path.replace(/^\.\//, ''),
lineNumber: line_number,
runTime: run_time
};
});
const totalExamples = allExamples.length;
const failedExamples = examples.length;
const pendingExamples = allExamples.filter(example => example.pending_message !== null).length;
const totalTime = allExamples.reduce((total, { run_time }) => total + run_time, 0);
return {
examples,
slowExamples,
summary: generateSummary(totalExamples, failedExamples, pendingExamples),
success: examples.length === 0
success: examples.length === 0,
totalTime
};
}


/***/ }),

/***/ 4683:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {

"use strict";

var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.reportProfileComment = void 0;
exports.examples2Table = examples2Table;
const core = __importStar(__nccwpck_require__(9093));
const github = __importStar(__nccwpck_require__(5942));
const util_1 = __nccwpck_require__(8438);
const actions_replace_comment_1 = __importDefault(__nccwpck_require__(5518));
async function examples2Table(examples) {
const { markdownTable } = await __nccwpck_require__.e(/* import() */ 448).then(__nccwpck_require__.bind(__nccwpck_require__, 6850));
return markdownTable([
['Example', 'Description', 'Time in seconds'],
...examples.map(({ filePath, lineNumber, description, runTime }) => [
[filePath, lineNumber].join(':'),
description,
String((0, util_1.floor)(runTime, 5))
])
]);
}
const commentGeneralOptions = () => {
const pullRequestId = github.context.issue.number;
if (!pullRequestId) {
throw new Error('Cannot find the PR id.');
}
return {
token: core.getInput('token', { required: true }),
owner: github.context.repo.owner,
repo: github.context.repo.repo,
issue_number: pullRequestId
};
};
const slowestExamplesSummary = (result) => {
const totalTime = result.totalTime;
const slowTotalTime = result.slowExamples.reduce((total, { runTime }) => total + runTime, 0);
const percentage = (slowTotalTime / totalTime) * 100;
// eslint-disable-next-line i18n-text/no-en
return `Top ${result.slowExamples.length} slowest examples (${(0, util_1.floor)(slowTotalTime, 2)} seconds, ${(0, util_1.floor)(percentage, 2)}% of total time)`;
};
const reportProfileComment = async (result) => {
const title = core.getInput('profileTitle', { required: true });
const summary = slowestExamplesSummary(result);
await (0, actions_replace_comment_1.default)({
...commentGeneralOptions(),
body: `${title}
<details>
<summary>${summary}</summary>

${await examples2Table(result.slowExamples)}

</details>
`
});
};
exports.reportProfileComment = reportProfileComment;


/***/ }),

/***/ 2389:
Expand Down Expand Up @@ -39403,6 +39509,22 @@ const reportSummary = async (result) => {
exports.reportSummary = reportSummary;


/***/ }),

/***/ 8438:
/***/ ((__unused_webpack_module, exports) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.floor = void 0;
const floor = (n, ndigits) => {
const shift = Math.pow(10, ndigits);
return Math.floor(n * shift) / shift;
};
exports.floor = floor;


/***/ }),

/***/ 9491:
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js.map

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions dist/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/main.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion dist/parse.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 34294b5

Please sign in to comment.