flakey_spec_catcher 0.9.2 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 924bcd5b7fe71399bc43663478b9b238731e9920e4fcc8c54ba8977a345ee065
4
- data.tar.gz: '080682849736c9d46acd6eeeb8ccc8e98115fb9558004e821f4beed33dfd455e'
3
+ metadata.gz: 6afbdca4bb65ca89de114e1dcfbdbffb93e5dbfbe7f39cc4c4511e018f422bf3
4
+ data.tar.gz: 3e6b37e7f310e74b2711139e6d45b94028d22a3624e7bcd08494e8bef49bc26a
5
5
  SHA512:
6
- metadata.gz: 68cf5c4b41ae6b158a501bab2a6134a40dd1d0ca3d7ce26452948b986ddf713d443458643d2a27a8ff565b9856c647867630015c78dc2f9e7784bf31b0d772e4
7
- data.tar.gz: cee42fcbf243eaa03e56745491515ae7580e2e7974d751faef5f2387c40f07cb20b9f225d188e04009950b7cfd339720e406b789f4e7fa2ec537c2c109b81c18
6
+ metadata.gz: d37a8bfaffe6c700ce2f748b96cac49838db1bbb45f4f96d50b87029f13b01e57507e08e939f9316e7ec3a523ed6d2b34ab0f1d090e461e5405442cad588f565
7
+ data.tar.gz: b84ce73838ec8ff524c444a207627eadefd15f91dd9b7358493280e562c0eadd1a85a72aca6c2a8072d95e9f26e2b3965983389aeb7ac384876a40ec5a737079
data/README.md CHANGED
@@ -152,9 +152,14 @@ FSC_USAGE_PATTERNS = '{ spec/ui => bundle exec rspec }, { spec/api => parallel_r
152
152
  ```
153
153
  -t, --test=TEST_NAME Specify one or more specs in comma separated list
154
154
  -u, --usage=USAGE Specify a re-run usage for the manual re-run
155
+ --use-parent Use the parent of commit for git diff instead of the Head of SCM
155
156
  -r, --repeat=REPEAT_FACTOR Specify a repeat factor for the manual re-run(s)
156
157
  -e, --excluded-tags=EXCLUDED Specify tags to exclude in a comma separated list
157
158
  -o, --output=PATH_TO_OUTPUT Direct all re-run output to a specific file
159
+ --node-total Specify now many nodes the run is being split into
160
+ --node-index Specify the index this node represents in a split run
161
+ -d, --dry-run Performs all setup but doesn't run any tests
162
+ --dry-run-quiet Prints list of tests to be run
158
163
  -v, --version Prints current flakey_spec_catcher_version
159
164
  -h, --help Displays available flakey_spec_catcher cli overrides
160
165
  ```
@@ -195,6 +200,36 @@ flakey_spec_catcher --test='api/spec/*_spec.rb' --usage='bundle exec parallel_rs
195
200
  flakey_spec_catcher --test='api/spec/admin_spec.rb' --repeat='10' --usage='rspec'
196
201
  ```
197
202
 
203
+ ### Running on multiple nodes:
204
+
205
+ If there are a lot of tests required to be checked, then you may want to run the
206
+ tests on multiple nodes. this can be done with the combination of the `--node-total`
207
+ and `--node-index` arguments.
208
+
209
+ Usage Examples:
210
+ ```sh
211
+ # if you have 30 tests to run
212
+
213
+ # this will be tests 0-9
214
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=0
215
+ # this will be tests 10-19
216
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=1
217
+ # this will be tests 20-29
218
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=2
219
+ ```
220
+
221
+ Note that the last node may have a different number of tests that it runs:
222
+ ```sh
223
+ # if you have 20 tests to run
224
+
225
+ # this will be tests 0-6 (7 tests)
226
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=0
227
+ # this will be tests 7-13 (7 tests)
228
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=1
229
+ # this will be tests 14-19 (6 tests)
230
+ bundle exec flakey_spec_catcher --node-total=3 --node-index=2
231
+ ```
232
+
198
233
  ### Additional Git Detection Examples
199
234
 
200
235
  ```sh
@@ -9,4 +9,6 @@ if app.user_config.enable_runs
9
9
  app.show_settings
10
10
  app.rerun_preview
11
11
  exit app.run_specs
