flakey_spec_catcher 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15d0a03b7d5147dc7d4ef97bd1868c53a9a279ae767cdc652adbfdfec076ba89
4
- data.tar.gz: a58a1f258d13ab6050275c20e702cd1283598fe8254cf79517a01edd50323fbc
3
+ metadata.gz: 7f845e77fb2900e6e7fca4c3de62b8104dd1c1844fba4b0881d9d9c77d3b65c0
4
+ data.tar.gz: 3611db64df625c5cc1506e400a5cd5d664da15bf254431835f245d6539b9fdaa
5
5
  SHA512:
6
- metadata.gz: ba2cb9723f0f04756c506eaf91608b9fec132f0ba5285d8594e0ec1c67ab1503bb5a87bdcc3e68aa64ab74479791cbcbb2b88d051c9b5faad8a35062448de3d7
7
- data.tar.gz: bc0207b9163c7a07a7398b8694125d503fbd7bda397d84bef7f34c37906a2efdca814ae31d10775ba4893473c7751e6e79c7e20676618a2ec52e31157b4023b8
6
+ metadata.gz: b314f343b5630fab71d1d95eeb0b08f371d7bf314b2b5045e33fbc7eaa6d088c17d86244ee0826cb338f0e74b515f66f2fa1e0b76874fe128cbb0cfac534aedb
7
+ data.tar.gz: 9efea9ff0b95595f1535fdff9ada0bd86822b716c01c7faec2edc48d6600c82a2b6dea07e0fba1a225f63a936720f75e8d74577b8102b3833bc693564e3bcf93
data/README.md CHANGED
@@ -11,7 +11,7 @@ There are two primary usecases for flakey_spec_catcher (FSC):
11
11
  commit many times.
12
12
 
13
13
  2. Manual Re-runs - Specify a test to re-run many times regardless of whether it has
14
- corresponding changes in yuor commit.
14
+ corresponding changes in your commit.
15
15
 
16
16
  FSC detects changes by running the equivalent of a git diff
17
17
  between the current branch's commit and the HEAD of Source Control Management (SCM)
@@ -70,7 +70,7 @@ you'll also need to ensure that FSC has access to any needed gems.
70
70
  It's best to do this by adding flakey_speec_catcher to your Gemfile via bundler
71
71
  and then running it with `bundle exec flakey_spec_catcher`
72
72
 
73
- ### In what cases if FSC not suitable?
73
+ ### In what cases is FSC not suitable?
74
74
 
75
75
  Since FSC by default re-runs tests at the smallest possible level of
76
76
  change (a single test case or example), it is not suitable to allow it to run
@@ -72,7 +72,7 @@ module FlakeySpecCatcher
72
72
  # Not sure if we need to check for description in quotes
73
73
  # spec_scope = /^\s*(#{SCOPE_SPECIFIERS.join("|")})\s*('.*'|".*").*do\s*$/
74
74
 
75
- /\s*(#{SCOPE_SPECIFIERS.join("|")}).*\s+do\s*$/
75
+ /\s*(#{SCOPE_SPECIFIERS.join("|")}).*\s+do.*$/
76
76
  end
77
77
 
78
78
  def line_matches_method_or_block(line)
@@ -37,8 +37,6 @@ module FlakeySpecCatcher
37
37
 
38
38
  opts.on('-r', '--repeat=REPEAT_FACTOR',
39
39
  'Specify a repeat factor for the manual re-run(s)') do |repeat|
40
- raise ArgumentError if @rerun_patterns.nil?
41
-
42
40
  parsed_repeat_factor = remove_formatter_quotes(repeat).to_i
43
41
  @repeat_factor = parsed_repeat_factor if parsed_repeat_factor.positive?
44
42
  end
@@ -20,8 +20,8 @@ module FlakeySpecCatcher
20
20
  attr_reader :capsule_manager
21
21
 
22
22
  def initialize(test_mode: false, capsule_manager: FlakeySpecCatcher::CapsuleManager.new)
23
+ @remote = find_git_remote
23
24
  @branch = find_remote_branch
24
- @remote = `git remote`.gsub(/\s+/, '')
25
25
  @capsule_manager = capsule_manager
26
26
  initialize_git_comparison(test_mode)
27
27
  parse_changes
@@ -34,7 +34,19 @@ module FlakeySpecCatcher
34
34
 
35
35
  private
36
36
 
37
+ # Use 'origin' unless otherwise specified
38
+ def find_git_remote
39
+ if ENV['FSC_GIT_REMOTE'].nil? || ENV['FSC_GIT_REMOTE'].strip.empty?
40
+ remotes = `git remote show`.split
41
+ remotes.empty? ? nil : remotes[0]
42
+ else
43
+ ENV['FSC_GIT_REMOTE']
44
+ end
45
+ end
46
+
37
47
  def find_remote_branch
48
+ return nil if @remote.nil?
49
+
38
50
  working_branch = `git branch | grep '*'`.delete('*').gsub(/\s+/, '')
39
51
  # `git remote show origin` will show us if our branch is configured to push
40
52
  # to a non-master branch. Note that our push destination is what we're interested in
@@ -55,7 +67,7 @@ module FlakeySpecCatcher
55
67
  # dev/reports pushes to dev/reports (up to date)
56
68
  # master pushes to master (up to date)
57
69
 
58
- remote_branches = `git remote show origin`.split("\n")
70
+ remote_branches = `git remote show #{@remote}`.split("\n")
59
71
 
60
72
  # Separate 'dev/reports pushes to dev/reports (up to date)' into
61
73
  # ['dev/reports', 'dev/reports'] or [<LOCAL BRANCH>, <REMOTE BRANCH>]
@@ -78,7 +90,7 @@ module FlakeySpecCatcher
78
90
  end
79
91
 
80
92
  def initialize_git_comparison(test_mode)
81
- if !test_mode
93
+ if !test_mode && !@remote.nil?
82
94
  @working_commit_sha = `git rev-parse @`.gsub(/\s+/, '')
83
95
  @base_commit_sha = `git rev-parse #{@remote}/#{@branch}`.gsub(/\s+/, '')
84
96
  else
@@ -9,7 +9,7 @@ module FlakeySpecCatcher
9
9
  include Comparable
10
10
  attr_reader :usage, :testcase
11
11
 
12
- def initialize(usage: nil, testcase: '')
12
+ def initialize(usage: nil, testcase: [])
13
13
  @usage = initialize_usage(usage)
14
14
  @testcase = initialize_testcase(testcase)
15
15
  end
@@ -30,6 +30,10 @@ module FlakeySpecCatcher
30
30
  @testcase <=> other.testcase
31
31
  end
32
32
 
33
+ def ==(other)
34
+ usage == other.usage && testcase == other.testcase
35
+ end
36
+
33
37
  private
34
38
 
35
39
  def initialize_usage(usage)
@@ -42,9 +46,11 @@ module FlakeySpecCatcher
42
46
 
43
47
  def initialize_testcase(testcase)
44
48
  if testcase.nil? || testcase.empty?
45
- ''
46
- else
49
+ []
50
+ elsif testcase.is_a?(Array)
47
51
  testcase
52
+ else
53
+ raise "Error: expected array for testcase not #{testcase.class}"
48
54
  end
49
55
  end
50
56
  end
@@ -23,7 +23,7 @@ module FlakeySpecCatcher
23
23
  if @user_config.manual_rerun_patterns.nil?
24
24
  pair_reruns_with_usages
25
25
  else
26
- @rerun_capsules.clear
26
+ @rerun_capsules = []
27
27
  inject_manual_reruns(@user_config.manual_rerun_patterns,
28
28
  @user_config.manual_rerun_usage)
29
29
  end
@@ -59,57 +59,52 @@ module FlakeySpecCatcher
59
59
  def pair_reruns_with_usages
60
60
  reruns = tests_for_rerun
61
61
  configured_usage_patterns = @user_config.rspec_usage_patterns
62
-
63
62
  if configured_usage_patterns.count.zero?
64
63
  add_capsules_with_default_usage(reruns)
65
64
  return
66
65
  end
67
66
 
68
- reruns.each do |rerun|
69
- match_found = false
70
- configured_usage_patterns.each do |usage_pattern_pair|
71
- next if match_found
72
-
73
- pattern, usage = usage_pattern_pair
74
- if rerun =~ /#{pattern}/
75
- add_rerun_capsule(testcase: rerun, usage: usage)
76
- match_found = true
77
- end
67
+ configured_usage_patterns.each do |usage_pattern_pair|
68
+ tests = []
69
+ pattern, usage = usage_pattern_pair
70
+ reruns.each do |rerun|
71
+ tests.push rerun if rerun =~ /#{pattern}/
78
72
  end
79
- add_rerun_capsule(testcase: rerun) unless match_found
73
+ reruns -= tests
74
+ add_rerun_capsule(testcase: tests, usage: usage)
80
75
  end
76
+ add_rerun_capsule(testcase: reruns) if reruns.any?
81
77
  end
82
78
 
83
79
  # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
84
80
  def inject_manual_reruns(patterns, usage)
81
+ tests = []
85
82
  patterns.tr(' ', '').split(',').each do |pattern|
86
83
  # Check if file exists first and handle if user supplies testcase:line_number
87
84
  file_name = pattern.split(':')[0]
88
85
  line_number_present = pattern.split(':').count > 1
89
86
  matching_files = Dir.glob(file_name)
90
-
91
87
  # If no file matches are run, don't queue up re-runs
92
88
  if matching_files.count.zero?
93
89
  puts "Specified pattern #{pattern} did not match an existing file"
94
90
  raise ArgumentError
95
91
  end
96
-
97
92
  # It won't make sense to have multiple files to run with one specific line number
98
93
  if line_number_present
99
94
  if matching_files.count > 1
100
95
  puts "Specified pattern #{pattern} matched multiple files but a line number was given"
101
96
  raise ArgumentError
102
97
  else
103
- add_rerun_capsule(testcase: pattern, usage: usage)
98
+ tests.push pattern
104
99
  end
105
-
106
100
  # No line numbers, queue up all matching files
107
101
  else
108
102
  matching_files.each do |file|
109
- add_rerun_capsule(testcase: file, usage: usage)
103
+ tests.push file
110
104
  end
111
105
  end
112
106
  end
107
+ add_rerun_capsule(testcase: tests, usage: usage)
113
108
  end
114
109
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
115
110
 
@@ -131,13 +126,18 @@ module FlakeySpecCatcher
131
126
  end
132
127
 
133
128
  def add_capsules_with_default_usage(reruns)
134
- reruns.each do |rerun|
135
- @rerun_capsules.push(FlakeySpecCatcher::RerunCapsule.new(testcase: rerun))
136
- end
129
+ @rerun_capsules.push(FlakeySpecCatcher::RerunCapsule.new(testcase: reruns)) unless reruns.empty?
137
130
  end
138
131
 
139
- def add_rerun_capsule(testcase: '', usage: nil)
140
- @rerun_capsules.push(FlakeySpecCatcher::RerunCapsule.new(testcase: testcase, usage: usage))
132
+ def add_rerun_capsule(testcase: [], usage: nil)
133
+ return if testcase.empty?
134
+
135
+ capsule = @rerun_capsules.find { |cap| cap.usage == usage }
136
+ if capsule
137
+ capsule.testcase.push(testcase)
138
+ else
139
+ @rerun_capsules.push(FlakeySpecCatcher::RerunCapsule.new(testcase: testcase, usage: usage))
140
+ end
141
141
  end
142
142
  end
143
143
  end
@@ -44,10 +44,12 @@ module FlakeySpecCatcher
44
44
  def rerun_preview
45
45
  puts "\n********************************************"
46
46
  puts "Re-run Preview\n"
47
- @rerun_manager.rerun_capsules.sort.each do |capsule|
48
- rerun_msg = " Running #{capsule.testcase} #{@user_config.repeat_factor} times "
49
- rerun_msg += "using `#{capsule.usage}`" unless capsule.default_usage?
50
- puts rerun_msg
47
+ @rerun_manager.rerun_capsules.each do |capsule|
48
+ capsule.testcase.each do |test|
49
+ rerun_msg = " Running #{test} #{@user_config.repeat_factor} times "
50
+ rerun_msg += "using `#{capsule.usage}`" unless capsule.default_usage?
51
+ puts rerun_msg
52
+ end
51
53
  end
52
54
  puts "\n********************************************"
53
55
  end
@@ -55,8 +57,8 @@ module FlakeySpecCatcher
55
57
 
56
58
  def run_specs
57
59
  status = 0
58
- @user_config.repeat_factor.times do
59
- @rerun_manager.rerun_capsules.sort.each do |capsule|
60
+ @rerun_manager.rerun_capsules.sort.each do |capsule|
61
+ @user_config.repeat_factor.times do
60
62
  iteration_status = handle_capsule_rerun(capsule)
61
63
  status = [status, iteration_status].max
62
64
  end
@@ -85,11 +87,9 @@ module FlakeySpecCatcher
85
87
  end
86
88
 
87
89
  def invoke_custom_rspec_runner(usage, testcase)
88
- custom_usage_output = `#{usage} #{testcase}`
90
+ custom_usage_output = `#{usage} #{testcase.join(' ')}`
89
91
 
90
- if @user_config.output_file != '/dev/null'
91
- File.open(@user_config.output_file, 'a') { |f| f.puts custom_usage_output }
92
- end
92
+ File.open(@user_config.output_file, 'a') { |f| f.puts custom_usage_output } if @user_config.output_file != '/dev/null'
93
93
 
94
94
  $?.exitstatus # rubocop:disable Style/SpecialGlobalVars
95
95
  end
@@ -6,7 +6,6 @@ module FlakeySpecCatcher
6
6
  #
7
7
  # Captures user-defined settings to configure RSpec re-run settings.
8
8
 
9
- # rubocop:disable Metrics/ClassLength
10
9
  class UserConfig
11
10
  attr_reader :repeat_factor, :ignore_files, :ignore_branches, :silent_mode
12
11
  attr_reader :rerun_file_only, :rspec_usage_patterns, :excluded_tags
@@ -171,5 +170,4 @@ module FlakeySpecCatcher
171
170
  end
172
171
  # rubocop:enable Metrics/CyclomaticComplexity
173
172
  end
174
- # rubocop:enable Metrics/ClassLength
175
173
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FlakeySpecCatcher
4
- VERSION = '0.8.0'
4
+ VERSION = '0.9.0'
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.8.0
4
+ version: 0.9.0
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-01-17 00:00:00.000000000 Z
13
+ date: 2020-02-07 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -122,8 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
122
  - !ruby/object:Gem::Version
123
123
  version: '0'
124
124
  requirements: []
125
- rubyforge_project:
126
- rubygems_version: 2.7.7
125
+ rubygems_version: 3.0.4
127
126
  signing_key:
128
127
  specification_version: 4
129
128
  summary: Run new or changed specs many times to prevent unreliable specs