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 +4 -4
- data/README.md +35 -0
- data/bin/flakey_spec_catcher +2 -0
- data/lib/flakey_spec_catcher/cli_override.rb +37 -6
- data/lib/flakey_spec_catcher/git_controller.rb +3 -0
- data/lib/flakey_spec_catcher/rerun_manager.rb +32 -0
- data/lib/flakey_spec_catcher/runner.rb +15 -1
- data/lib/flakey_spec_catcher/user_config.rb +27 -9
- data/lib/flakey_spec_catcher/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6afbdca4bb65ca89de114e1dcfbdbffb93e5dbfbe7f39cc4c4511e018f422bf3
|
4
|
+
data.tar.gz: 3e6b37e7f310e74b2711139e6d45b94028d22a3624e7bcd08494e8bef49bc26a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/bin/flakey_spec_catcher
CHANGED
@@ -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
|
-
|
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
|
-
|
38
|
-
|
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
|
[]
|
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.
|
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-
|
13
|
+
date: 2020-02-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|