Skip to content

Commit

Permalink
fix(betterer 🐛): improve docs, handle include and exclude, add tests,…
Browse files Browse the repository at this point in the history
… simplify
  • Loading branch information
phenomnomnominal committed Sep 16, 2024
1 parent 8cf8207 commit 5fb1285
Show file tree
Hide file tree
Showing 17 changed files with 630 additions and 271 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"docgen",
"GOLDENS",
"hasher",
"initialisation",
"initialise",
"initialised",
"Initialising",
Expand Down
11 changes: 2 additions & 9 deletions packages/coverage/src/coverage-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,17 @@ import { BettererResolverTest } from '@betterer/betterer';
import { constraint } from './constraint.js';
import { differ } from './differ.js';
import { goal } from './goal.js';
import { deserialise, serialise } from './serialiser.js';

export class BettererCoverageTestΩ
extends BettererResolverTest<BettererCoverageIssues, BettererCoverageIssues, BettererCoverageDiff>
implements BettererCoverageTest
{
constructor(test: BettererCoverageTestFunction, coverageSummaryPath = './coverage/coverage-summary.json') {
super({
test: async () => {
return await test(coverageSummaryPath, this.resolver);
},
test: async () => await test(coverageSummaryPath, this.resolver),
constraint,
differ,
goal,
serialiser: {
serialise,
deserialise
}
goal
});
}
}
4 changes: 2 additions & 2 deletions packages/coverage/src/coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { test, testTotal } from './test.js';
* Use this test to track your per-file test coverage. Reads a {@link https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-reports/lib/json-summary/index.js | json-summary format}
* coverage summary. Make sure to run your tests separately before running Betterer.
*
* @param coverageSummaryPath - relative path to the coverage summary. Defaults to './coverage/coverage-summary.json'.
* @param coverageSummaryPath - relative path to the coverage summary. Defaults to `'./coverage/coverage-summary.json'`.
*/
export function coverage(coverageSummaryPath?: string): BettererCoverageTest {
return new BettererCoverageTestΩ(test, coverageSummaryPath);
Expand All @@ -19,7 +19,7 @@ export function coverage(coverageSummaryPath?: string): BettererCoverageTest {
* Use this test to track your total test coverage. Reads a {@link https://github.com/istanbuljs/istanbuljs/blob/master/packages/istanbul-reports/lib/json-summary/index.js | json-summary format}
* coverage summary. Make sure to run your tests separately before running Betterer.
*
* @param coverageSummaryPath - relative path to the coverage summary. Defaults to './coverage/coverage-summary.json'.
* @param coverageSummaryPath - relative path to the coverage summary. Defaults to `'./coverage/coverage-summary.json'`.
*/
export function coverageTotal(coverageSummaryPath?: string): BettererCoverageTest {
return new BettererCoverageTestΩ(testTotal, coverageSummaryPath);
Expand Down
7 changes: 0 additions & 7 deletions packages/coverage/src/serialiser.ts

This file was deleted.

18 changes: 14 additions & 4 deletions packages/coverage/src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,21 @@ export async function testTotal(
relativeCoverageSummaryPath: string,
resolver: BettererFileResolver
): Promise<BettererCoverageIssues> {
const absoluteCoverageSummaryPath = resolver.resolve(relativeCoverageSummaryPath);
const { total } = await readCoverageSummary(absoluteCoverageSummaryPath);
return {
total: getUncoveredIssues(total)
const uncovered = await test(relativeCoverageSummaryPath, resolver);

const total: BettererCoverageIssue = {
lines: 0,
statements: 0,
functions: 0,
branches: 0
};
Object.values(uncovered).forEach((fileCoverage) => {
total.branches += fileCoverage.branches;
total.functions += fileCoverage.functions;
total.lines += fileCoverage.lines;
total.statements += fileCoverage.statements;
});
return { total };
}

async function readCoverageSummary(coverageSummaryPath: string): Promise<IstanbulCoverageSummary> {
Expand Down
14 changes: 7 additions & 7 deletions packages/coverage/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import type { CoverageSummaryData, Totals } from 'istanbul-lib-coverage';

export type IstanbulCoverage = Totals;
export type IstanbulFileCoverage = CoverageSummaryData;
export type IstanbulCoverageSummary = Record<string, IstanbulFileCoverage> & {
total: IstanbulFileCoverage;
};
export type IstanbulCoverageSummary = Record<string, IstanbulFileCoverage>;

/**
* @public A {@link @betterer/betterer#BettererTest | `BettererTest`} to incrementally improve test coverage.
Expand All @@ -22,21 +20,23 @@ export type BettererCoverageTestFunction = (
) => Promise<BettererCoverageIssues>;

/**
* @public The different types of coverage which are checked
* @public The different types of coverage which are checked.
*/
export type BettererCoverageTypes = 'lines' | 'statements' | 'functions' | 'branches';

/**
* @public The lines, statements, functions and branches coverage for a file (or the total project)
* @public The lines, statements, functions and branches coverage for a file (or the total project).
*
* @remarks Each value indicates how many of each type remain uncovered in the file.
*/
export type BettererCoverageIssue = Record<BettererCoverageTypes, number>;

/**
* @public The coverage for all the files in a project
* @public The coverage for all the files in a project.
*/
export type BettererCoverageIssues = Record<string, BettererCoverageIssue>;

/**
* @public The difference in coverage for a project between two test runs
* @public The difference in coverage for a project between two test runs.
*/
export type BettererCoverageDiff = BettererCoverageIssues;
132 changes: 132 additions & 0 deletions test/__snapshots__/coverage-total-include.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`betterer > should report the total coverage for included files 1`] = `
"// BETTERER RESULTS V2.
//
// If this file contains merge conflicts, use \`betterer merge\` to automatically resolve them:
// https://phenomnomnominal.github.io/betterer/docs/results-file/#merge
//
exports[\`test\`] = {
value: \`{
"total": { "lines": 50, "statements": 130, "functions": 15, "branches": 100 }
}
\`
};
"
`;
exports[`betterer > should report the total coverage for included files 2`] = `
"// BETTERER RESULTS V2.
//
// If this file contains merge conflicts, use \`betterer merge\` to automatically resolve them:
// https://phenomnomnominal.github.io/betterer/docs/results-file/#merge
//
exports[\`test\`] = {
value: \`{
"total": { "lines": 30, "statements": 130, "functions": 15, "branches": 100 }
}
\`
};
"
`;
exports[`betterer > should report the total coverage for included files 3`] = `
"// BETTERER RESULTS V2.
//
// If this file contains merge conflicts, use \`betterer merge\` to automatically resolve them:
// https://phenomnomnominal.github.io/betterer/docs/results-file/#merge
//
exports[\`test\`] = {
value: \`{
"total": { "lines": 30, "statements": 130, "functions": 15, "branches": 100 }
}
\`
};
"
`;
exports[`betterer > should report the total coverage for included files 4`] = `
[
"🌟 Betterer (0ms):
",
"🌟 Betterer (0ms): 1 test running...
🤔 test: running "test"!
",
"🌟 Betterer (0ms): 1 test running...
✅ test: "test" got checked for the first time! 🎉
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" got checked for the first time! 🎉
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" got checked for the first time! 🎉
1 test got checked. 🤔
1 test got checked for the first time! 🎉
",
"🌟 Betterer (0ms):
",
"🌟 Betterer (0ms): 1 test running...
🤔 test: running "test"!
",
"🌟 Betterer (0ms): 1 test running...
✅ test: "test" stayed the same. 😐
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" stayed the same. 😐
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" stayed the same. 😐
1 test got checked. 🤔
1 test stayed the same. 😐
",
"🌟 Betterer (0ms):
",
"🌟 Betterer (0ms): 1 test running...
🤔 test: running "test"!
",
"🌟 Betterer (0ms): 1 test running...
✅ test: "test" got better! 😍
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" got better! 😍
",
"🎉 Betterer (0ms): 1 test done!
✅ test: "test" got better! 😍
1 test got checked. 🤔
1 test got better! 😍
",
"🌟 Betterer (0ms):
",
"🌟 Betterer (0ms): 1 test running...
🤔 test: running "test"!
",
"🌟 Betterer (0ms): 1 test running...
🔥 test: "test" got worse. 😔
",
"🌟 Betterer (0ms): 1 test running...
🔥 test: "test" got worse. 😔
Error: "test" got worse. 😔
",
"💥 Betterer (0ms): 1 test done! 1 test errored!
🔥 test: "test" got worse. 😔
・ "lines" coverage is worse in "total": 60 > 30
Error: "test" got worse. 😔
",
"💥 Betterer (0ms): 1 test done! 1 test errored!
🔥 test: "test" got worse. 😔
・ "lines" coverage is worse in "total": 60 > 30
Error: "test" got worse. 😔
1 test got checked. 🤔
1 test got worse. 😔
You should try to fix the new issues! As a last resort, you can run \`betterer --update\` to force an update of the results file. 🆙
",
]
`;
48 changes: 27 additions & 21 deletions test/coverage-files-better.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('betterer', () => {
it('should report an improved file coverage result', async () => {
const { betterer } = await import('@betterer/betterer');

const fixture = await createFixture('coverage-files-better', {
const { paths, logs, cleanup, resolve, testNames, writeFile } = await createFixture('coverage-files-better', {
'.betterer.js': `
import { coverage } from '@betterer/coverage';
Expand All @@ -22,10 +22,11 @@ export default {
`
});

const file1Path = fixture.resolve('./src/file-1.ts');
const file2Path = fixture.resolve('./src/file-2.ts');
const file1Path = resolve('./src/file-1.ts');
const file2Path = resolve('./src/file-2.ts');

const coverage = `{
const coverage = `
{
"total": {
"lines": { "total": 220, "covered": 110, "skipped": 0, "pct": 50 },
"statements": { "total": 410, "covered": 140, "skipped": 0, "pct": 34.1 },
Expand All @@ -44,18 +45,20 @@ export default {
"functions": { "total": 10, "covered": 6, "skipped": 0, "pct": 60 },
"branches": { "total": 150, "covered": 50, "skipped": 0, "pct": 33.3 }
}
}`;
}
`;

const configPaths = [fixture.paths.config];
const resultsPath = fixture.paths.results;
const coveragePath = fixture.resolve('./coverage/coverage-summary.json');
const configPaths = [paths.config];
const resultsPath = paths.results;
const coveragePath = resolve('./coverage/coverage-summary.json');

await fixture.writeFile(coveragePath, coverage);
await writeFile(coveragePath, coverage);

await betterer({ configPaths, resultsPath, workers: false });

// file-1 is better
const betterCoverage = `{
const betterCoverage = `
{
"total": {
"lines": { "total": 220, "covered": 120, "skipped": 0, "pct": 54.54 },
"statements": { "total": 410, "covered": 140, "skipped": 0, "pct": 34.1 },
Expand All @@ -74,16 +77,18 @@ export default {
"functions": { "total": 10, "covered": 6, "skipped": 0, "pct": 60 },
"branches": { "total": 150, "covered": 50, "skipped": 0, "pct": 33.3 }
}
}`;
}
`;

await fixture.writeFile(coveragePath, betterCoverage);
await writeFile(coveragePath, betterCoverage);

const betterTestRun = await betterer({ configPaths, resultsPath, workers: false });

expect(fixture.testNames(betterTestRun.better)).toEqual(['test']);
expect(testNames(betterTestRun.better)).toEqual(['test']);

// file-1 is gone
const evenBetterCoverage = `{
const evenBetterCoverage = `
{
"total": {
"lines": { "total": 120, "covered": 60, "skipped": 0, "pct": 50 },
"statements": { "total": 210, "covered": 70, "skipped": 0, "pct": 33.3 },
Expand All @@ -96,13 +101,14 @@ export default {
"functions": { "total": 10, "covered": 6, "skipped": 0, "pct": 60 },
"branches": { "total": 150, "covered": 50, "skipped": 0, "pct": 33.3 }
}
}`;
}
`;

await fixture.writeFile(coveragePath, evenBetterCoverage);
await writeFile(coveragePath, evenBetterCoverage);

const evenBetterTestRun = await betterer({ configPaths, resultsPath, workers: false });

expect(fixture.testNames(evenBetterTestRun.better)).toEqual(['test']);
expect(testNames(evenBetterTestRun.better)).toEqual(['test']);

// file-2 is fully covered
const completedCoverage = `{
Expand All @@ -120,14 +126,14 @@ export default {
}
}`;

await fixture.writeFile(coveragePath, completedCoverage);
await writeFile(coveragePath, completedCoverage);

const completedTestRun = await betterer({ configPaths, resultsPath, workers: false });

expect(fixture.testNames(completedTestRun.completed)).toEqual(['test']);
expect(testNames(completedTestRun.completed)).toEqual(['test']);

expect(fixture.logs).toMatchSnapshot();
expect(logs).toMatchSnapshot();

await fixture.cleanup();
await cleanup();
});
});
Loading

0 comments on commit 5fb1285

Please sign in to comment.