Skip to content

Instantly share code, notes, and snippets.

@stufro
Last active April 24, 2023 19:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stufro/71ebea8cc89925837bd42e84bb0c5b5c to your computer and use it in GitHub Desktop.
Save stufro/71ebea8cc89925837bd42e84bb0c5b5c to your computer and use it in GitHub Desktop.
Splitting up cucumber feature files based on number of scenarios
# recursively places features into groups in turn
class CucumberSlicer
def initialize(slices:)
@slices = slices
end
def slice
feature_files = Dir.glob("features/**/*.feature")
sorted_features = feature_files.map { |filepath| [filepath, scenario_count(filepath)] }
.sort_by { |_file, count| count }
.map { |file, _| file }
populate_slices(initialize_slices, 0, sorted_features)
end
private
def scenario_count(filepath)
File.open(filepath).grep(/Scenario:|(?<!Examples:\s)^\s*\|/).count
end
def populate_slices(slices, slice_index, features)
return slices if features.count.zero?
slices[slice_index] << features.pop
populate_slices(slices, (slice_index + 1) % @slices, features)
end
def initialize_slices
Array.new(@slices) { [] }
end
end
# prevents 1 group becoming larger than the others by calculating if the group has space for the number of
# scenarios before placing into the group
class CucumberSlicer
class << self
def slice(num_slices: 5)
feature_filepaths = Dir.glob("features/**/*.feature")
features = gather_features_metadata(feature_filepaths)
average_scenario_count = total_scenario_count(features) / num_slices
slices = initialize_slices(num_slices)
features.each do |feature|
slice = pick_a_slice(slices, feature[:scenario_count], average_scenario_count)
add_feature_to_a_slice(feature, slice)
end
slices.pluck(:feature_filepaths)
end
private
def add_feature_to_a_slice(feature, slice)
slice[:scenario_count] += feature[:scenario_count]
slice[:feature_filepaths] << feature[:feature_filepath]
end
def pick_a_slice(slices, feature_size, target_size)
slices.find { |slice| (slice[:scenario_count] + feature_size) <= (target_size + 1) }
end
def gather_features_metadata(feature_filepaths)
feature_filepaths.map do |feature_filepath|
scenario_count = File.read(feature_filepath).scan(/Scenario:|(?<!Examples:\s)^\s*\|/).count
{ scenario_count:, feature_filepath: }
end
end
def total_scenario_count(features)
features.sum { |feature| feature[:scenario_count] }
end
def initialize_slices(num_slices)
Array.new(num_slices) { { scenario_count: 0, feature_filepaths: [] } }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment