diff --git a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts index a9dd4e5e4..eb5e34ccb 100644 --- a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts +++ b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.ts @@ -84,9 +84,9 @@ export async function parseLcovFiles( typeof result === 'string' || result.pathToProject == null ? record.file : path.join(result.pathToProject, record.file), - functions: filterOutInvalidLines(record, 'functions'), - branches: filterOutInvalidLines(record, 'branches'), - lines: filterOutInvalidLines(record, 'lines'), + functions: patchInvalidStats(record, 'functions'), + branches: patchInvalidStats(record, 'branches'), + lines: patchInvalidStats(record, 'lines'), }), ); }), @@ -101,21 +101,19 @@ export async function parseLcovFiles( } /** - * Filters out invalid line numbers. - * - * Some tools like pytest-cov emit line number 0. https://github.com/nedbat/coveragepy/issues/1846 - * + * Filters out invalid `line` numbers, and ensures `hit <= found`. * @param record LCOV record * @param type Coverage type - * @returns Coverage output from record without invalid line numbers + * @returns Patched stats for type in record */ -function filterOutInvalidLines( +function patchInvalidStats( record: LCOVRecord, type: T, ): LCOVRecord[T] { const stats = record[type]; return { ...stats, + hit: Math.min(stats.hit, stats.found), details: stats.details.filter(detail => detail.line > 0), }; } diff --git a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts index bde457156..14da90d7e 100644 --- a/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts +++ b/packages/plugin-coverage/src/lib/runner/lcov/lcov-runner.unit.test.ts @@ -39,7 +39,7 @@ SF:kw/__init__.py DA:1,1,gG9L/J2A/IwO9tZM1raZxQ DA:0,0,gG9L/J2A/IwO9tZM1raZxQ LF:2 -LH:1 +LH:3 BRF:0 BRH:0 end_of_record @@ -125,12 +125,14 @@ end_of_record parseLcovFiles([path.join('coverage', 'pytest', 'lcov.info')]), ).resolves.toEqual([ expect.objectContaining({ - lines: expect.objectContaining({ + lines: { + found: 2, + hit: 2, // not 3 details: [ { hit: 1, line: 1 }, // no { hit: 0, line: 0 }, ], - }), + }, }), ]); });