Skip to content

Commit 3f51136

Browse files
authored
CBG-4852 replace go2xunit with gotestsum (#7754)
1 parent 6355676 commit 3f51136

File tree

2 files changed

+74
-83
lines changed

2 files changed

+74
-83
lines changed

Jenkinsfile

Lines changed: 56 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,9 @@ pipeline {
5252
}
5353
stage('Go Tools') {
5454
steps {
55-
// unhandled error checker
56-
sh 'go install github.com/kisielk/errcheck@latest'
5755
// goveralls is used to send coverprofiles to coveralls.io
5856
sh 'go install github.com/mattn/goveralls@latest'
59-
// Jenkins test reporting tools
60-
sh 'go install github.com/tebeka/go2xunit@latest'
57+
sh 'go install gotest.tools/gotestsum@latest'
6158
}
6259
}
6360
}
@@ -90,89 +87,85 @@ pipeline {
9087
stage('CE') {
9188
when { branch 'main' }
9289
steps {
93-
// Travis-related variables are required as coveralls.io only officially supports a certain set of CI tools.
94-
withEnv(["PATH+GO=${env.GOTOOLS}/bin", "TRAVIS_BRANCH=${env.BRANCH}", "TRAVIS_PULL_REQUEST=${env.CHANGE_ID}", "TRAVIS_JOB_ID=${env.BUILD_NUMBER}"]) {
95-
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ce-unit-tests', description: 'CE Unit Tests Running', status: 'PENDING')
96-
97-
// Build CE coverprofiles
98-
sh '2>&1 go test -shuffle=on -timeout=20m -coverpkg=./... -coverprofile=cover_ce.out -race -count=1 -v ./... > verbose_ce.out.raw || true'
99-
100-
// Print total coverage stats
101-
sh 'go tool cover -func=cover_ce.out | awk \'END{print "Total SG CE Coverage: " $3}\''
102-
103-
sh 'mkdir -p reports'
104-
105-
// strip non-printable characters from the raw verbose test output
106-
sh 'LC_CTYPE=C tr -dc [:print:][:space:] < verbose_ce.out.raw > verbose_ce.out'
107-
108-
// Grab test fail/total counts so we can print them later
109-
sh "grep '\\-\\-\\- PASS: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-pass.count"
110-
sh "grep '\\-\\-\\- FAIL: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-fail.count"
111-
sh "grep '\\-\\-\\- SKIP: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-skip.count"
112-
sh "grep '=== RUN' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-total.count"
113-
script {
90+
script {
91+
// Travis-related variables are required as coveralls.io only officially supports a certain set of CI tools.
92+
withEnv(["PATH+GO=${env.GOTOOLS}/bin", "TRAVIS_BRANCH=${env.BRANCH}", "TRAVIS_PULL_REQUEST=${env.CHANGE_ID}", "TRAVIS_JOB_ID=${env.BUILD_NUMBER}"]) {
93+
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ce-unit-tests', description: 'CE Unit Tests Running', status: 'PENDING')
94+
95+
sh 'mkdir -p reports'
96+
// --junitfile-project-name is used so that Jenkins doesn't collapse CE and EE results together.
97+
def testExitCode = sh(
98+
script: 'gotestsum --junitfile=test-ce.xml --junitfile-project-name CE --junitfile-testcase-classname relative --format standard-verbose -- -shuffle=on -timeout=20m -coverpkg=./... -coverprofile=cover_ce.out -race -count=1 ./... > verbose_ce.out',
99+
returnStatus: true,
100+
)
101+
102+
// convert the junit file to prepend CE- to all test names to differentiate from EE tests
103+
sh '''xmlstarlet ed -u '//testcase/@classname' -x 'concat("CE-", .)' test-ce.xml > reports/test-ce.xml'''
104+
105+
// Print total coverage stats
106+
sh 'go tool cover -func=cover_ce.out | awk \'END{print "Total SG CE Coverage: " $3}\''
107+
108+
// Grab test fail/total counts so we can print them later
109+
sh "grep '\\-\\-\\- PASS: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-pass.count"
110+
sh "grep '\\-\\-\\- FAIL: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-fail.count"
111+
sh "grep '\\-\\-\\- SKIP: ' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-skip.count"
112+
sh "grep '=== RUN' verbose_ce.out | wc -l | awk '{printf \$1}' > test-ce-total.count"
114113
env.TEST_CE_PASS = readFile 'test-ce-pass.count'
115114
env.TEST_CE_FAIL = readFile 'test-ce-fail.count'
116115
env.TEST_CE_SKIP = readFile 'test-ce-skip.count'
117116
env.TEST_CE_TOTAL = readFile 'test-ce-total.count'
118-
}
119117

120-
// Generate junit-formatted test report
121-
script {
122-
try {
123-
sh 'which go2xunit' // check if go2xunit is installed
124-
sh 'go2xunit -fail -suite-name-prefix="CE-" -input verbose_ce.out -output reports/test-ce.xml'
118+
if (testExitCode == 0) {
125119
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ce-unit-tests', description: env.TEST_CE_PASS + '/' + env.TEST_CE_TOTAL + ' passed (' + env.TEST_CE_SKIP + ' skipped)', status: 'SUCCESS')
126-
} catch (Exception e) {
120+
} else {
127121
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ce-unit-tests', description: env.TEST_CE_FAIL + '/' + env.TEST_CE_TOTAL + ' failed (' + env.TEST_CE_SKIP + ' skipped)', status: 'FAILURE')
128122
// archive verbose test logs in the event of a test failure
129123
archiveArtifacts artifacts: 'verbose_ce.out', fingerprint: false
130124
unstable('At least one CE unit test failed')
131125
}
132-
}
133126

134-
// Publish CE coverage to coveralls.io
135-
// Replace covermode values with set just for coveralls to reduce the variability in reports.
136-
sh 'awk \'NR==1{print "mode: set";next} $NF>0{$NF=1} {print}\' cover_ce.out > cover_ce_coveralls.out'
137-
sh 'which goveralls' // check if goveralls is installed
138-
sh 'goveralls -coverprofile=cover_ce_coveralls.out -service=uberjenkins -repotoken=$COVERALLS_TOKEN || true'
127+
// Publish CE coverage to coveralls.io
128+
// Replace covermode values with set just for coveralls to reduce the variability in reports.
129+
sh 'awk \'NR==1{print "mode: set";next} $NF>0{$NF=1} {print}\' cover_ce.out > cover_ce_coveralls.out'
130+
sh 'which goveralls' // check if goveralls is installed
131+
sh 'goveralls -coverprofile=cover_ce_coveralls.out -service=uberjenkins -repotoken=$COVERALLS_TOKEN || true'
132+
}
139133
}
140134
}
141135
}
142136

143137
stage('EE') {
144138
steps {
145-
withEnv(["PATH+GO=${env.GOTOOLS}/bin"]) {
146-
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ee-unit-tests', description: 'EE Unit Tests Running', status: 'PENDING')
147-
148-
// Build EE coverprofiles
149-
sh "2>&1 go test -shuffle=on -timeout=20m -tags ${EE_BUILD_TAG} -coverpkg=./... -coverprofile=cover_ee.out -race -count=1 -v ./... > verbose_ee.out.raw || true"
150-
151-
sh 'go tool cover -func=cover_ee.out | awk \'END{print "Total SG EE Coverage: " $3}\''
152-
153-
sh 'mkdir -p reports'
154-
155-
// strip non-printable characters from the raw verbose test output
156-
sh 'LC_CTYPE=C tr -dc [:print:][:space:] < verbose_ee.out.raw > verbose_ee.out'
157-
158-
// Grab test fail/total counts so we can print them later
159-
sh "grep '\\-\\-\\- PASS: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-pass.count"
160-
sh "grep '\\-\\-\\- FAIL: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-fail.count"
161-
sh "grep '\\-\\-\\- SKIP: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-skip.count"
162-
sh "grep '=== RUN' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-total.count"
163-
script {
139+
script {
140+
withEnv(["PATH+GO=${env.GOTOOLS}/bin"]) {
141+
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ee-unit-tests', description: 'EE Unit Tests Running', status: 'PENDING')
142+
143+
sh 'mkdir -p reports'
144+
// --junitfile-project-name is used so that Jenkins doesn't collapse CE and EE results together.
145+
def testExitCode = sh(
146+
script: "gotestsum --junitfile=test-ee.xml --junitfile-project-name EE --junitfile-testcase-classname relative --format standard-verbose -- -shuffle=on -timeout=20m -tags ${EE_BUILD_TAG} -coverpkg=./... -coverprofile=cover_ee.out -race -count=1 ./... 2>&1 > verbose_ee.out",
147+
returnStatus: true,
148+
)
149+
150+
// convert the junit file to prepend EE- to all test names to differentiate from EE tests
151+
sh '''xmlstarlet ed -u '//testcase/@classname' -x 'concat("EE-", .)' test-ee.xml > reports/test-ee.xml'''
152+
153+
sh 'go tool cover -func=cover_ee.out | awk \'END{print "Total SG EE Coverage: " $3}\''
154+
155+
// Grab test fail/total counts so we can print them later
156+
sh "grep '\\-\\-\\- PASS: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-pass.count"
157+
sh "grep '\\-\\-\\- FAIL: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-fail.count"
158+
sh "grep '\\-\\-\\- SKIP: ' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-skip.count"
159+
sh "grep '=== RUN' verbose_ee.out | wc -l | awk '{printf \$1}' > test-ee-total.count"
164160
env.TEST_EE_PASS = readFile 'test-ee-pass.count'
165161
env.TEST_EE_FAIL = readFile 'test-ee-fail.count'
166162
env.TEST_EE_SKIP = readFile 'test-ee-skip.count'
167163
env.TEST_EE_TOTAL = readFile 'test-ee-total.count'
168-
}
169164

170-
// Generate junit-formatted test report
171-
script {
172-
try {
173-
sh 'go2xunit -fail -suite-name-prefix="EE-" -input verbose_ee.out -output reports/test-ee.xml'
165+
// Generate junit-formatted test report
166+
if (testExitCode == 0) {
174167
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ee-unit-tests', description: env.TEST_EE_PASS + '/' + env.TEST_EE_TOTAL + ' passed (' + env.TEST_EE_SKIP + ' skipped)', status: 'SUCCESS')
175-
} catch (Exception e) {
168+
} else {
176169
githubNotify(credentialsId: "${GH_ACCESS_TOKEN_CREDENTIAL}", context: 'sgw-pipeline-ee-unit-tests', description: env.TEST_EE_FAIL + '/' + env.TEST_EE_TOTAL + ' failed (' + env.TEST_EE_SKIP + ' skipped)', status: 'FAILURE')
177170
// archive verbose test logs in the event of a test failure
178171
archiveArtifacts artifacts: 'verbose_ee.out', fingerprint: false

jenkins-integration-build.sh

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,10 @@ if [ "${USE_GO_MODULES:-}" == "false" ]; then
5656
go get -u -v github.com/axw/gocov/gocov
5757
go get -u -v github.com/AlekSi/gocov-xml
5858
else
59-
# Install tools to use after job has completed
60-
# go2xunit will fail with 1.23 with name mismatch (try disabling parallel mode), but without any t.Parallel()
61-
go install golang.org/dl/go1.22.8@latest
62-
~/go/bin/go1.22.8 download
63-
~/go/bin/go1.22.8 install -v github.com/tebeka/go2xunit@latest
64-
go install -v github.com/axw/gocov/gocov@latest
65-
go install -v github.com/AlekSi/gocov-xml@latest
59+
# Install tools to use
60+
go install github.com/axw/gocov/gocov@latest
61+
go install github.com/AlekSi/gocov-xml@latest
62+
go install gotest.tools/gotestsum@latest
6663
fi
6764

6865
if [ "${SG_TEST_X509:-}" == "true" -a "${COUCHBASE_SERVER_PROTOCOL}" != "couchbases" ]; then
@@ -77,7 +74,7 @@ INT_LOG_FILE_NAME="verbose_int"
7774
if [ -d "godeps" ]; then
7875
export GOPATH=$(pwd)/godeps
7976
fi
80-
export PATH=$PATH:$(go env GOPATH)/bin
77+
export PATH=$PATH:$(go env GOPATH)/bin:~/go/bin
8178
echo "PATH: $PATH"
8279

8380
if [ "${TEST_DEBUG:-}" == "true" ]; then
@@ -109,10 +106,15 @@ if [ "${SG_TEST_PROFILE_FREQUENCY:-}" == "true" ]; then
109106
fi
110107

111108
if [ "${RUN_WALRUS}" == "true" ]; then
109+
set +e
112110
# EE
113-
go test -coverprofile=coverage_walrus_ee.out -coverpkg=github.com/couchbase/sync_gateway/... -tags cb_sg_devmode,cb_sg_enterprise $GO_TEST_FLAGS github.com/couchbase/sync_gateway/${TARGET_PACKAGE} > verbose_unit_ee.out.raw 2>&1 | true
111+
gotestsum --junitfile=rosmar-ee.xml --junitfile-project-name rosmar-EE --junitfile-testcase-classname relative --format standard-verbose -- -coverprofile=coverage_walrus_ee.out -coverpkg=github.com/couchbase/sync_gateway/... -tags cb_sg_devmode,cb_sg_enterprise $GO_TEST_FLAGS github.com/couchbase/sync_gateway/${TARGET_PACKAGE} > verbose_unit_ee.out 2>&1
112+
xmlstarlet ed -u '//testcase/@classname' -x 'concat("rosmar-EE-", .)' rosmar-ee.xml > verbose_unit_ee.xml
114113
# CE
115-
go test -coverprofile=coverage_walrus_ce.out -coverpkg=github.com/couchbase/sync_gateway/... -tags cb_sg_devmode $GO_TEST_FLAGS github.com/couchbase/sync_gateway/${TARGET_PACKAGE} > verbose_unit_ce.out.raw 2>&1 | true
114+
gotestsum --junitfile=rosmar-ce.xml --junitfile-project-name rosmar-CE --junitfile-testcase-classname relative --format standard-verbose -- -coverprofile=coverage_walrus_ce.out -coverpkg=github.com/couchbase/sync_gateway/... -tags cb_sg_devmode $GO_TEST_FLAGS github.com/couchbase/sync_gateway/${TARGET_PACKAGE} > verbose_unit_ce.out 2>&1
115+
xmlstarlet ed -u '//testcase/@classname' -x 'concat("rosmar-CE-", .)' rosmar-ce.xml > verbose_unit_ce.xml
116+
set -e
117+
116118
fi
117119

118120
# Run CBS
@@ -141,26 +143,22 @@ else
141143
GO_TEST_FLAGS="${GO_TEST_FLAGS} -tags cb_sg_devmode"
142144
fi
143145

144-
go test ${GO_TEST_FLAGS} -coverprofile=coverage_int.out -coverpkg=github.com/couchbase/sync_gateway/... github.com/couchbase/sync_gateway/${TARGET_PACKAGE} 2>&1 | stdbuf -oL tee "${INT_LOG_FILE_NAME}.out.raw" | stdbuf -oL grep -a -E '(--- (FAIL|PASS|SKIP):|github.com/couchbase/sync_gateway(/.+)?\t|TEST: |panic: )'
146+
gotestsum --junitfile=integration.xml --junitfile-project-name integration --junitfile-testcase-classname relative --format standard-verbose -- ${GO_TEST_FLAGS} -coverprofile=coverage_int.out -coverpkg=github.com/couchbase/sync_gateway/... github.com/couchbase/sync_gateway/${TARGET_PACKAGE} 2>&1 | stdbuf -oL tee "${INT_LOG_FILE_NAME}.out" | stdbuf -oL grep -a -E '(--- (FAIL|PASS|SKIP):|github.com/couchbase/sync_gateway(/.+)?\t|TEST: |panic: )'
145147
if [ "${PIPESTATUS[0]}" -ne "0" ]; then # If test exit code is not 0 (failed)
146148
echo "Go test failed! Parsing logs to find cause..."
147149
TEST_FAILED=true
148150
fi
149151

150152
# Collect CBS logs if server error occurred
151-
if [ "${SG_CBCOLLECT_ALWAYS:-}" == "true" ] || grep -a -q "server logs for details\|Timed out after 1m0s waiting for a bucket to become available" "${INT_LOG_FILE_NAME}.out.raw"; then
153+
if [ "${SG_CBCOLLECT_ALWAYS:-}" == "true" ] || grep -a -q "server logs for details\|Timed out after 1m0s waiting for a bucket to become available" "${INT_LOG_FILE_NAME}.out"; then
152154
docker exec -t couchbase /opt/couchbase/bin/cbcollect_info /workspace/cbcollect.zip
153155
fi
154156

155-
# Generate xunit test report that can be parsed by the JUnit Plugin
156-
LC_CTYPE=C tr -dc [:print:][:space:] < ${INT_LOG_FILE_NAME}.out.raw > ${INT_LOG_FILE_NAME}.out # Strip non-printable characters
157-
~/go/bin/go2xunit -input "${INT_LOG_FILE_NAME}.out" -output "${INT_LOG_FILE_NAME}.xml"
157+
# If rosmar tests were run, then prepend classname with integration to tell them apart
158158
if [ "${RUN_WALRUS}" == "true" ]; then
159-
# Strip non-printable characters before xml creation
160-
LC_CTYPE=C tr -dc [:print:][:space:] < "verbose_unit_ee.out.raw" > "verbose_unit_ee.out"
161-
LC_CTYPE=C tr -dc [:print:][:space:] < "verbose_unit_ce.out.raw" > "verbose_unit_ce.out"
162-
~/go/bin/go2xunit -input "verbose_unit_ee.out" -output "verbose_unit_ee.xml"
163-
~/go/bin/go2xunit -input "verbose_unit_ce.out" -output "verbose_unit_ce.xml"
159+
xmlstarlet ed -u '//testcase/@classname' -x 'concat("integration-EE-", .)' integration.xml > "${INT_LOG_FILE_NAME}.xml"
160+
else
161+
cp integration.xml "${INT_LOG_FILE_NAME}.xml"
164162
fi
165163

166164
# Get coverage

0 commit comments

Comments
 (0)