Class: Minitest::Bisect
- Inherits:
-
Object
- Object
- Minitest::Bisect
- Defined in:
- lib/minitest/bisect.rb
Constant Summary collapse
- VERSION =
"1.0.0"
- SHH =
" &> /dev/null"
Instance Attribute Summary collapse
-
#culprits ⇒ Object
Returns the value of attribute culprits.
-
#failures ⇒ Object
Returns the value of attribute failures.
-
#mode ⇒ Object
Returns the value of attribute mode.
-
#seen_bad ⇒ Object
Returns the value of attribute seen_bad.
-
#tainted ⇒ Object
(also: #tainted?)
Returns the value of attribute tainted.
Class Method Summary collapse
Instance Method Summary collapse
- #bisect_files(files) ⇒ Object
- #bisect_methods(cmd) ⇒ Object
- #build_files_cmd(culprits, rb, mt) ⇒ Object
- #build_methods_cmd(cmd, culprits = [], bad = nil) ⇒ Object
-
#initialize ⇒ Bisect
constructor
A new instance of Bisect.
- #reset ⇒ Object
- #result(file, klass, method, fails, assertions, time) ⇒ Object
- #run(files) ⇒ Object
Constructor Details
#initialize ⇒ Bisect
Returns a new instance of Bisect.
16 17 18 19 |
# File 'lib/minitest/bisect.rb', line 16 def initialize self.culprits = [] self.failures = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = [] } } end |
Instance Attribute Details
#culprits ⇒ Object
Returns the value of attribute culprits.
9 10 11 |
# File 'lib/minitest/bisect.rb', line 9 def culprits @culprits end |
#failures ⇒ Object
Returns the value of attribute failures.
9 10 11 |
# File 'lib/minitest/bisect.rb', line 9 def failures @failures end |
#mode ⇒ Object
Returns the value of attribute mode.
9 10 11 |
# File 'lib/minitest/bisect.rb', line 9 def mode @mode end |
#seen_bad ⇒ Object
Returns the value of attribute seen_bad.
9 10 11 |
# File 'lib/minitest/bisect.rb', line 9 def seen_bad @seen_bad end |
#tainted ⇒ Object Also known as: tainted?
Returns the value of attribute tainted.
9 10 11 |
# File 'lib/minitest/bisect.rb', line 9 def tainted @tainted end |
Class Method Details
.run(files) ⇒ Object
12 13 14 |
# File 'lib/minitest/bisect.rb', line 12 def self.run files new.run files end |
Instance Method Details
#bisect_files(files) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/minitest/bisect.rb', line 51 def bisect_files files self.mode = :files files, flags = files.partition { |arg| File.file? arg } rb_flags, mt_flags = flags.partition { |arg| arg =~ /^-I/ } mt_flags += ["-s", $$] puts "reproducing..." system "#{build_files_cmd files, rb_flags, mt_flags} #{SHH}" abort "Reproduction run passed? Aborting." unless tainted? puts "reproduced" found, count = files.find_minimal_combination_and_count do |test| puts "# of culprit files: #{test.size}" system "#{build_files_cmd test, rb_flags, mt_flags} #{SHH}" self.tainted? end puts puts "Minimal files found in #{count} steps:" puts cmd = build_files_cmd found, rb_flags, mt_flags puts cmd cmd end |
#bisect_methods(cmd) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/minitest/bisect.rb', line 79 def bisect_methods cmd self.mode = :methods puts "reproducing..." system "#{build_methods_cmd cmd} #{SHH}" abort "Reproduction run passed? Aborting." unless tainted? puts "reproduced" # from: {"file.rb"=>{"Class"=>["test_method"]}} to: "Class#test_method" bad = failures.values.first.to_a.join "#" found, count = culprits.find_minimal_combination_and_count do |test| puts "# of culprit methods: #{test.size}" system "#{build_methods_cmd cmd, test, bad} #{SHH}" self.tainted? end puts puts "Minimal methods found in #{count} steps:" puts cmd = build_methods_cmd cmd, found, bad puts cmd puts cmd end |
#build_files_cmd(culprits, rb, mt) ⇒ Object
107 108 109 110 111 112 113 |
# File 'lib/minitest/bisect.rb', line 107 def build_files_cmd culprits, rb, mt reset tests = culprits.flatten.compact.map {|f| %(require "./#{f}")}.join " ; " %(ruby #{rb.shelljoin} -e '#{tests}' -- #{mt.shelljoin}) end |
#build_methods_cmd(cmd, culprits = [], bad = nil) ⇒ Object
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/minitest/bisect.rb', line 115 def build_methods_cmd cmd, culprits = [], bad = nil reset if bad then re = [] bbc = (culprits + [bad]).map { |s| s.split(/#/) }.group_by(&:first) bbc.each do |klass, methods| methods = methods.map(&:last).flatten re << /#{klass}##{Regexp.union(methods)}/ end re = Regexp.union(re).to_s.gsub(/-mix/, "") cmd += " -n '/^#{re}$/'" if bad end cmd end |
#reset ⇒ Object
21 22 23 24 25 26 |
# File 'lib/minitest/bisect.rb', line 21 def reset self.seen_bad = false self.tainted = false failures.clear # not clearing culprits on purpose end |
#result(file, klass, method, fails, assertions, time) ⇒ Object
136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/minitest/bisect.rb', line 136 def result file, klass, method, fails, assertions, time if mode == :methods then if fails.empty? then culprits << "#{klass}##{method}" unless seen_bad # UGH else self.seen_bad = true end end unless fails.empty? self.tainted = true self.failures[file][klass] << method end end |
#run(files) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/minitest/bisect.rb', line 28 def run files Minitest::Server.run self cmd = nil if :until_I_have_negative_filtering_in_minitest then files, flags = files.partition { |arg| File.file? arg } rb_flags, mt_flags = flags.partition { |arg| arg =~ /^-I/ } mt_flags += ["-s", $$] cmd = bisect_methods build_files_cmd(files, rb_flags, mt_flags) else cmd = bisect_methods bisect_files files end puts "Final reproduction:" puts system cmd ensure Minitest::Server.stop end |