mirror of
https://github.com/dorny/test-reporter.git
synced 2025-12-16 14:27:10 +01:00
feat(lcov) use really lcov.info file
This commit is contained in:
parent
61007344dd
commit
fb59f4f91d
11 changed files with 204 additions and 113 deletions
|
|
@ -1,45 +1,21 @@
|
||||||

|

|
||||||
## ❌ <a id="user-content-r0" href="#r0">fixtures/lcov.json</a>
|
## ❌ <a id="user-content-r0" href="#r0">fixtures/lcov.info</a>
|
||||||
**15** tests were completed in **0ms** with **7** passed, **8** failed and **0** skipped.
|
**6** tests were completed in **0ms** with **4** passed, **2** failed and **0** skipped.
|
||||||
|Test suite|Passed|Failed|Skipped|Time|
|
|Test suite|Passed|Failed|Skipped|Time|
|
||||||
|:---|---:|---:|---:|---:|
|
|:---|---:|---:|---:|---:|
|
||||||
|[src/core/dao.service.ts](#r0s0)|3✅|||0ms|
|
|[src/services/notifier/NotifierService.js](#r0s0)|2✅|1❌||0ms|
|
||||||
|[src/domains/auth/auth.controller.ts](#r0s1)|2✅|1❌||0ms|
|
|[src/services/notifier/providers/DiscordNotifierProvider.js](#r0s1)|2✅|1❌||0ms|
|
||||||
|[src/shared/notif/providers/fcm/fcm.service.spec.ts](#r0s2)||3❌||0ms|
|
### ❌ <a id="user-content-r0s0" href="#r0s0">src/services/notifier/NotifierService.js</a>
|
||||||
|[src/shared/notif/providers/fcm/fcm.service.ts](#r0s3)|1✅|2❌||0ms|
|
|
||||||
|[src/shared/notif/providers/mail/mail-service.ts](#r0s4)|1✅|2❌||0ms|
|
|
||||||
### ✅ <a id="user-content-r0s0" href="#r0s0">src/core/dao.service.ts</a>
|
|
||||||
```
|
```
|
||||||
src/core/dao.service.ts
|
src/services/notifier/NotifierService.js
|
||||||
✅ statement
|
✅ lines 100% (21/21)
|
||||||
✅ fonction
|
✅ functions 100% (10/10)
|
||||||
✅ branche
|
❌ branches 50% (3/6)
|
||||||
```
|
```
|
||||||
### ❌ <a id="user-content-r0s1" href="#r0s1">src/domains/auth/auth.controller.ts</a>
|
### ❌ <a id="user-content-r0s1" href="#r0s1">src/services/notifier/providers/DiscordNotifierProvider.js</a>
|
||||||
```
|
```
|
||||||
src/domains/auth/auth.controller.ts
|
src/services/notifier/providers/DiscordNotifierProvider.js
|
||||||
✅ statement
|
✅ lines 100% (17/17)
|
||||||
❌ fonction
|
✅ functions 100% (3/3)
|
||||||
✅ branche
|
❌ branches 75% (3/4)
|
||||||
```
|
|
||||||
### ❌ <a id="user-content-r0s2" href="#r0s2">src/shared/notif/providers/fcm/fcm.service.spec.ts</a>
|
|
||||||
```
|
|
||||||
src/shared/notif/providers/fcm/fcm.service.spec.ts
|
|
||||||
❌ statement
|
|
||||||
❌ fonction
|
|
||||||
❌ branche
|
|
||||||
```
|
|
||||||
### ❌ <a id="user-content-r0s3" href="#r0s3">src/shared/notif/providers/fcm/fcm.service.ts</a>
|
|
||||||
```
|
|
||||||
src/shared/notif/providers/fcm/fcm.service.ts
|
|
||||||
❌ statement
|
|
||||||
❌ fonction
|
|
||||||
✅ branche
|
|
||||||
```
|
|
||||||
### ❌ <a id="user-content-r0s4" href="#r0s4">src/shared/notif/providers/mail/mail-service.ts</a>
|
|
||||||
```
|
|
||||||
src/shared/notif/providers/mail/mail-service.ts
|
|
||||||
❌ statement
|
|
||||||
❌ fonction
|
|
||||||
✅ branche
|
|
||||||
```
|
```
|
||||||
92
__tests__/fixtures/lcov.info
Normal file
92
__tests__/fixtures/lcov.info
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
TN:
|
||||||
|
SF:src/services/notifier/NotifierService.js
|
||||||
|
FN:9,(anonymous_0)
|
||||||
|
FN:10,(anonymous_1)
|
||||||
|
FN:26,(anonymous_2)
|
||||||
|
FN:27,(anonymous_3)
|
||||||
|
FN:29,(anonymous_4)
|
||||||
|
FN:30,(anonymous_5)
|
||||||
|
FN:46,(anonymous_6)
|
||||||
|
FN:47,(anonymous_7)
|
||||||
|
FN:48,(anonymous_8)
|
||||||
|
FN:49,(anonymous_9)
|
||||||
|
FNF:10
|
||||||
|
FNH:10
|
||||||
|
FNDA:1,(anonymous_0)
|
||||||
|
FNDA:1,(anonymous_1)
|
||||||
|
FNDA:1,(anonymous_2)
|
||||||
|
FNDA:3,(anonymous_3)
|
||||||
|
FNDA:3,(anonymous_4)
|
||||||
|
FNDA:3,(anonymous_5)
|
||||||
|
FNDA:1,(anonymous_6)
|
||||||
|
FNDA:3,(anonymous_7)
|
||||||
|
FNDA:3,(anonymous_8)
|
||||||
|
FNDA:3,(anonymous_9)
|
||||||
|
DA:9,1
|
||||||
|
DA:10,1
|
||||||
|
DA:11,1
|
||||||
|
DA:13,1
|
||||||
|
DA:14,1
|
||||||
|
DA:26,1
|
||||||
|
DA:27,3
|
||||||
|
DA:29,1
|
||||||
|
DA:30,3
|
||||||
|
DA:31,3
|
||||||
|
DA:33,3
|
||||||
|
DA:34,3
|
||||||
|
DA:46,1
|
||||||
|
DA:47,3
|
||||||
|
DA:48,3
|
||||||
|
DA:51,3
|
||||||
|
DA:53,3
|
||||||
|
DA:54,3
|
||||||
|
DA:58,3
|
||||||
|
DA:61,1
|
||||||
|
DA:64,1
|
||||||
|
LF:21
|
||||||
|
LH:21
|
||||||
|
BRDA:11,0,0,1
|
||||||
|
BRDA:11,0,1,0
|
||||||
|
BRDA:31,1,0,3
|
||||||
|
BRDA:31,1,1,0
|
||||||
|
BRDA:51,2,0,3
|
||||||
|
BRDA:51,2,1,0
|
||||||
|
BRF:6
|
||||||
|
BRH:3
|
||||||
|
end_of_record
|
||||||
|
TN:
|
||||||
|
SF:src/services/notifier/providers/DiscordNotifierProvider.js
|
||||||
|
FN:12,(anonymous_0)
|
||||||
|
FN:33,(anonymous_1)
|
||||||
|
FN:51,(anonymous_2)
|
||||||
|
FNF:3
|
||||||
|
FNH:3
|
||||||
|
FNDA:1,(anonymous_0)
|
||||||
|
FNDA:1,(anonymous_1)
|
||||||
|
FNDA:1,(anonymous_2)
|
||||||
|
DA:3,1
|
||||||
|
DA:12,1
|
||||||
|
DA:13,1
|
||||||
|
DA:14,1
|
||||||
|
DA:22,1
|
||||||
|
DA:23,1
|
||||||
|
DA:33,1
|
||||||
|
DA:34,1
|
||||||
|
DA:35,1
|
||||||
|
DA:40,1
|
||||||
|
DA:41,1
|
||||||
|
DA:51,1
|
||||||
|
DA:52,1
|
||||||
|
DA:53,1
|
||||||
|
DA:58,1
|
||||||
|
DA:59,1
|
||||||
|
DA:62,1
|
||||||
|
LF:17
|
||||||
|
LH:17
|
||||||
|
BRDA:18,0,0,0
|
||||||
|
BRDA:18,0,1,1
|
||||||
|
BRDA:20,1,0,1
|
||||||
|
BRDA:20,1,1,1
|
||||||
|
BRF:4
|
||||||
|
BRH:3
|
||||||
|
end_of_record
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -3,12 +3,12 @@ import * as path from 'path'
|
||||||
|
|
||||||
import {getReport} from '../src/report/get-report'
|
import {getReport} from '../src/report/get-report'
|
||||||
import {normalizeFilePath} from '../src/utils/path-utils'
|
import {normalizeFilePath} from '../src/utils/path-utils'
|
||||||
import { LcovParser } from "../src/parsers/lcov-json/lcov-parser";
|
import { LcovParser } from "../src/parsers/lcov/lcov-parser";
|
||||||
|
|
||||||
describe('lcov report coverage', () => {
|
describe('lcov report coverage', () => {
|
||||||
|
|
||||||
it('report from facebook/jest test results matches snapshot', async () => {
|
it('report from facebook/jest test results matches snapshot', async () => {
|
||||||
const fixturePath = path.join(__dirname, 'fixtures', 'lcov.json')
|
const fixturePath = path.join(__dirname, 'fixtures', 'lcov.info')
|
||||||
const outputPath = path.join(__dirname, '__outputs__', 'lcov-report-results.md')
|
const outputPath = path.join(__dirname, '__outputs__', 'lcov-report-results.md')
|
||||||
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
const filePath = normalizeFilePath(path.relative(__dirname, fixturePath))
|
||||||
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
const fileContent = fs.readFileSync(fixturePath, {encoding: 'utf8'})
|
||||||
|
|
|
||||||
16
package-lock.json
generated
16
package-lock.json
generated
|
|
@ -15,6 +15,7 @@
|
||||||
"adm-zip": "^0.5.3",
|
"adm-zip": "^0.5.3",
|
||||||
"fast-glob": "^3.2.5",
|
"fast-glob": "^3.2.5",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
|
"lcov-parse": "^1.0.0",
|
||||||
"picomatch": "^2.2.2",
|
"picomatch": "^2.2.2",
|
||||||
"xml2js": "^0.5.0"
|
"xml2js": "^0.5.0"
|
||||||
},
|
},
|
||||||
|
|
@ -25,6 +26,7 @@
|
||||||
"@types/adm-zip": "^0.5.0",
|
"@types/adm-zip": "^0.5.0",
|
||||||
"@types/github-slugger": "^1.3.0",
|
"@types/github-slugger": "^1.3.0",
|
||||||
"@types/jest": "^28.1.7",
|
"@types/jest": "^28.1.7",
|
||||||
|
"@types/lcov-parse": "^1.0.2",
|
||||||
"@types/node": "^18.7.7",
|
"@types/node": "^18.7.7",
|
||||||
"@types/picomatch": "^2.2.1",
|
"@types/picomatch": "^2.2.1",
|
||||||
"@types/xml2js": "^0.4.8",
|
"@types/xml2js": "^0.4.8",
|
||||||
|
|
@ -1790,6 +1792,12 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/lcov-parse": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/lcov-parse/-/lcov-parse-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-tdoxiYm04XdDEdR7UMwkWj78UAVo9U2IOcxI6tmX2/s9TK/ue/9T8gbpS/07yeWyVkVO0UumFQ5EUIBQbVejzQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "18.17.17",
|
"version": "18.17.17",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.17.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.17.tgz",
|
||||||
|
|
@ -5807,6 +5815,14 @@
|
||||||
"language-subtag-registry": "~0.3.2"
|
"language-subtag-registry": "~0.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lcov-parse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==",
|
||||||
|
"bin": {
|
||||||
|
"lcov-parse": "bin/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
"adm-zip": "^0.5.3",
|
"adm-zip": "^0.5.3",
|
||||||
"fast-glob": "^3.2.5",
|
"fast-glob": "^3.2.5",
|
||||||
"got": "^11.8.2",
|
"got": "^11.8.2",
|
||||||
|
"lcov-parse": "^1.0.0",
|
||||||
"picomatch": "^2.2.2",
|
"picomatch": "^2.2.2",
|
||||||
"xml2js": "^0.5.0"
|
"xml2js": "^0.5.0"
|
||||||
},
|
},
|
||||||
|
|
@ -46,6 +47,7 @@
|
||||||
"@types/adm-zip": "^0.5.0",
|
"@types/adm-zip": "^0.5.0",
|
||||||
"@types/github-slugger": "^1.3.0",
|
"@types/github-slugger": "^1.3.0",
|
||||||
"@types/jest": "^28.1.7",
|
"@types/jest": "^28.1.7",
|
||||||
|
"@types/lcov-parse": "^1.0.2",
|
||||||
"@types/node": "^18.7.7",
|
"@types/node": "^18.7.7",
|
||||||
"@types/picomatch": "^2.2.1",
|
"@types/picomatch": "^2.2.1",
|
||||||
"@types/xml2js": "^0.4.8",
|
"@types/xml2js": "^0.4.8",
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import {SwiftXunitParser} from './parsers/swift-xunit/swift-xunit-parser'
|
||||||
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
import {normalizeDirPath, normalizeFilePath} from './utils/path-utils'
|
||||||
import {getCheckRunContext} from './utils/github-utils'
|
import {getCheckRunContext} from './utils/github-utils'
|
||||||
import {Icon} from './utils/markdown-utils'
|
import {Icon} from './utils/markdown-utils'
|
||||||
import {LcovParser} from './parsers/lcov-json/lcov-parser'
|
import {LcovParser} from './parsers/lcov/lcov-parser'
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
import {ParseOptions, TestParser} from '../../test-parser'
|
|
||||||
|
|
||||||
import {TestCaseResult, TestGroupResult, TestRunResult, TestSuiteResult} from '../../test-results'
|
|
||||||
import {CovParsedStat, CovStats, LcovReport} from './lcov-types'
|
|
||||||
|
|
||||||
export class LcovParser implements TestParser {
|
|
||||||
constructor(readonly options: ParseOptions) {}
|
|
||||||
async parse(path: string, content: string): Promise<TestRunResult> {
|
|
||||||
const report = this.parseFile(path, content)
|
|
||||||
return this.getTestRunResult(path, report)
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseFile(path: string, content: string): LcovReport {
|
|
||||||
try {
|
|
||||||
return JSON.parse(content) as LcovReport
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`Invalid JSON at ${path}\n\n${e}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private async getTestRunResult(path: string, report: LcovReport): Promise<TestRunResult> {
|
|
||||||
const suites: TestSuiteResult[] = []
|
|
||||||
|
|
||||||
for (const key of Object.keys(report)) {
|
|
||||||
const s: CovParsedStat = this.getParsedStat(report[key].s)
|
|
||||||
const f: CovParsedStat = this.getParsedStat(report[key].f)
|
|
||||||
const b: CovParsedStat = this.getParsedStat(report[key].b)
|
|
||||||
|
|
||||||
const statementCaseResult: TestCaseResult = {
|
|
||||||
name: 'statement',
|
|
||||||
time: 0,
|
|
||||||
result: s.percentage >= 80 ? 'success' : 'failed'
|
|
||||||
}
|
|
||||||
const fonctionCaseResult: TestCaseResult = {
|
|
||||||
name: 'fonction',
|
|
||||||
time: 0,
|
|
||||||
result: f.percentage >= 80 ? 'success' : 'failed'
|
|
||||||
}
|
|
||||||
const brancheCaseResult: TestCaseResult = {
|
|
||||||
name: 'branche',
|
|
||||||
time: 0,
|
|
||||||
result: b.percentage >= 80 ? 'success' : 'failed'
|
|
||||||
}
|
|
||||||
|
|
||||||
const testCases: TestCaseResult[] = [statementCaseResult, fonctionCaseResult, brancheCaseResult]
|
|
||||||
const goups: TestGroupResult[] = [new TestGroupResult(key, testCases)]
|
|
||||||
const suite: TestSuiteResult = new TestSuiteResult(key, goups)
|
|
||||||
|
|
||||||
suites.push(suite)
|
|
||||||
console.log({key, s, f, b})
|
|
||||||
}
|
|
||||||
|
|
||||||
return new TestRunResult(path, suites)
|
|
||||||
}
|
|
||||||
|
|
||||||
private getParsedStat(stat: CovStats): CovParsedStat {
|
|
||||||
const max = Object.keys(stat).length
|
|
||||||
const nonCovered = this.zeroLength(stat)
|
|
||||||
const percentage = ((max - nonCovered) / max) * 100
|
|
||||||
|
|
||||||
return {max, nonCovered, percentage}
|
|
||||||
}
|
|
||||||
private zeroLength(report: CovStats): number {
|
|
||||||
return Object.keys(report).filter(key => report[key] === 0).length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
62
src/parsers/lcov/lcov-parser.ts
Normal file
62
src/parsers/lcov/lcov-parser.ts
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import {ParseOptions, TestParser} from '../../test-parser'
|
||||||
|
|
||||||
|
import {TestCaseResult, TestGroupResult, TestRunResult, TestSuiteResult} from '../../test-results'
|
||||||
|
import {parseProm} from './lcov-utils'
|
||||||
|
import {LcovBranch, LcovFile, LcovFunc, LcovLine, LcovPart} from 'lcov-parse'
|
||||||
|
|
||||||
|
export class LcovParser implements TestParser {
|
||||||
|
constructor(readonly options: ParseOptions) {}
|
||||||
|
async parse(path: string, content: string): Promise<TestRunResult> {
|
||||||
|
const report = await this.parseFile(path, content)
|
||||||
|
return this.getTestRunResult(path, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
private parseFile(path: string, content: string): Promise<LcovFile[]> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
return parseProm(content)
|
||||||
|
//return JSON.parse(content) as LcovReport
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Invalid JSON at ${path}\n\n${e}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private async getTestRunResult(path: string, report: LcovFile[]): Promise<TestRunResult> {
|
||||||
|
const suites: TestSuiteResult[] = []
|
||||||
|
|
||||||
|
for (let reportElement of report) {
|
||||||
|
const fileName = reportElement.file
|
||||||
|
|
||||||
|
const statementCaseResult: TestCaseResult = {
|
||||||
|
name: `lines ${this.getPartInfo(reportElement.lines)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.lines) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
const fonctionCaseResult: TestCaseResult = {
|
||||||
|
name: `functions ${this.getPartInfo(reportElement.functions)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.functions) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
const brancheCaseResult: TestCaseResult = {
|
||||||
|
name: `branches ${this.getPartInfo(reportElement.branches)}`,
|
||||||
|
time: 0,
|
||||||
|
result: this.getPercentage(reportElement.branches) >= 80 ? 'success' : 'failed'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const testCases: TestCaseResult[] = [statementCaseResult, fonctionCaseResult, brancheCaseResult]
|
||||||
|
const groups: TestGroupResult[] = [new TestGroupResult(fileName, testCases)]
|
||||||
|
const suite: TestSuiteResult = new TestSuiteResult(fileName, groups)
|
||||||
|
|
||||||
|
suites.push(suite)
|
||||||
|
}
|
||||||
|
return new TestRunResult(path, suites)
|
||||||
|
}
|
||||||
|
|
||||||
|
private getPercentage(stat: LcovPart<LcovLine | LcovFunc | LcovBranch>): number {
|
||||||
|
return stat ? stat.hit/ stat.found * 100 : 100;
|
||||||
|
}
|
||||||
|
private getPartInfo(stat: LcovPart<LcovLine | LcovFunc | LcovBranch>): string {
|
||||||
|
return `${this.getPercentage(stat)}% (${stat.hit}/${stat.found})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/parsers/lcov/lcov-utils.ts
Normal file
14
src/parsers/lcov/lcov-utils.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import parse, {LcovFile} from 'lcov-parse'
|
||||||
|
|
||||||
|
const parseProm = (pathOrStr: string): Promise<LcovFile[]> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
parse(pathOrStr, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
resolve(data ?? []);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export {parseProm}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue