@@ -66,9 +66,6 @@ KUBE_COVERMODE=${KUBE_COVERMODE:-atomic}
66
66
# The directory to save test coverage reports to, if generating them. If unset,
67
67
# a semi-predictable temporary directory will be used.
68
68
KUBE_COVER_REPORT_DIR=" ${KUBE_COVER_REPORT_DIR:- } "
69
- # How many 'go test' instances to run simultaneously when running tests in
70
- # coverage mode.
71
- KUBE_COVERPROCS=${KUBE_COVERPROCS:- 4}
72
69
# use KUBE_RACE="" to disable the race detector
73
70
# this is defaulted to "-race" in make test as well
74
71
# NOTE: DO NOT ADD A COLON HERE. KUBE_RACE="" is meaningful!
@@ -133,26 +130,21 @@ done
133
130
shift $(( OPTIND - 1 ))
134
131
135
132
# Use eval to preserve embedded quoted strings.
133
+ #
134
+ # KUBE_TEST_ARGS contains arguments for `go test` (like -short)
135
+ # and may end with `-args <arguments for test binary>`, so it
136
+ # has to be passed to `go test` at the end of the invocation.
136
137
testargs=()
137
138
eval " testargs=(${KUBE_TEST_ARGS:- } )"
138
139
139
- # Used to filter verbose test output.
140
- go_test_grep_pattern=" .*"
141
-
142
- goflags=()
143
- # The junit report tool needs full test case information to produce a
144
- # meaningful report.
145
- if [[ -n " ${KUBE_JUNIT_REPORT_DIR} " ]] ; then
146
- goflags+=(-v)
147
- goflags+=(-json)
148
- # Show only summary lines by matching lines like "status package/test"
149
- go_test_grep_pattern=" ^[^[:space:]]\+[[:space:]]\+[^[:space:]]\+/[^[[:space:]]\+"
150
- fi
151
-
140
+ # gotestsum --format value
141
+ gotestsum_format=standard-quiet
152
142
if [[ -n " ${FULL_LOG:- } " ]] ; then
153
- go_test_grep_pattern= " .* "
143
+ gotestsum_format=standard-verbose
154
144
fi
155
145
146
+ goflags=()
147
+
156
148
# Filter out arguments that start with "-" and move them to goflags.
157
149
testcases=()
158
150
for arg; do
@@ -180,113 +172,78 @@ junitFilenamePrefix() {
180
172
echo " ${KUBE_JUNIT_REPORT_DIR} /junit_$( kube::util::sortable_date) "
181
173
}
182
174
183
- produceJUnitXMLReport () {
184
- local -r junit_filename_prefix=$1
185
- if [[ -z " ${junit_filename_prefix} " ]]; then
186
- return
187
- fi
188
-
189
- local junit_xml_filename
190
- junit_xml_filename=" ${junit_filename_prefix} .xml"
191
-
175
+ installTools () {
192
176
if ! command -v gotestsum > /dev/null 2>&1 ; then
193
177
kube::log::status " gotestsum not found; installing from ./hack/tools"
194
178
go -C " ${KUBE_ROOT} /hack/tools" install gotest.tools/gotestsum
195
179
fi
196
- gotestsum --junitfile " ${junit_xml_filename} " --raw-command cat " ${junit_filename_prefix} " * .stdout
197
- if [[ ! ${KUBE_KEEP_VERBOSE_TEST_OUTPUT} =~ ^[yY]$ ]]; then
198
- rm " ${junit_filename_prefix} " * .stdout
199
- fi
200
180
201
181
if ! command -v prune-junit-xml > /dev/null 2>&1 ; then
202
182
kube::log::status " prune-junit-xml not found; installing from ./cmd"
203
183
go -C " ${KUBE_ROOT} /cmd/prune-junit-xml" install .
204
184
fi
205
- prune-junit-xml " ${junit_xml_filename} "
206
-
207
- kube::log::status " Saved JUnit XML test report to ${junit_xml_filename} "
208
185
}
209
186
210
187
runTests () {
211
188
local junit_filename_prefix
212
189
junit_filename_prefix=$( junitFilenamePrefix)
213
190
214
- # Try to normalize input names.
191
+ installTools
192
+
193
+ # Try to normalize input names. This is slow!
215
194
local -a targets
195
+ kube::log::status " Normalizing Go targets"
216
196
kube::util::read-array targets < <( kube::golang::normalize_go_targets " $@ " )
217
197
218
- # If we're not collecting coverage, run all requested tests with one 'go test'
219
- # command, which is much faster.
220
- if [[ ! ${KUBE_COVER} =~ ^[yY]$ ]]; then
221
- kube::log::status " Running tests without code coverage ${KUBE_RACE: +" and with ${KUBE_RACE} " } "
222
- # shellcheck disable=SC2031
223
- go test " ${goflags[@]: +${goflags[@]} } " \
224
- " ${KUBE_TIMEOUT} " " ${targets[@]} " \
225
- " ${testargs[@]: +${testargs[@]} } " \
226
- | tee ${junit_filename_prefix: +" ${junit_filename_prefix} .stdout" } \
227
- | grep --binary-files=text " ${go_test_grep_pattern} " && rc=$? || rc=$?
228
- produceJUnitXMLReport " ${junit_filename_prefix} "
229
- return " ${rc} "
198
+ # Enable coverage data collection?
199
+ local cover_msg
200
+ local COMBINED_COVER_PROFILE
201
+
202
+ if [[ ${KUBE_COVER} =~ ^[yY]$ ]]; then
203
+ cover_msg=" with code coverage"
204
+ if [[ -z " ${KUBE_COVER_REPORT_DIR} " ]]; then
205
+ cover_report_dir=" /tmp/k8s_coverage/$( kube::util::sortable_date) "
206
+ else
207
+ cover_report_dir=" ${KUBE_COVER_REPORT_DIR} "
208
+ fi
209
+ kube::log::status " Saving coverage output in '${cover_report_dir} '"
210
+ mkdir -p " ${@ +${@/#/ ${cover_report_dir} / } } "
211
+ COMBINED_COVER_PROFILE=" ${cover_report_dir} /combined-coverage.out"
212
+ goflags+=(-cover -covermode=" ${KUBE_COVERMODE} " -coverprofile=" ${COMBINED_COVER_PROFILE} " )
213
+ else
214
+ cover_msg=" without code coverage"
215
+ fi
216
+
217
+ # Keep the raw JSON output in addition to the JUnit file?
218
+ local jsonfile=" "
219
+ if [[ -n " ${junit_filename_prefix} " ]] && [[ ${KUBE_KEEP_VERBOSE_TEST_OUTPUT} =~ ^[yY]$ ]]; then
220
+ jsonfile=" ${junit_filename_prefix} .stdout"
230
221
fi
231
222
232
- kube::log::status " Running tests with code coverage ${KUBE_RACE: +" and with ${KUBE_RACE} " } "
223
+ kube::log::status " Running tests ${cover_msg} ${KUBE_RACE: +" and with ${KUBE_RACE} " } "
224
+ gotestsum --format=" ${gotestsum_format} " \
225
+ --jsonfile=" ${jsonfile} " \
226
+ --junitfile=" ${junit_filename_prefix: +" ${junit_filename_prefix} .xml" } " \
227
+ --raw-command \
228
+ -- \
229
+ go test -json \
230
+ " ${goflags[@]: +${goflags[@]} } " \
231
+ " ${KUBE_TIMEOUT} " \
232
+ " ${targets[@]} " \
233
+ " ${testargs[@]: +${testargs[@]} } " \
234
+ && rc=$? || rc=$?
235
+
236
+ if [[ -n " ${junit_filename_prefix} " ]]; then
237
+ prune-junit-xml " ${junit_filename_prefix} .xml"
238
+ fi
233
239
234
- # Create coverage report directories.
235
- if [[ -z " ${KUBE_COVER_REPORT_DIR} " ]]; then
236
- cover_report_dir=" /tmp/k8s_coverage/$( kube::util::sortable_date) "
237
- else
238
- cover_report_dir=" ${KUBE_COVER_REPORT_DIR} "
240
+ if [[ ${KUBE_COVER} =~ ^[yY]$ ]]; then
241
+ coverage_html_file=" ${cover_report_dir} /combined-coverage.html"
242
+ go tool cover -html=" ${COMBINED_COVER_PROFILE} " -o=" ${coverage_html_file} "
243
+ kube::log::status " Combined coverage report: ${coverage_html_file} "
239
244
fi
240
- cover_profile=" coverage.out" # Name for each individual coverage profile
241
- kube::log::status " Saving coverage output in '${cover_report_dir} '"
242
- mkdir -p " ${@ +${@/#/ ${cover_report_dir} / } } "
243
-
244
- # Run all specified tests, collecting coverage results. Go currently doesn't
245
- # support collecting coverage across multiple packages at once, so we must issue
246
- # separate 'go test' commands for each package and then combine at the end.
247
- # To speed things up considerably, we can at least use xargs -P to run multiple
248
- # 'go test' commands at once.
249
- # To properly parse the test results if generating a JUnit test report, we
250
- # must make sure the output from PARALLEL runs is not mixed. To achieve this,
251
- # we spawn a subshell for each PARALLEL process, redirecting the output to
252
- # separate files.
253
-
254
- printf " %s\n" " ${@ } " \
255
- | xargs -I{} -n 1 -P " ${KUBE_COVERPROCS} " \
256
- bash -c " set -o pipefail; _pkg=\"\$ 0\" ; _pkg_out=\$ {_pkg//\//_}; \
257
- go test ${goflags[*]: +${goflags[*]} } \
258
- ${KUBE_TIMEOUT} \
259
- -cover -covermode=\" ${KUBE_COVERMODE} \" \
260
- -coverprofile=\" ${cover_report_dir} /\$ {_pkg}/${cover_profile} \" \
261
- \"\$ {_pkg}\" \
262
- ${testargs[*]: +${testargs[*]} } \
263
- | tee ${junit_filename_prefix: +\" ${junit_filename_prefix} -\$ _pkg_out.stdout\" } \
264
- | grep \" ${go_test_grep_pattern} \" " \
265
- {} \
266
- && test_result=$? || test_result=$?
267
-
268
- produceJUnitXMLReport " ${junit_filename_prefix} "
269
-
270
- COMBINED_COVER_PROFILE=" ${cover_report_dir} /combined-coverage.out"
271
- {
272
- # The combined coverage profile needs to start with a line indicating which
273
- # coverage mode was used (set, count, or atomic). This line is included in
274
- # each of the coverage profiles generated when running 'go test -cover', but
275
- # we strip these lines out when combining so that there's only one.
276
- echo " mode: ${KUBE_COVERMODE} "
277
-
278
- # Include all coverage reach data in the combined profile, but exclude the
279
- # 'mode' lines, as there should be only one.
280
- while IFS=' ' read -r x; do
281
- grep -h -v " ^mode:" < " ${x} " || true
282
- done < <( find " ${cover_report_dir} " -name " ${cover_profile} " )
283
- } > " ${COMBINED_COVER_PROFILE} "
284
-
285
- coverage_html_file=" ${cover_report_dir} /combined-coverage.html"
286
- go tool cover -html=" ${COMBINED_COVER_PROFILE} " -o=" ${coverage_html_file} "
287
- kube::log::status " Combined coverage report: ${coverage_html_file} "
288
-
289
- return " ${test_result} "
245
+
246
+ return " ${rc} "
290
247
}
291
248
292
249
reportCoverageToCoveralls () {
0 commit comments