Skip to content

Commit

Permalink
[ci-visibility] Fix test source file to be relative to the repository…
Browse files Browse the repository at this point in the history
… root (#4030)
  • Loading branch information
juan-fernandez authored and tlhunter committed Feb 12, 2024
1 parent 53fb7cd commit a68a248
Show file tree
Hide file tree
Showing 15 changed files with 120 additions and 60 deletions.
5 changes: 5 additions & 0 deletions integration-tests/ci-visibility.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const {
TEST_ITR_SKIPPING_COUNT,
TEST_ITR_UNSKIPPABLE,
TEST_ITR_FORCED_RUN,
TEST_SOURCE_FILE,
TEST_IS_NEW,
TEST_EARLY_FLAKE_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED,
Expand Down Expand Up @@ -811,6 +812,10 @@ testFrameworks.forEach(({
assert.propertyVal(testSpan.meta, 'test.customtag2', 'customvalue2')
})

testSpans.forEach(testSpan => {
assert.equal(testSpan.meta[TEST_SOURCE_FILE].startsWith('ci-visibility/test/ci-visibility-test'), true)
})

done()
})

Expand Down
32 changes: 5 additions & 27 deletions integration-tests/cucumber/cucumber.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ const {
TEST_ITR_SKIPPING_COUNT,
TEST_CODE_COVERAGE_LINES_PCT,
TEST_ITR_FORCED_RUN,
TEST_ITR_UNSKIPPABLE
TEST_ITR_UNSKIPPABLE,
TEST_SOURCE_FILE
} = require('../../packages/dd-trace/src/plugins/util/test')

const hookFile = 'dd-trace/loader-hook.mjs'
const isOldNode = semver.satisfies(process.version, '<=16')
const versions = ['7.0.0', isOldNode ? '9' : 'latest']

Expand All @@ -43,19 +43,6 @@ const moduleType = [
`ci-visibility/features/farewell.feature --parallel 2 --publish-quiet`,
featuresPath: 'ci-visibility/features/',
fileExtension: 'js'
},
{
type: 'esm',
runTestsCommand: `node --loader=${hookFile} ./node_modules/.bin/cucumber-js ci-visibility/features-esm/*.feature`,
runTestsWithCoverageCommand:
`./node_modules/nyc/bin/nyc.js -r=text-summary ` +
`node --loader=./node_modules/@istanbuljs/esm-loader-hook/index.js ` +
`--loader=${hookFile} ./node_modules/.bin/cucumber-js ci-visibility/features-esm/*.feature`,
parallelModeCommand:
`node --loader=${hookFile} ./node_modules/.bin/cucumber-js ` +
`ci-visibility/features-esm/farewell.feature --parallel 2 --publish-quiet`,
featuresPath: 'ci-visibility/features-esm/',
fileExtension: 'mjs'
}
]

