Skip to content

Commit

Permalink
[test visibility] Add total code coverage measure to vitest (#4570)
Browse files Browse the repository at this point in the history
  • Loading branch information
juan-fernandez authored Aug 5, 2024
1 parent 3e690eb commit f53157a
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { describe, test, expect } from 'vitest'
import { sum } from './sum'

describe('code coverage', () => {
test('passes', () => {
expect(sum(1, 2)).to.equal(3)
})
})
14 changes: 12 additions & 2 deletions integration-tests/vitest.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { defineConfig } from 'vite'

export default defineConfig({
const config = {
test: {
include: [
process.env.TEST_DIR || 'ci-visibility/vitest-tests/test-visibility*'
]
}
})
}

if (process.env.COVERAGE_PROVIDER) {
config.test.coverage = {
provider: process.env.COVERAGE_PROVIDER || 'v8',
include: ['ci-visibility/vitest-tests/**'],
reporter: ['text-summary']
}
}

export default defineConfig(config)
69 changes: 65 additions & 4 deletions integration-tests/vitest/vitest.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,24 @@ const {
TEST_STATUS,
TEST_TYPE,
TEST_IS_RETRY,
TEST_CODE_OWNERS
TEST_CODE_OWNERS,
TEST_CODE_COVERAGE_LINES_PCT
} = require('../../packages/dd-trace/src/plugins/util/test')

// tested with 1.6.0
const versions = ['1.6.0', 'latest']

const linePctMatchRegex = /Lines\s+:\s+([\d.]+)%/

versions.forEach((version) => {
describe(`vitest@${version}`, () => {
let sandbox, cwd, receiver, childProcess
let sandbox, cwd, receiver, childProcess, testOutput

before(async function () {
sandbox = await createSandbox([`vitest@${version}`], true)
sandbox = await createSandbox([
`vitest@${version}`,
`@vitest/coverage-istanbul@${version}`,
`@vitest/coverage-v8@${version}`
], true)
cwd = sandbox.folder
})

Expand All @@ -37,6 +43,7 @@ versions.forEach((version) => {
})

afterEach(async () => {
testOutput = ''
childProcess.kill()
await receiver.stop()
})
Expand Down Expand Up @@ -233,5 +240,59 @@ versions.forEach((version) => {
}).catch(done)
})
})

// only works for >=2.0.0
if (version === 'latest') {
const coverageProviders = ['v8', 'istanbul']

coverageProviders.forEach((coverageProvider) => {
it(`reports code coverage for ${coverageProvider} provider`, (done) => {
let codeCoverageExtracted
const eventsPromise = receiver
.gatherPayloadsMaxTimeout(({ url }) => url.endsWith('/api/v2/citestcycle'), (payloads) => {
const events = payloads.flatMap(({ payload }) => payload.events)

const testSession = events.find(event => event.type === 'test_session_end').content

codeCoverageExtracted = testSession.metrics[TEST_CODE_COVERAGE_LINES_PCT]
})

childProcess = exec(
'./node_modules/.bin/vitest run --coverage',
{
cwd,
env: {
...getCiVisAgentlessConfig(receiver.port),
NODE_OPTIONS: '--import dd-trace/register.js -r dd-trace/ci/init',
COVERAGE_PROVIDER: coverageProvider,
TEST_DIR: 'ci-visibility/vitest-tests/coverage-test*'
},
stdio: 'inherit'
}
)

childProcess.stdout.on('data', (chunk) => {
testOutput += chunk.toString()
})
childProcess.stderr.on('data', (chunk) => {
testOutput += chunk.toString()
})

childProcess.on('exit', () => {
eventsPromise.then(() => {
const linePctMatch = testOutput.match(linePctMatchRegex)
const linesPctFromNyc = linePctMatch ? Number(linePctMatch[1]) : null

assert.equal(
linesPctFromNyc,
codeCoverageExtracted,
'coverage reported by vitest does not match extracted coverage'
)
done()
}).catch(done)
})
})
})
}
})
})
20 changes: 18 additions & 2 deletions packages/datadog-instrumentations/src/vitest.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,21 @@ function getSortWrapper (sort) {
this.ctx.config.retry = NUM_FAILED_TEST_RETRIES
}

let testCodeCoverageLinesTotal

if (this.ctx.coverageProvider?.generateCoverage) {
shimmer.wrap(this.ctx.coverageProvider, 'generateCoverage', generateCoverage => async function () {
const totalCodeCoverage = await generateCoverage.apply(this, arguments)

try {
testCodeCoverageLinesTotal = totalCodeCoverage.getCoverageSummary().lines.pct
} catch (e) {
// ignore errors
}
return totalCodeCoverage
})
}

shimmer.wrap(this.ctx, 'exit', exit => async function () {
let onFinish

Expand All @@ -136,8 +151,9 @@ function getSortWrapper (sort) {
sessionAsyncResource.runInAsyncScope(() => {
testSessionFinishCh.publish({
status: getSessionStatus(this.state),
onFinish,
error
testCodeCoverageLinesTotal,
error,
onFinish
})
})

Expand Down
9 changes: 7 additions & 2 deletions packages/datadog-plugin-vitest/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const {
getTestSuitePath,
getTestSuiteCommonTags,
TEST_SOURCE_FILE,
TEST_IS_RETRY
TEST_IS_RETRY,
TEST_CODE_COVERAGE_LINES_PCT
} = require('../../dd-trace/src/plugins/util/test')
const { COMPONENT } = require('../../dd-trace/src/constants')

Expand Down Expand Up @@ -150,13 +151,17 @@ class VitestPlugin extends CiPlugin {
}
})

this.addSub('ci:vitest:session:finish', ({ status, onFinish, error }) => {
this.addSub('ci:vitest:session:finish', ({ status, onFinish, error, testCodeCoverageLinesTotal }) => {
this.testSessionSpan.setTag(TEST_STATUS, status)
this.testModuleSpan.setTag(TEST_STATUS, status)
if (error) {
this.testModuleSpan.setTag('error', error)
this.testSessionSpan.setTag('error', error)
}
if (testCodeCoverageLinesTotal) {
this.testModuleSpan.setTag(TEST_CODE_COVERAGE_LINES_PCT, testCodeCoverageLinesTotal)
this.testSessionSpan.setTag(TEST_CODE_COVERAGE_LINES_PCT, testCodeCoverageLinesTotal)
}
this.testModuleSpan.finish()
this.testSessionSpan.finish()
finishAllTraceSpans(this.testSessionSpan)
Expand Down

0 comments on commit f53157a

Please sign in to comment.