Skip to content

Commit 106f5b2

Browse files
authored
Merge pull request #94 from evandcoleman/feature/collapse-parallelized-tests
Add option to collapse parallel test runs
2 parents 986cd0f + e4f3b10 commit 106f5b2

File tree

4 files changed

+112
-7
lines changed

4 files changed

+112
-7
lines changed

.rubocop.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Style/ClassAndModuleChildren:
2424
Enabled: false
2525

2626
Metrics/AbcSize:
27-
Max: 60
27+
Max: 66
2828

2929
# The %w might be confusing for new users
3030
Style/WordArray:

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ xcode_summary.ignored_results { |result|
107107
}
108108

109109
xcode_summary.report 'MyApp.xcresult'
110+
111+
# When `true`, collapses parallelized test runs of the same target into one line.
112+
# Defaults to `false`.
113+
xcode_summary.collapse_parallelized_tests = true
110114
```
111115

112116
You can use `ignores_warnings` to supress warnings and shows only errors.

lib/xcode_summary/plugin.rb

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ class DangerXcodeSummary < Plugin
8282
# @return [Boolean]
8383
attr_accessor :strict
8484

85+
# Defines if parallelized test runs from the same target should be collapsed into one message.
86+
# Defaults to `false`
87+
# @param [Boolean] value
88+
# @return [Boolean]
89+
attr_accessor :collapse_parallelized_tests
90+
8591
# rubocop:disable Lint/DuplicateMethods
8692
def project_root
8793
root = @project_root || Dir.pwd
@@ -121,6 +127,10 @@ def strict
121127
@strict.nil? || @strict
122128
end
123129

130+
def collapse_parallelized_tests
131+
@collapse_parallelized_tests || false
132+
end
133+
124134
# Pick a Dangerfile plugin for a chosen request_source and cache it
125135
# based on https://github.com/danger/danger/blob/master/lib/danger/plugin_support/plugin.rb#L31
126136
#
@@ -211,26 +221,63 @@ def sort_and_log_warnings(all_warnings)
211221

212222
def messages(xcode_summary)
213223
if test_summary
214-
test_messages = xcode_summary.action_test_plan_summaries.map do |test_plan_summaries|
224+
test_runs = xcode_summary.action_test_plan_summaries.map do |test_plan_summaries|
215225
test_plan_summaries.summaries.map do |summary|
216226
summary.testable_summaries.map do |test_summary|
217227
test_summary.tests.filter_map do |action_test_object|
218228
if action_test_object.instance_of? XCResult::ActionTestSummaryGroup
219229
subtests = action_test_object.all_subtests
220230
subtests_duration = subtests.map(&:duration).sum
221-
test_text_infix = subtests.count == 1 ? 'test' : 'tests'
231+
222232
failed_tests_count = subtests.reject { |test| test.test_status == 'Success' }.count
223233
expected_failed_tests_count = subtests.select { |test| test.test_status == 'Expected Failure' }.count
224234

225-
"#{test_summary.target_name}: Executed #{subtests.count} #{test_text_infix}, " \
226-
"with #{failed_tests_count} failures (#{expected_failed_tests_count} expected) in " \
227-
"#{subtests_duration.round(3)} (#{action_test_object.duration.round(3)}) seconds"
235+
{
236+
target_name: test_summary.target_name,
237+
test_count: subtests.count,
238+
failed_tests_count: failed_tests_count,
239+
expected_failed_tests_count: expected_failed_tests_count,
240+
tests_duration: subtests_duration,
241+
action_duration: action_test_object.duration
242+
}
228243
end
229244
end
230245
end
231246
end
232247
end
233-
test_messages.flatten.uniq.compact.map(&:strip)
248+
249+
flattened_test_runs = test_runs.flatten.uniq.compact
250+
251+
if collapse_parallelized_tests
252+
test_runs_by_target = flattened_test_runs.group_by { |test_run| test_run[:target_name] }
253+
flattened_test_runs = test_runs_by_target.map do |target_name, test_runs|
254+
test_runs.reduce do |acc, test_run|
255+
acc.merge(
256+
test_count: acc[:test_count] + test_run[:test_count],
257+
failed_tests_count: acc[:failed_tests_count] + test_run[:failed_tests_count],
258+
expected_failed_tests_count: acc[:expected_failed_tests_count] + test_run[:expected_failed_tests_count],
259+
tests_duration: acc[:tests_duration] + test_run[:tests_duration],
260+
action_duration: acc[:action_duration] + test_run[:action_duration]
261+
)
262+
end
263+
end
264+
end
265+
266+
test_messages = flattened_test_runs.map do |test_run|
267+
target_name = test_run[:target_name]
268+
test_count = test_run[:test_count]
269+
failed_tests_count = test_run[:failed_tests_count]
270+
expected_failed_tests_count = test_run[:expected_failed_tests_count]
271+
subtests_duration = test_run[:tests_duration]
272+
action_duration = test_run[:action_duration]
273+
test_text_infix = test_count == 1 ? 'test' : 'tests'
274+
275+
"#{target_name}: Executed #{test_count} #{test_text_infix}, " \
276+
"with #{failed_tests_count} failures (#{expected_failed_tests_count} expected) in " \
277+
"#{subtests_duration.round(3)} (#{action_duration.round(3)}) seconds"
278+
end
279+
280+
test_messages.map(&:strip)
234281
else
235282
[]
236283
end

spec/xcode_summary_spec.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,60 @@ module Danger
257257
expect(result).to eq '{"warnings":21,"errors":3}'
258258
end
259259
end
260+
261+
context 'with collapse_parallelized_tests' do
262+
context 'enabled' do
263+
before do
264+
@xcode_summary.collapse_parallelized_tests = true
265+
end
266+
267+
it 'collapses test runs from the same target' do
268+
# Allow for message receiving testing
269+
allow(@xcode_summary).to receive(:message).and_call_original
270+
@xcode_summary.report('spec/fixtures/swiftlint.xcresult')
271+
272+
# Ensure that the plugin received a call to message with the combined test results
273+
expect(@xcode_summary).to have_received(:message).with(/SwiftLintFrameworkTests: Executed .* tests/m, sticky: false)
274+
275+
# The standard test case should only show one message per target, even with parallelized tests
276+
expect(@dangerfile.status_report[:messages].length).to eq(1)
277+
end
278+
end
279+
280+
context 'disabled' do
281+
before do
282+
@xcode_summary.collapse_parallelized_tests = false
283+
end
284+
285+
it 'shows individual test runs for each target' do
286+
@xcode_summary.report('spec/fixtures/swiftlint.xcresult')
287+
288+
# We know from the existing tests that the standard behavior should match
289+
# the test in the "summary" context, with one test run per message
290+
expect(@dangerfile.status_report[:messages]).to eq [
291+
'SwiftLintFrameworkTests: Executed 540 tests, with 1 failures (0 expected) in 114.029 (27.922) seconds'
292+
]
293+
end
294+
end
295+
296+
context 'with default value' do
297+
it 'defaults to disabled behavior' do
298+
# Don't set collapse_parallelized_tests to test the default
299+
# Reset any test_summary setting to ensure clean state
300+
@xcode_summary.test_summary = true
301+
302+
@xcode_summary.report('spec/fixtures/swiftlint.xcresult')
303+
304+
# Default should match the disabled behavior
305+
expect(@dangerfile.status_report[:messages]).to eq [
306+
'SwiftLintFrameworkTests: Executed 540 tests, with 1 failures (0 expected) in 114.029 (27.922) seconds'
307+
]
308+
309+
# Verify the default value is false
310+
expect(@xcode_summary.collapse_parallelized_tests).to eq(false)
311+
end
312+
end
313+
end
260314
end
261315
end
262316

0 commit comments

Comments
 (0)