Expand All @@ -68,24 +55,14 @@ versions.forEach(version => {
featuresPath,
fileExtension
}) => {
// temporary fix for failing esm tests on the CI, skip for now for the release and comeback to solve the issue
if (type === 'esm') {
return
}

// esm support by cucumber was only added on >= 8.0.0
// if (type === 'esm' && semver.satisfies(version, '<8.0.0')) {
// return
// }

// TODO: add esm tests
describe(`cucumber@${version} ${type}`, () => {
let sandbox, cwd, receiver, childProcess
before(async function () {
// add an explicit timeout to make tests less flaky
this.timeout(50000)

sandbox = await createSandbox([`@cucumber/cucumber@${version}`, 'assert',
'nyc', '@istanbuljs/esm-loader-hook'], true)
sandbox = await createSandbox([`@cucumber/cucumber@${version}`, 'assert', 'nyc'], true)
cwd = sandbox.folder
})

Expand Down Expand Up @@ -225,6 +202,7 @@ versions.forEach(version => {
assert.exists(testSuiteId)
assert.equal(testModuleId.toString(10), testModuleEventContent.test_module_id.toString(10))
assert.equal(testSessionId.toString(10), testSessionEventContent.test_session_id.toString(10))
assert.equal(meta[TEST_SOURCE_FILE].startsWith('ci-visibility/features'), true)
// Can read DD_TAGS
assert.propertyVal(meta, 'test.customtag', 'customvalue')
assert.propertyVal(meta, 'test.customtag2', 'customvalue2')
Expand Down
4 changes: 3 additions & 1 deletion integration-tests/cypress/cypress.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const {
TEST_ITR_SKIPPING_COUNT,
TEST_ITR_SKIPPING_TYPE,
TEST_ITR_UNSKIPPABLE,
TEST_ITR_FORCED_RUN
TEST_ITR_FORCED_RUN,
TEST_SOURCE_FILE
} = require('../../packages/dd-trace/src/plugins/util/test')
const { ERROR_MESSAGE } = require('../../packages/dd-trace/src/constants')
const semver = require('semver')
Expand Down Expand Up @@ -282,6 +283,7 @@ moduleType.forEach(({
assert.exists(testSuiteId)
assert.equal(testModuleId.toString(10), testModuleEventContent.test_module_id.toString(10))
assert.equal(testSessionId.toString(10), testSessionEventContent.test_session_id.toString(10))
assert.equal(meta[TEST_SOURCE_FILE].startsWith('cypress/e2e/'), true)
// Can read DD_TAGS
assert.propertyVal(meta, 'test.customtag', 'customvalue')
assert.propertyVal(meta, 'test.customtag2', 'customvalue2')
Expand Down
8 changes: 6 additions & 2 deletions integration-tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,10 @@ async function curlAndAssertMessage (agent, procOrUrl, fn, timeout, expectedMess
}

function getCiVisAgentlessConfig (port) {
// We remove GITHUB_WORKSPACE so the repository root is not assigned to dd-trace-js
const { GITHUB_WORKSPACE, ...rest } = process.env
return {
...process.env,
...rest,
DD_API_KEY: '1',
DD_CIVISIBILITY_AGENTLESS_ENABLED: 1,
DD_CIVISIBILITY_AGENTLESS_URL: `http://127.0.0.1:${port}`,
Expand All @@ -283,8 +285,10 @@ function getCiVisAgentlessConfig (port) {
}

function getCiVisEvpProxyConfig (port) {
// We remove GITHUB_WORKSPACE so the repository root is not assigned to dd-trace-js
const { GITHUB_WORKSPACE, ...rest } = process.env
return {
...process.env,
...rest,
DD_TRACE_AGENT_PORT: port,
NODE_OPTIONS: '-r dd-trace/ci/init',
DD_CIVISIBILITY_AGENTLESS_ENABLED: '0'
Expand Down
10 changes: 9 additions & 1 deletion integration-tests/playwright/playwright.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ const {
} = require('../helpers')
const { FakeCiVisIntake } = require('../ci-visibility-intake')
const webAppServer = require('../ci-visibility/web-app-server')
const { TEST_STATUS, TEST_SOURCE_START, TEST_TYPE } = require('../../packages/dd-trace/src/plugins/util/test')
const {
TEST_STATUS,
TEST_SOURCE_START,
TEST_TYPE,
TEST_SOURCE_FILE
} = require('../../packages/dd-trace/src/plugins/util/test')

const versions = ['1.18.0', 'latest']

Expand Down Expand Up @@ -99,6 +104,9 @@ versions.forEach((version) => {

testEvents.forEach(testEvent => {
assert.exists(testEvent.content.metrics[TEST_SOURCE_START])
assert.equal(
testEvent.content.meta[TEST_SOURCE_FILE].startsWith('ci-visibility/playwright-tests/'), true
)
// Can read DD_TAGS
assert.propertyVal(testEvent.content.meta, 'test.customtag', 'customvalue')
assert.propertyVal(testEvent.content.meta, 'test.customtag2', 'customvalue2')
Expand Down
20 changes: 10 additions & 10 deletions packages/datadog-instrumentations/src/cucumber.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ function wrapRun (pl, isLatestVersion) {

const asyncResource = new AsyncResource('bound-anonymous-fn')
return asyncResource.runInAsyncScope(() => {
const testSuiteFullPath = this.pickle.uri
const testFileAbsolutePath = this.pickle.uri

if (!pickleResultByFile[testSuiteFullPath]) { // first test in suite
if (!pickleResultByFile[testFileAbsolutePath]) { // first test in suite
isUnskippable = isMarkedAsUnskippable(this.pickle)
const testSuitePath = getTestSuitePath(testSuiteFullPath, process.cwd())
const testSuitePath = getTestSuitePath(testFileAbsolutePath, process.cwd())
isForcedToRun = isUnskippable && skippableSuites.includes(testSuitePath)

testSuiteStartCh.publish({ testSuitePath, isUnskippable, isForcedToRun, itrCorrelationId })
Expand All @@ -113,7 +113,7 @@ function wrapRun (pl, isLatestVersion) {

testStartCh.publish({
testName: this.pickle.name,
fullTestSuite: testSuiteFullPath,
testFileAbsolutePath,
testSourceLine
})
try {
Expand All @@ -123,21 +123,21 @@ function wrapRun (pl, isLatestVersion) {
const { status, skipReason, errorMessage } = isLatestVersion
? getStatusFromResultLatest(result) : getStatusFromResult(result)

if (!pickleResultByFile[testSuiteFullPath]) {
pickleResultByFile[testSuiteFullPath] = [status]
if (!pickleResultByFile[testFileAbsolutePath]) {
pickleResultByFile[testFileAbsolutePath] = [status]
} else {
pickleResultByFile[testSuiteFullPath].push(status)
pickleResultByFile[testFileAbsolutePath].push(status)
}
testFinishCh.publish({ status, skipReason, errorMessage })
// last test in suite
if (pickleResultByFile[testSuiteFullPath].length === pickleByFile[testSuiteFullPath].length) {
const testSuiteStatus = getSuiteStatusFromTestStatuses(pickleResultByFile[testSuiteFullPath])
if (pickleResultByFile[testFileAbsolutePath].length === pickleByFile[testFileAbsolutePath].length) {
const testSuiteStatus = getSuiteStatusFromTestStatuses(pickleResultByFile[testFileAbsolutePath])
if (global.__coverage__) {
const coverageFiles = getCoveredFilenamesFromCoverage(global.__coverage__)

testSuiteCodeCoverageCh.publish({
coverageFiles,
suiteFile: testSuiteFullPath
suiteFile: testFileAbsolutePath
})
// We need to reset coverage to get a code coverage per suite
// Before that, we preserve the original coverage
Expand Down
3 changes: 3 additions & 0 deletions packages/datadog-instrumentations/src/jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
const rootDir = config.globalConfig ? config.globalConfig.rootDir : config.rootDir
this.rootDir = rootDir
this.testSuite = getTestSuitePath(context.testPath, rootDir)
this.testFileAbsolutePath = context.testPath
this.nameToParams = {}
this.global._ddtrace = global._ddtrace

Expand Down Expand Up @@ -194,6 +195,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
testStartCh.publish({
name: removeEfdTestName(testName),
suite: this.testSuite,
testFileAbsolutePath: this.testFileAbsolutePath,
runner: 'jest-circus',
testParameters,
frameworkVersion: jestVersion,
Expand Down Expand Up @@ -244,6 +246,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
testSkippedCh.publish({
name: getJestTestName(event.test),
suite: this.testSuite,
testFileAbsolutePath: this.testFileAbsolutePath,
runner: 'jest-circus',
frameworkVersion: jestVersion,
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
Expand Down
19 changes: 12 additions & 7 deletions packages/datadog-plugin-cucumber/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const {
TEST_ITR_UNSKIPPABLE,
TEST_ITR_FORCED_RUN,
TEST_CODE_OWNERS,
ITR_CORRELATION_ID
ITR_CORRELATION_ID,
TEST_SOURCE_FILE
} = require('../../dd-trace/src/plugins/util/test')
const { RESOURCE_NAME } = require('../../../ext/tags')
const { COMPONENT, ERROR_MESSAGE } = require('../../dd-trace/src/constants')
Expand Down Expand Up @@ -122,7 +123,7 @@ class CucumberPlugin extends CiPlugin {
}

const relativeCoverageFiles = [...coverageFiles, suiteFile]
.map(filename => getTestSuitePath(filename, this.sourceRoot))
.map(filename => getTestSuitePath(filename, this.repositoryRoot))

this.telemetry.distribution(TELEMETRY_CODE_COVERAGE_NUM_FILES, {}, relativeCoverageFiles.length)

Expand All @@ -136,10 +137,11 @@ class CucumberPlugin extends CiPlugin {
this.telemetry.ciVisEvent(TELEMETRY_CODE_COVERAGE_FINISHED, 'suite', { library: 'istanbul' })
})

this.addSub('ci:cucumber:test:start', ({ testName, fullTestSuite, testSourceLine }) => {
this.addSub('ci:cucumber:test:start', ({ testName, testFileAbsolutePath, testSourceLine }) => {
const store = storage.getStore()
const testSuite = getTestSuitePath(fullTestSuite, this.sourceRoot)
const testSpan = this.startTestSpan(testName, testSuite, testSourceLine)
const testSuite = getTestSuitePath(testFileAbsolutePath, this.sourceRoot)
const testSourceFile = getTestSuitePath(testFileAbsolutePath, this.repositoryRoot)
const testSpan = this.startTestSpan(testName, testSuite, testSourceFile, testSourceLine)

this.enter(testSpan, store)
})
Expand Down Expand Up @@ -191,12 +193,15 @@ class CucumberPlugin extends CiPlugin {
})
}

startTestSpan (testName, testSuite, testSourceLine) {
startTestSpan (testName, testSuite, testSourceFile, testSourceLine) {
return super.startTestSpan(
testName,
testSuite,
this.testSuiteSpan,
{ [TEST_SOURCE_START]: testSourceLine }
{
[TEST_SOURCE_START]: testSourceLine,
[TEST_SOURCE_FILE]: testSourceFile
}
)
}
}
Expand Down
13 changes: 12 additions & 1 deletion packages/datadog-plugin-cypress/src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ const {
TEST_SKIPPED_BY_ITR,
TEST_ITR_UNSKIPPABLE,
TEST_ITR_FORCED_RUN,
ITR_CORRELATION_ID
ITR_CORRELATION_ID,
TEST_SOURCE_FILE
} = require('../../dd-trace/src/plugins/util/test')
const { ORIGIN_KEY, COMPONENT } = require('../../dd-trace/src/constants')
const log = require('../../dd-trace/src/log')
Expand Down Expand Up @@ -361,6 +362,11 @@ module.exports = (on, config) => {
cypressTestName === test.name && spec.relative === test.suite
)
const skippedTestSpan = getTestSpan(cypressTestName, spec.relative)
if (spec.absolute && repositoryRoot) {
skippedTestSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
} else {
skippedTestSpan.setTag(TEST_SOURCE_FILE, spec.relative)
}
skippedTestSpan.setTag(TEST_STATUS, 'skip')
if (isSkippedByItr) {
skippedTestSpan.setTag(TEST_SKIPPED_BY_ITR, 'true')
Expand Down Expand Up @@ -392,6 +398,11 @@ module.exports = (on, config) => {
if (itrCorrelationId) {
finishedTest.testSpan.setTag(ITR_CORRELATION_ID, itrCorrelationId)
}
if (spec.absolute && repositoryRoot) {
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, getTestSuitePath(spec.absolute, repositoryRoot))
} else {
finishedTest.testSpan.setTag(TEST_SOURCE_FILE, spec.relative)
}
finishedTest.testSpan.finish(finishedTest.finishTime)
})

Expand Down
13 changes: 9 additions & 4 deletions packages/datadog-plugin-cypress/test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,18 @@ describe('Plugin', function () {
this.timeout(testTimeout)
it('instruments tests', function (done) {
process.env.DD_TRACE_AGENT_PORT = agentListenPort
const testSuiteFolder = semver.intersects(version, '>=10')
? 'app-10' : 'app'

cypressExecutable.run({
project: semver.intersects(version, '>=10')
? './packages/datadog-plugin-cypress/test/app-10' : './packages/datadog-plugin-cypress/test/app',
project: `./packages/datadog-plugin-cypress/test/${testSuiteFolder}`,
config: {
baseUrl: `http://localhost:${appPort}`
},
quiet: true,
headless: true
})

agent.use(traces => {
const passedTestSpan = traces[0][0]
const failedTestSpan = traces[1][0]
Expand All @@ -77,7 +80,8 @@ describe('Plugin', function () {
[TEST_NAME]: 'can visit a page renders a hello world',
[TEST_STATUS]: 'pass',
[TEST_SUITE]: 'cypress/integration/integration-test.js',
[TEST_SOURCE_FILE]: 'cypress/integration/integration-test.js',
[TEST_SOURCE_FILE]:
`packages/datadog-plugin-cypress/test/${testSuiteFolder}/cypress/integration/integration-test.js`,
[TEST_TYPE]: 'browser',
[ORIGIN_KEY]: CI_APP_ORIGIN,
[TEST_IS_RUM_ACTIVE]: 'true',
Expand All @@ -102,7 +106,8 @@ describe('Plugin', function () {
[TEST_NAME]: 'can visit a page will fail',
[TEST_STATUS]: 'fail',
[TEST_SUITE]: 'cypress/integration/integration-test.js',
[TEST_SOURCE_FILE]: 'cypress/integration/integration-test.js',
[TEST_SOURCE_FILE]:
`packages/datadog-plugin-cypress/test/${testSuiteFolder}/cypress/integration/integration-test.js`,
[TEST_TYPE]: 'browser',
[ORIGIN_KEY]: CI_APP_ORIGIN,
[ERROR_TYPE]: 'AssertionError',
Expand Down
21 changes: 20 additions & 1 deletion packages/datadog-plugin-jest/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const {
TEST_ITR_FORCED_RUN,
TEST_CODE_OWNERS,
ITR_CORRELATION_ID,
TEST_SOURCE_FILE,
getTestSuitePath,
TEST_IS_NEW,
TEST_EARLY_FLAKE_IS_RETRY,
TEST_EARLY_FLAKE_IS_ENABLED
Expand Down Expand Up @@ -296,7 +298,17 @@ class JestPlugin extends CiPlugin {
}

startTestSpan (test) {
const { suite, name, runner, testParameters, frameworkVersion, testStartLine, isNew, isEfdRetry } = test
const {
suite,
name,
runner,
testParameters,
frameworkVersion,
testStartLine,
testFileAbsolutePath,
isNew,
isEfdRetry
} = test

const extraTags = {
[JEST_TEST_RUNNER]: runner,
Expand All @@ -306,6 +318,13 @@ class JestPlugin extends CiPlugin {
if (testStartLine) {
extraTags[TEST_SOURCE_START] = testStartLine
}
if (testFileAbsolutePath) {
extraTags[TEST_SOURCE_FILE] = getTestSuitePath(testFileAbsolutePath, this.repositoryRoot)
} else {
// If for whatever we don't have the full path, we'll set the source file to the suite name
extraTags[TEST_SOURCE_FILE] = suite
}

if (isNew) {
extraTags[TEST_IS_NEW] = 'true'
if (isEfdRetry) {
Expand Down
Loading

0 comments on commit a68a248

Please sign in to comment.