12
+ elsif app.user_config.dry_run
13
+ app.show_test_list
12
14
  end
@@ -7,14 +7,16 @@ module FlakeySpecCatcher
7
7
  #
8
8
  # Captures command line arguments for manual re-runs
9
9
  class CliOverride
10
- attr_reader :rerun_patterns, :rerun_usage, :repeat_factor, :enable_runs, :excluded_tags, :use_parent
11
- attr_reader :output_file
10
+ attr_reader :rerun_patterns, :rerun_usage, :repeat_factor, :enable_runs, :excluded_tags, :use_parent, :dry_run
11
+ attr_reader :output_file, :split_nodes, :split_index
12
12
 
13
13
  def initialize
14
+ @dry_run = false
14
15
  @enable_runs = true
15
16
  @excluded_tags = []
16
17
  @use_parent = false
17
18
  parse_command_line_args
19
+ validate_arguments
18
20
  end
19
21
 
20
22
  private
@@ -36,15 +38,20 @@ module FlakeySpecCatcher
36
38
  end
37
39
 
38
40
  opts.on('-u', '--usage=USAGE', 'Specify a re-run usage for the manual re-run') do |usage|
39
- raise ArgumentError if @rerun_patterns.nil?
40
-
41
41
  @rerun_usage = remove_formatter_quotes(usage)
42
42
  end
43
43
 
44
+ opts.on('--node-total=SPLIT_NODES', 'Specify now many nodes the run is being split into') do |nodes|
45
+ @split_nodes = remove_formatter_quotes(nodes).to_i
46
+ end
47
+
48
+ opts.on('--node-index=SPLIT_INDEX', 'Specify the index this node represents in a split run') do |index|
49
+ @split_index = remove_formatter_quotes(index).to_i
50
+ end
51
+
44
52
  opts.on('-r', '--repeat=REPEAT_FACTOR',
45
53
  'Specify a repeat factor for the manual re-run(s)') do |repeat|
46
- parsed_repeat_factor = remove_formatter_quotes(repeat).to_i
47
- @repeat_factor = parsed_repeat_factor if parsed_repeat_factor.positive?
54
+ @repeat_factor = remove_formatter_quotes(repeat).to_i
48
55
  end
49
56
 
