Compare commits
1 commit
0.x
...
feat/diff-
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f7cf162a0 |
3 changed files with 83 additions and 3 deletions
26
README.md
26
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Diff Cov
|
||||
|
||||
Simple CLI to print diffs highlighted with test coverage status
|
||||
Simple CLI to print git and lcov diffs highlighted with test coverage status
|
||||
|
||||

|
||||
|
||||
|
|
@ -45,6 +45,8 @@ git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/0.x
|
|||
|
||||
## Usage
|
||||
|
||||
### Git diff
|
||||
|
||||
Before you run `diff-cov` you must run your test suite with coverage and output
|
||||
a `lcov` coverage file. You must also have all your changes committed to ensure
|
||||
it's included in the output.
|
||||
|
|
@ -62,3 +64,25 @@ diff-cov --coverageFile coverage/lcov.info
|
|||
|
||||
A report is printed at the bottom and colored with a threshold of `90%`
|
||||
anything below this percentage coverage will be colored red.
|
||||
|
||||
### LCov diff
|
||||
|
||||
You can also print the coverage difference between to lcov.info files. To use
|
||||
this run your tests with coverage for a first time. After its finished you can
|
||||
copy your lcov.info file somewhere for later for example:
|
||||
|
||||
```shell
|
||||
cp ./lcov.info /tmp/lcov.info
|
||||
```
|
||||
|
||||
Then you can work on your test and run the tests once more with coverage to
|
||||
generate you a new `lcov.info` file. Then you can print the difference in
|
||||
coverage between the two files with:
|
||||
|
||||
```shell
|
||||
diff-cov --compare /tmp/lcov.info
|
||||
```
|
||||
|
||||
This can come in handy when you need to find out what a test is testing. You
|
||||
can create your base coverage file, comment out a test, run the tests again and
|
||||
diff the results.
|
||||
|
|
|
|||
20
src/index.ts
20
src/index.ts
|
|
@ -5,6 +5,7 @@ import { hideBin } from "yargs/helpers";
|
|||
import exec from "./exec";
|
||||
|
||||
import report from "./report";
|
||||
import lcovDiff from "./lcov-diff";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const parseDiff = require("./diff-parser");
|
||||
|
|
@ -21,11 +22,16 @@ const options: { [key: string]: Options } = {
|
|||
description: "The path to the lcov report file",
|
||||
type: "string",
|
||||
},
|
||||
compare: {
|
||||
description: "The path to the lcov report you wish to compare to the `coverage-file`",
|
||||
type: "string",
|
||||
},
|
||||
};
|
||||
|
||||
type Argv = Arguments<
|
||||
Partial<{
|
||||
coverageFile: string;
|
||||
compare?: string;
|
||||
}>
|
||||
>;
|
||||
|
||||
|
|
@ -36,6 +42,10 @@ export const validate = async (argv: Argv) => {
|
|||
`Please ensure you have run tests with coverage enabled.`
|
||||
);
|
||||
}
|
||||
|
||||
if (argv.compare && !fs.existsSync(argv.compare)) {
|
||||
return new Error(`Lcov compare file must be a valid file '${argv.compare}' provided.`);
|
||||
}
|
||||
};
|
||||
|
||||
export const run = async (argv = process.argv) => {
|
||||
|
|
@ -45,13 +55,19 @@ export const run = async (argv = process.argv) => {
|
|||
return error(validationError.message);
|
||||
}
|
||||
|
||||
const baseCoverage = await parseLcov.default(parsed.coverageFile);
|
||||
|
||||
if (parsed.compare) {
|
||||
const compareCoverage = await parseLcov.default(parsed.compare);
|
||||
return lcovDiff(baseCoverage, compareCoverage);
|
||||
}
|
||||
|
||||
const diffText = await exec(`git diff origin/HEAD...HEAD`);
|
||||
if (diffText.code > 0) {
|
||||
return error("Error loading the diff\n\n" + diffText.stderr);
|
||||
}
|
||||
|
||||
const diff = parseDiff.default(diffText.stdout);
|
||||
const coverage = await parseLcov.default(parsed.coverageFile);
|
||||
|
||||
report(diff, coverage);
|
||||
report(diff, baseCoverage);
|
||||
};
|
||||
|
|
|
|||
40
src/lcov-diff.ts
Normal file
40
src/lcov-diff.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
const buildCoverageSet = (report: any) => {
|
||||
const set = new Set<string>();
|
||||
for (const coverage of report) {
|
||||
for (const detail of coverage.lines.details) {
|
||||
if (detail.hit > 0) {
|
||||
set.add(`${coverage.file}:${detail.line}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
function setDiff<T>(a: Set<T>, b: Set<T>) {
|
||||
return new Set([...a].filter((x) => !b.has(x)));
|
||||
}
|
||||
|
||||
export const lcovDiff = async (baseCoverage: any, compareCoverage: any) => {
|
||||
const baseSet = buildCoverageSet(baseCoverage);
|
||||
const compareSet = buildCoverageSet(compareCoverage);
|
||||
|
||||
const map = new Map<string, number>();
|
||||
|
||||
const added = setDiff(baseSet, compareSet);
|
||||
for (const key of added) {
|
||||
map.set(key, 1);
|
||||
}
|
||||
|
||||
const removed = setDiff(compareSet, baseSet);
|
||||
for (const key of removed) {
|
||||
map.set(key, 0);
|
||||
}
|
||||
|
||||
for (const [key, value] of [...map.entries()].sort()) {
|
||||
const color = value > 0 ? "\x1b[32m" : "\x1b[31m";
|
||||
console.log(color, key, "\x1b[0m");
|
||||
}
|
||||
};
|
||||
|
||||
export default lcovDiff;
|
||||
Loading…
Reference in a new issue