Skip to content

Commit f6e1481

Browse files
authored
Merge pull request #223 from buildkite-plugins/toote_skipped_and_escaping
Skipped tests and output escaping
2 parents 23eed4e + e478260 commit f6e1481

File tree

8 files changed

+237
-120
lines changed

8 files changed

+237
-120
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ The buildkite annotation context to use. Useful to differentiate multiple runs o
4040

4141
Default: `-(.*).xml`
4242

43-
The regular expression (with capture group) that matches the job UUID in the junit file names. This is used to create the job links in the annotation.
43+
The regular expression (with capture group) that matches the job UUID in the junit file names. This is used to create the job links in the annotation.
4444

4545
To use this, configure your test reporter to embed the `$BUILDKITE_JOB_ID` environment variable into your junit file names. For example `"junit-buildkite-job-$BUILDKITE_JOB_ID.xml"`.
4646

@@ -54,7 +54,7 @@ There are two options for this:
5454
* `file`
5555
* displays: `MyClass::UnderTest text of the failed expectation in path/to/my_class/under_test.file_ext`
5656

57-
### `fail-build-on-error` (optional)
57+
### `fail-build-on-error` (optional)
5858

5959
Default: `false`
6060

@@ -70,6 +70,12 @@ Exit code of the plugin if the call to `buildkite-agent artifact download` fails
7070

7171
Minimum amount of run tests that need to be analyzed or a failure will be reported. It is useful to ensure that tests are actually run and report files to analyze do contain information.
7272

73+
### `report-skipped` (optional, boolean)
74+
75+
Default: `false`
76+
77+
Will add a list of skipped tests at the end of the annotation. Note that even if there are skipped tests, the annotation may not be added unless other options or results of the processing forces it to.
78+
7379
### `report-slowest` (optional)
7480

7581
Default: `0`

hooks/command

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ docker \
5151
--env "BUILDKITE_PLUGIN_JUNIT_ANNOTATE_JOB_UUID_FILE_PATTERN=${BUILDKITE_PLUGIN_JUNIT_ANNOTATE_JOB_UUID_FILE_PATTERN:-}" \
5252
--env "BUILDKITE_PLUGIN_JUNIT_ANNOTATE_FAILURE_FORMAT=${BUILDKITE_PLUGIN_JUNIT_ANNOTATE_FAILURE_FORMAT:-}" \
5353
--env "BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SLOWEST=${BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SLOWEST:-}" \
54+
--env "BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SKIPPED=${BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SKIPPED:-}" \
5455
"${RUBY_IMAGE}" ruby /src/bin/annotate /junits \
5556
> "$annotation_path"
5657

@@ -78,9 +79,9 @@ if [ $has_errors -eq 0 ]; then
7879
echo "Will create annotation anyways"
7980
create_annotation=1
8081
fi
81-
82+
8283
if [[ -e "${annotation_path}" ]]; then
83-
TOTAL_TESTS=$(head -4 "${annotation_path}" | grep 'Total tests' | cut -d\ -f3)
84+
TOTAL_TESTS=$(head -5 "${annotation_path}" | grep 'Total tests' | cut -d\ -f3)
8485
else
8586
TOTAL_TESTS=0
8687
fi
@@ -95,7 +96,7 @@ elif ! check_size; then
9596

9697
# creating a simplified version of the annotation
9798
mv "${annotation_path}" "${annotation_path}2"
98-
head -4 "${annotation_path}2" >"${annotation_path}"
99+
head -5 "${annotation_path}2" >"${annotation_path}"
99100
# || true is to avoid issues if no summary is found
100101
grep '<summary>' "${annotation_path}2" >>"${annotation_path}" || true
101102

plugin.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ configuration:
2424
type: string
2525
min-tests:
2626
type: integer
27+
report-skipped:
28+
type: boolean
2729
report-slowest:
2830
type: integer
2931
ruby-image:

ruby/bin/annotate

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,21 @@ failure_format = ENV['BUILDKITE_PLUGIN_JUNIT_ANNOTATE_FAILURE_FORMAT']
1818
failure_format = 'classname' if !failure_format || failure_format.empty?
1919

2020
report_slowest = ENV['BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SLOWEST'].to_i
21+
report_skipped = ENV['BUILDKITE_PLUGIN_JUNIT_ANNOTATE_REPORT_SKIPPED'] == 'true'
2122

22-
class Failure < Struct.new(:name, :unit_name, :body, :job, :type, :message)
23+
class Failure < Struct.new(:name, :unit_name, :body, :job, :message)
2324
end
2425

2526
class Timing < Struct.new(:name, :unit_name, :time)
2627
end
2728

2829
junit_report_files = Dir.glob(File.join(junits_dir, "**", "*"), File::FNM_DOTMATCH)
2930
testcases = 0
30-
failures = []
31+
tests = {
32+
failure: [],
33+
error: [],
34+
skipped: []
35+
}
3136
timings = []
3237

3338
def text_content(element)
@@ -64,30 +69,27 @@ junit_report_files.sort.each do |file|
6469
unit_name = testcase.attributes[failure_format].to_s
6570
time = testcase.attributes['time'].to_f
6671
timings << Timing.new(name, unit_name, time)
67-
testcase.elements.each("failure") do |failure|
68-
failures << Failure.new(name, unit_name, text_content(failure), job, :failure, message_content(failure))
69-
end
70-
testcase.elements.each("error") do |error|
71-
failures << Failure.new(name, unit_name, text_content(error), job, :error, message_content(error))
72+
testcase.elements.each("failure | error | skipped") do |elem|
73+
tests[elem.name.to_sym] << Failure.new(name, unit_name, text_content(elem), job, message_content(elem))
7274
end
7375
end
7476
end
7577

7678
STDERR.puts "--- ✍️ Preparing annotation"
7779

78-
failures_count = failures.select {|f| f.type == :failure }.length
79-
errors_count = failures.select {|f| f.type == :error }.length
80-
81-
puts "Failures: #{failures_count}"
82-
puts "Errors: #{errors_count}"
80+
puts "Failures: #{tests[:failure].length}"
81+
puts "Errors: #{tests[:error].length}"
82+
puts "Skipped: #{tests[:skipped].length}"
8383
puts "Total tests: #{testcases}"
8484

85-
failures.each do |failure|
85+
skipped = tests.delete(:skipped) # save value for later
86+
87+
tests.values.flatten.each do |failure|
8688
puts ""
8789
puts "<details>"
88-
puts "<summary><code>#{failure.name} in #{failure.unit_name}</code></summary>\n\n"
90+
puts "<summary><code>#{CGI.escapeHTML failure.name} in #{CGI.escapeHTML failure.unit_name}</code></summary>\n\n"
8991
if failure.message
90-
puts "<p>#{failure.message.chomp.strip}</p>\n\n"
92+
puts "<p>#{CGI.escapeHTML failure.message.chomp.strip}</p>\n\n"
9193
end
9294
if failure.body
9395
puts "<pre><code>#{CGI.escapeHTML(failure.body.chomp.strip)}</code></pre>\n\n"
@@ -114,4 +116,17 @@ if report_slowest > 0
114116
puts "</details>"
115117
end
116118

117-
exit 64 if failures.any? # special exit code to signal test failures
119+
if report_skipped
120+
STDERR.puts "Reporting skipped tests"
121+
puts ""
122+
puts "<details>"
123+
puts "<summary>#{skipped.length} tests skipped</summary>\n\n"
124+
puts "<ol>"
125+
skipped.each do |sk|
126+
puts "<li>#{CGI.escapeHTML sk.name} in #{CGI.escapeHTML sk.unit_name} (#{CGI.escapeHTML sk.message || "no reason"})</li>\n"
127+
end
128+
puts "</ol>"
129+
puts "</details>"
130+
end
131+
132+
exit 64 if tests.values.flatten.any? # special exit code to signal test failures

0 commit comments

Comments
 (0)