50
57
  opts.on('-e', '--excluded-tags=EXCLUDED_TAGS',
@@ -62,12 +69,36 @@ module FlakeySpecCatcher
62
69
  @enable_runs = false
63
70
  end
64
71
 
72
+ opts.on('-d', '--dry-run', "Performs all setup but doesn't run any tests") do
73
+ @dry_run = true
74
+ end
75
+
76
+ opts.on('--dry-run-quiet', 'Prints list of tests to be run') do
77
+ @enable_runs = false
78
+ @dry_run = true
79
+ end
80
+
65
81
  opts.on('-h', '--help', 'Displays available flakey_spec_catcher cli overrides') do
66
82
  puts opts
67
83
  @enable_runs = false
68
84
  end
69
85
  end.parse!
70
86
  end
87
+
88
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
89
+ def validate_arguments
90
+ if !@rerun_usage.nil? && @rerun_patterns.nil?
91
+ raise ArgumentError, 'rerun usage can only be specified with rerun patterns'
92
+ end
93
+ raise ArgumentError, 'repeat factor must be positive' if !@repeat_factor.nil? && @repeat_factor.negative?
94
+ raise ArgumentError, 'split index and split nodes must be specified together' if @split_nodes.nil? != @split_index.nil?
95
+
96
+ splitting = !@split_nodes.nil? && !@split_index.nil?
97
+ raise ArgumentError, 'split total must be positive' if splitting && @split_nodes.negative?
98
+ raise ArgumentError, 'split index must be positive' if splitting && @split_index.negative?
99
+ raise ArgumentError, 'split index must be less than split nodes' if splitting && @split_index >= @split_nodes
100
+ end
101
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
71
102
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/BlockLength
72
103
 
73
104
  def remove_formatter_quotes(env_var)
@@ -26,6 +26,9 @@ module FlakeySpecCatcher
26
26
  @remote = find_git_remote
27
27
  @branch = find_remote_branch
28
28
  @capsule_manager = capsule_manager
29
+ # we don't need to do any git comparisons if we have manually specified tests to run.
30
+ return unless @user_config.manual_rerun_patterns.nil? || @user_config.manual_rerun_patterns.empty?
31
+
29
32
  initialize_git_comparison(test_mode)
30
33
  parse_changes
31
34
  identify_change_contexts
@@ -17,6 +17,7 @@ module FlakeySpecCatcher
17
17
  @user_config = user_config
18
18
  @rerun_capsules = []
19
19
  determine_rerun_usage
20
+ split!
20
21
  end
21
22
 
22
23
  def determine_rerun_usage
@@ -110,6 +111,37 @@ module FlakeySpecCatcher
110
111
 
111
112
  private
112
113
 
114
+ # rubocop:disable Metrics/AbcSize
115
+ def split!
116
+ return unless !@user_config.split_nodes.nil? && !@user_config.split_index.nil?
117
+
118
+ # we create this restriction for simplicity. if we have multiple capsules then
119
+ # we have to split while being aware of splitting across capsules.
120
+ # if we absolutely need to split with different usage types, then we can implement that later..
121
+ raise ArgumentError('can only split on one usage type') if @rerun_capsules.size != 1
122
+
123
+ # ensure everything is sorted consistently before splitting
124
+ capsule = @rerun_capsules[0]
125
+ capsule.testcase.sort!
126
+
127
+ # compute the total tests that are changing
128
+ test_count = capsule.testcase.size
129
+
130
+ # the last node is going to be different from the previous nodes.
131
+ # for instance, if there are 13 test to run and you want 3 nodes:
132
+ # node1 -> 5
133
+ # node2 -> 5
134
+ # node3 -> 3
135
+ # it may be more efficient to split differently, but for now this will work.
136
+ node_test_count = (test_count / @user_config.split_nodes.to_f).ceil
137
+
138
+ skipping = @user_config.split_index * node_test_count
139
+ skipping_until = (@user_config.split_index + 1) * node_test_count
140
+ split_tests = capsule.testcase[skipping...skipping_until]
141
+ @rerun_capsules = [FlakeySpecCatcher::RerunCapsule.new(usage: capsule.usage, testcase: split_tests)]
142
+ end
143
+ # rubocop:enable Metrics/AbcSize
144
+
113
145
  def filter_reruns_by_ignore_files(reruns)
114
146
  return reruns if @user_config.ignore_files.count.zero?
115
147
 
@@ -10,7 +10,7 @@ require_relative './event_listener.rb'
10
10
 
11
11
  module FlakeySpecCatcher
12
12
  class Runner
13
- attr_reader :user_config, :rerun_manager, :git_controller
13
+ attr_reader :user_config, :rerun_manager, :git_controller, :test_run_count
14
14
 
15
15
  def initialize(test_mode: false,
16
16
  user_config: FlakeySpecCatcher::UserConfig.new,
@@ -23,6 +23,7 @@ module FlakeySpecCatcher
23
23
  @user_config = user_config
24
24
  @rerun_manager = rerun_manager
25
25
  @rspec_result_manager = result_manager
26
+ @test_run_count = 0
26
27
  end
27
28
 
28
29
  # Debug Methods
@@ -34,6 +35,8 @@ module FlakeySpecCatcher
34
35
  puts " Current Sha: #{@git_controller.working_commit_sha}"
35
36
  puts " Base Sha: #{@git_controller.base_commit_sha}"
36
37
  puts " Repeat factor: #{@user_config.repeat_factor}"
38
+ puts " Node Total: #{@user_config.split_nodes}" if @user_config.split_nodes
39
+ puts " Node Index: #{@user_config.split_index}" if @user_config.split_index
37
40
  puts " Changed Specs Detected: #{@git_controller.changed_examples}"
38
41
  return if @user_config.output_file == '/dev/null'
39
42
 
@@ -55,7 +58,17 @@ module FlakeySpecCatcher
55
58
  end
56
59
  # end Debug methods
57
60
 
61
+ def show_test_list
62
+ @rerun_manager.rerun_capsules.each do |capsule|
63
+ capsule.testcase.each do |test|
64
+ puts test
65
+ end
66
+ end
67
+ end
68
+
58
69
  def run_specs
70
+ return 0 if @user_config.dry_run
71
+
59
72
  status = 0
60
73
  @rerun_manager.rerun_capsules.sort.each do |capsule|
61
74
  @user_config.repeat_factor.times do
@@ -95,6 +108,7 @@ module FlakeySpecCatcher
95
108
  end
96
109
 
97
110
  def handle_capsule_rerun(capsule)
111
+ @test_run_count += 1
98
112
  if capsule.default_usage?
99
113
  invoke_rspec_runner(capsule.testcase)
100
114
  else
@@ -10,7 +10,8 @@ module FlakeySpecCatcher
10
10
  attr_reader :repeat_factor, :ignore_files, :ignore_branches, :silent_mode
11
11
  attr_reader :rerun_file_only, :rspec_usage_patterns, :excluded_tags
12
12
  attr_reader :manual_rerun_patterns, :manual_rerun_usage
13
- attr_reader :enable_runs, :output_file, :use_parent
13
+ attr_reader :enable_runs, :output_file, :use_parent, :dry_run
14
+ attr_reader :split_nodes, :split_index
14
15
 
15
16
  USER_CONFIG_ENV_VARS = %w[FSC_REPEAT_FACTOR FSC_IGNORE_FILES FSC_IGNORE_BRANCHES
16
17
  FSC_SILENT_MODE FSC_RERUN_FILE_ONLY FSC_USAGE_PATTERNS
@@ -34,14 +35,8 @@ module FlakeySpecCatcher
34
35
  @rspec_usage_patterns = env_var_string_to_pairs(ENV['FSC_USAGE_PATTERNS'])
35
36
  @excluded_tags = env_var_string_to_tags(ENV['FSC_EXCLUDED_TAGS'])
36
37
  @output_file = ENV['FSC_OUTPUT_FILE']
37
- end
38
- # rubocop:enable Metrics/AbcSize
39
-
40
- def override_settings
41
- apply_cli_override
42
- return unless @manual_rerun_patterns.nil?
43
-
44
- parse_commit_message
38
+ @split_nodes = env_var_string_to_int_or_nil('FSC_NODE_TOTAL')
39
+ @split_index = env_var_string_to_int_or_nil('FSC_NODE_INDEX')
45
40
  end
46
41
 
47
42
  def apply_cli_override
@@ -50,6 +45,9 @@ module FlakeySpecCatcher
50
45
  @use_parent = @cli_override.use_parent
51
46
  @repeat_factor = @cli_override.repeat_factor if @cli_override.repeat_factor.to_i.positive?
52
47
  @enable_runs = @cli_override.enable_runs
48
+ @dry_run = @cli_override.dry_run
49
+ @split_nodes = @cli_override.split_nodes unless @cli_override.split_nodes.nil?
50
+ @split_index = @cli_override.split_index unless @cli_override.split_index.nil?
53
51
  @excluded_tags = if @cli_override.excluded_tags.empty?
54
52
  @excluded_tags
55
53
  else
@@ -57,6 +55,14 @@ module FlakeySpecCatcher
57
55
  end
58
56
  @output_file = set_output_file
59
57
  end
58
+ # rubocop:enable Metrics/AbcSize
59
+
60
+ def override_settings
61
+ apply_cli_override
62
+ return unless @manual_rerun_patterns.nil?
63
+
64
+ parse_commit_message
65
+ end
60
66
 
61
67
  def set_output_file
62
68
  if !@cli_override.output_file.nil?
@@ -76,6 +82,18 @@ module FlakeySpecCatcher
76
82
  env_var.to_i.positive? ? env_var.to_i : 20
77
83
  end
78
84
 
85
+ def env_var_string_to_int_or_nil(env_var_name)
86
+ env_var = ENV[env_var_name]
87
+ if env_var.nil? || env_var.empty?
88
+ nil
89
+ else
90
+ check = env_var.to_i
91
+ raise ArgumentError, "#{env_var_name} must be positive" if check.negative?
92
+
93
+ check
94
+ end
95
+ end
96
+
79
97
  def env_var_string_to_array(env_var)
80
98
  if env_var.nil? || env_var.empty?
81
99
  []
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FlakeySpecCatcher
4
- VERSION = '0.9.2'
4
+ VERSION = '0.9.3'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flakey_spec_catcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Watson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-02-18 00:00:00.000000000 Z
13
+ date: 2020-02-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec