11# frozen_string_literal: true
22module ParallelTests
33 class Grouper
4+ BY_SCENARIOS_SUPPORTED_OPTIONS = [ :single_process_tag ] . freeze
5+
46 class << self
57 def by_steps ( tests , num_groups , options )
68 features_with_steps = group_by_features_with_steps ( tests , options )
@@ -9,20 +11,16 @@ def by_steps(tests, num_groups, options)
911
1012 def by_scenarios ( tests , num_groups , options = { } )
1113 scenarios = group_by_scenarios ( tests , options )
12- in_even_groups_by_size ( scenarios , num_groups )
14+ in_even_groups_by_size ( scenarios , num_groups , options . slice ( BY_SCENARIOS_SUPPORTED_OPTIONS ) )
1315 end
1416
1517 def in_even_groups_by_size ( items , num_groups , options = { } )
1618 groups = Array . new ( num_groups ) { { items : [ ] , size : 0 } }
1719
1820 return specify_groups ( items , num_groups , options , groups ) if options [ :specify_groups ]
1921
20- # add all files that should run in a single process to one group
21- single_process_patterns = options [ :single_process ] || [ ]
22-
23- single_items , items = items . partition do |item , _size |
24- single_process_patterns . any? { |pattern | item =~ pattern }
25- end
22+ # add all files/scenarios that should run in a single process to one group
23+ single_items , items = separate_single_items ( items , options )
2624
2725 isolate_count = isolate_count ( options )
2826
@@ -41,7 +39,7 @@ def in_even_groups_by_size(items, num_groups, options = {})
4139 group_features_by_size ( items_to_group ( items ) , groups [ isolate_count ..-1 ] )
4240 else
4341 # add all files that should run in a single non-isolated process to first group
44- single_items . each { | item , size | add_to_group ( groups . first , item , size ) }
42+ group_features_by_size ( items_to_group ( single_items ) , [ groups . first ] )
4543
4644 # group all by size
4745 group_features_by_size ( items_to_group ( items ) , groups )
@@ -129,6 +127,22 @@ def group_by_scenarios(tests, options = {})
129127 ParallelTests ::Cucumber ::Scenarios . all ( tests , options )
130128 end
131129
130+ def separate_single_items ( items , options )
131+ items . partition { |item , _size | to_single_items? ( item , options ) }
132+ end
133+
134+ def to_single_items? ( item , options )
135+ if options [ :single_process ]
136+ options [ :single_process ] . any? { |pattern | item =~ pattern }
137+ elsif options [ :single_process_tag ]
138+ raise "--single-tag option can be used only with '--group-by scenarios'" unless item_with_tags? ( item )
139+ item_tags = item [ 1 ]
140+ item_tags . any? { |tag | tag . match? ( options [ :single_process_tag ] ) }
141+ else
142+ false
143+ end
144+ end
145+
132146 def group_features_by_size ( items , groups_to_fill )
133147 items . each do |item , size |
134148 size ||= 1
@@ -138,7 +152,30 @@ def group_features_by_size(items, groups_to_fill)
138152 end
139153
140154 def items_to_group ( items )
141- items . first && items . first . size == 2 ? largest_first ( items ) : items
155+ return items_without_tags ( items ) if items_with_tags? ( items )
156+ return largest_first ( items ) if items_with_size? ( items )
157+
158+ items
159+ end
160+
161+ def items_with_tags? ( items )
162+ items . first . is_a? ( Array ) && item_with_tags? ( items . first )
163+ end
164+
165+ def items_with_size? ( items )
166+ items . first . is_a? ( Array ) && item_with_size? ( items . first )
167+ end
168+
169+ def item_with_tags? ( item )
170+ item [ 1 ] . is_a? ( Array )
171+ end
172+
173+ def item_with_size? ( item )
174+ item [ 1 ] . is_a? ( Numeric )
175+ end
176+
177+ def items_without_tags ( items )
178+ items . map ( &:first )
142179 end
143180 end
144181 end
0 commit comments