Skip to content

Commit

Permalink
feat(clear-text-reporter): Add "skipFull" option (#4875)
Browse files Browse the repository at this point in the history
Add `skipFull` clear text reporter option. With this, you indicate to not report 100% mutation score file in the report table.

---------

Co-authored-by: Nico Jansen <jansennico@gmail.com>
  • Loading branch information
sebiniemann and nicojs authored Aug 3, 2024
1 parent 2ea3312 commit da213ad
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 9 deletions.
14 changes: 12 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Choose whether or not to clean the temp dir (which is ".stryker-tmp" inside the

### `clearTextReporter` [`ClearTextOptions`]

Default: `{ "allowColor": true, "allowEmojis": false, "logTests": true, "maxTestsToLog": 3, "reportTests": true, "reportMutants": true, "reportScoreTable": true }`<br />
Default: `{ "allowColor": true, "allowEmojis": false, "logTests": true, "maxTestsToLog": 3, "reportTests": true, "reportMutants": true, "reportScoreTable": true, "skipFull": false }`<br />

Config file:

Expand All @@ -109,13 +109,23 @@ Config file:
"maxTestsToLog": 3,
"reportTests": true,
"reportMutants": true,
"reportScoreTable": true
"reportScoreTable": true,
"skipFull": false
}
}
```

Settings for the `clear-text` reporter.

- `allowColor`: "Indicates whether or not to use color coding in output.",
- `allowEmojis`: Enable emojis in your clear text report (experimental).
- `logTests`: Indicates whether or not to log which tests were executed for a given mutant.
- `maxTestsToLog`: Indicates the maximum amount of test to log when `logTests` is enabled.
- `reportTests`: Indicates whether or not to log all tests.
- `reportMutants`: Indicates whether or not to log all mutants.
- `reportScoreTable`: Indicates whether or not to log score table.
- `skipFull`: Indicates whether rows with 100% mutation score are hidden in the score table.

### `concurrency` [`number`]

Default: `cpuCoreCount <= 4? cpuCoreCount : cpuCoreCount - 1`<br />
Expand Down
5 changes: 5 additions & 0 deletions packages/api/schema/stryker-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@
"description": "Indicates whether or not to log score table.",
"type": "boolean",
"default": true
},
"skipFull": {
"description": "Indicates whether rows with 100% mutation score are hidden in the score table.",
"type": "boolean",
"default": false
}
}
},
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/reporters/clear-text-reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ export class ClearTextReporter implements Reporter {
if (this.options.clearTextReporter.reportMutants) {
this.reportMutants(metrics);
}
if (this.options.clearTextReporter.reportScoreTable) {
if (
this.options.clearTextReporter.reportScoreTable &&
(!this.options.clearTextReporter.skipFull || metrics.systemUnderTestMetrics.childResults.some((x) => x.metrics.mutationScore !== 100))
) {
this.writeLine(new ClearTextScoreTable(metrics.systemUnderTestMetrics, this.options).draw());
}
}
Expand Down
15 changes: 9 additions & 6 deletions packages/core/src/reporters/clear-text-score-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class ClearTextScoreTable {

constructor(
private readonly metricsResult: MetricsResult,
options: StrykerOptions,
private readonly options: StrykerOptions,
) {
this.columns = [
new FileColumn(metricsResult),
Expand Down Expand Up @@ -141,16 +141,19 @@ export class ClearTextScoreTable {
return this.columns.map(toDraw).join('|') + '|';
}

private drawValues(current = this.metricsResult, ancestorCount = 0): string[] {
return [this.drawRow((c) => c.drawTableCell(current, ancestorCount))].concat(
current.childResults.flatMap((child) => this.drawValues(child, ancestorCount + 1)),
);
private drawTableBody(current = this.metricsResult, ancestorCount = 0): string[] {
const rows: string[] = [];
if (!this.options.clearTextReporter.skipFull || current.metrics.mutationScore !== 100) {
rows.push(this.drawRow((c) => c.drawTableCell(current, ancestorCount)));
}
rows.push(...current.childResults.flatMap((child) => this.drawTableBody(child, ancestorCount + 1)));
return rows;
}

/**
* Returns a string with the score results drawn in a table.
*/
public draw(): string {
return [this.drawBorder(), this.drawHeader(), this.drawBorder(), this.drawValues().join(os.EOL), this.drawBorder()].join(os.EOL);
return [this.drawBorder(), this.drawHeader(), this.drawBorder(), this.drawTableBody().join(os.EOL), this.drawBorder()].join(os.EOL);
}
}
1 change: 1 addition & 0 deletions packages/core/test/helpers/producers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const createClearTextReporterOptions = factoryMethod<ClearTextReporterOpt
reportTests: true,
reportMutants: true,
reportScoreTable: true,
skipFull: false,
}));

export type ConcurrencyTokenProviderMock = sinon.SinonStubbedInstance<I<ConcurrencyTokenProvider>> & {
Expand Down
1 change: 1 addition & 0 deletions packages/core/test/unit/config/options-validator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe(OptionsValidator.name, () => {
reportTests: true,
reportMutants: true,
reportScoreTable: true,
skipFull: false,
},
commandRunner: {
command: 'npm test',
Expand Down
75 changes: 75 additions & 0 deletions packages/core/test/unit/reporters/clear-text-reporter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,81 @@ describe(ClearTextReporter.name, () => {
expect(stdoutStub).not.calledWithMatch(sinon.match('File | % score | # killed | # timeout | # survived | # no cov | # errors |'));
});

it('should not report files that achieved a 100% score when skipFull is true', () => {
testInjector.options.clearTextReporter.skipFull = true;

act({
files: {
'src/file.js': {
language: 'js',
mutants: [
{
id: '1',
location: { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } },
mutatorName: 'Block',
replacement: '{}',
status: 'Ignored',
},
],
source: 'console.log("hello world!")',
},
'src/file2.js': {
language: 'js',
mutants: [
{
id: '1',
location: { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } },
mutatorName: 'Block',
replacement: '{}',
status: 'Killed',
},
],
source: 'console.log("hello world!")',
},
},
schemaVersion: '1.0',
thresholds: factory.mutationScoreThresholds({}),
});

const serializedTable: string = stdoutStub.getCalls().pop()!.args[0];
const rows = serializedTable.split(os.EOL);

expect(rows).to.deep.eq([
'----------|---------|----------|-----------|------------|----------|----------|',
'File | % score | # killed | # timeout | # survived | # no cov | # errors |',
'----------|---------|----------|-----------|------------|----------|----------|',
` file.js |${chalk.grey(' n/a ')}| 0 | 0 | 0 | 0 | 0 |`,
'----------|---------|----------|-----------|------------|----------|----------|',
'',
]);
});

it('should omit the entire table if skipFull is true and all files achieve a 100% score', () => {
testInjector.options.clearTextReporter.skipFull = true;

act({
files: {
'src/file.js': {
language: 'js',
mutants: [
{
id: '1',
location: { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } },
mutatorName: 'Block',
replacement: '{}',
status: 'Killed',
},
],
source: 'console.log("hello world!")',
},
},
schemaVersion: '1.0',
thresholds: factory.mutationScoreThresholds({}),
});

sinon.assert.neverCalledWith(stdoutStub, sinon.match('-------'));
});

it('should show emojis in table with enableConsoleEmojis flag', () => {
testInjector.options.clearTextReporter.allowEmojis = true;

Expand Down

0 comments on commit da213ad

Please sign in to comment.