rspec-search-and-destroy 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -13,7 +13,7 @@ debug.
13
13
  First, add the appropriate hooks in your `spec_helper.rb`:
14
14
 
15
15
  ```ruby
16
- require 'rspec-sad'
16
+ require 'rspec-search-and-destroy'
17
17
 
18
18
  RSpec.configure do |config|
19
19
  RSpecSearchAndDestroy.configure(config)
@@ -1,21 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rspec-sad'
4
-
3
+ require 'rspec-search-and-destroy'
5
4
  require 'rspec-search-and-destroy/binary_chop_example_selector'
6
5
  require 'rspec-search-and-destroy/rspec_driver'
7
6
  require 'rspec-search-and-destroy/bisector'
7
+ require 'rspec-search-and-destroy/io_output'
8
8
 
9
9
  include RSpecSearchAndDestroy
10
10
 
11
- class TTYOutput
12
- def found(causal_example, failed_example)
13
- puts "Culprit found"
14
- puts "Run #{causal_example[:location]}"
15
- puts "Before #{failed_example[:location]}"
16
- end
17
- end
18
-
19
11
  require 'optparse'
20
12
 
21
13
  driver_options = {}
@@ -35,8 +27,7 @@ BANNER
35
27
  end
36
28
  option_parser.parse!
37
29
 
38
-
39
- output = TTYOutput.new
30
+ output = IOOutput.new
40
31
  selector = BinaryChopExampleSelector.new
41
32
  driver = RSpecDriver.new(driver_options)
42
33
 
@@ -1,6 +1,6 @@
1
1
  Given(/^a configured spec\/spec_helper\.rb$/) do
2
2
  config = <<CONFIG
3
- require 'rspec-sad'
3
+ require 'rspec-search-and-destroy'
4
4
 
5
5
  RSpec.configure do |config|
6
6
  RSpecSearchAndDestroy.configure(config)
@@ -0,0 +1,41 @@
1
+ class BisectionProgress
2
+ attr_reader :iteration, :enabled_examples, :total_examples, :start_time
3
+
4
+ def initialize(attributes = {})
5
+ @iteration = attributes.fetch(:iteration) { 1 }
6
+ @enabled_examples = attributes.fetch(:enabled_examples)
7
+ @total_examples = attributes.fetch(:total_examples)
8
+ @time_provider = attributes.fetch(:time_provider) { Time }
9
+ @start_time = attributes.fetch(:start_time) { @time_provider.now }
10
+ end
11
+
12
+ def next_iteration(enabled_examples)
13
+ self.class.new(iteration: iteration + 1,
14
+ enabled_examples: enabled_examples,
15
+ total_examples: total_examples,
16
+ time_provider: @time_provider,
17
+ start_time: start_time)
18
+ end
19
+
20
+ def run_time
21
+ @time_provider.now - @start_time
22
+ end
23
+
24
+ def ==(other)
25
+ values.map do |v|
26
+ self.send(v) == other.send(v)
27
+ end.all?
28
+ end
29
+
30
+ def hash
31
+ values.map do |v|
32
+ self.send(v).hash
33
+ end.reduce(:^)
34
+ end
35
+
36
+ private
37
+
38
+ def values
39
+ [:iteration, :enabled_examples, :total_examples]
40
+ end
41
+ end
@@ -1,3 +1,5 @@
1
+ require_relative 'bisection_progress'
2
+
1
3
  module RSpecSearchAndDestroy
2
4
  class Bisector
3
5
  attr_reader :output, :selector, :executor
@@ -8,7 +10,7 @@ module RSpecSearchAndDestroy
8
10
  @executor = executor
9
11
  end
10
12
 
11
- def bisect(causal_examples, failed_example)
13
+ def bisect(causal_examples, failed_example, progress = nil)
12
14
  case causal_examples.size
13
15
  when 1
14
16
  output.found(causal_examples.first, failed_example)
@@ -19,17 +21,22 @@ module RSpecSearchAndDestroy
19
21
  end
20
22
 
21
23
  enabled, disabled = selector.enable_set(causal_examples)
22
-
23
24
  to_run = enabled + [failed_example]
24
- executor.run_examples(to_run)
25
25
 
26
+ progress =
27
+ if progress
28
+ progress.next_iteration(enabled.size)
29
+ else
30
+ BisectionProgress.new(total_examples: causal_examples.size,
31
+ enabled_examples: enabled.size)
32
+ end
33
+ output.progress(progress)
34
+
35
+ executor.run_examples(to_run)
26
36
  results = executor.load_run_results
27
37
 
28
- if results.failed?
29
- bisect(enabled, failed_example)
30
- else
31
- bisect(disabled, failed_example)
32
- end
38
+ next_set = results.failed? ? enabled : disabled
39
+ bisect(next_set, failed_example, progress)
33
40
  end
34
41
  end
35
42
  end
@@ -0,0 +1,47 @@
1
+ class IOOutput
2
+ attr_reader :io
3
+
4
+ SEPARATOR = "-" * 20
5
+
6
+ def initialize(io = STDOUT)
7
+ @io = io
8
+ end
9
+
10
+ def found(causal_example, failed_example)
11
+ io.puts <<FOUND
12
+ #{SEPARATOR}
13
+ Culprit found
14
+ Run #{causal_example[:location]}
15
+ Before #{failed_example[:location]}
16
+ FOUND
17
+ end
18
+
19
+ def progress(state)
20
+ run_time = Duration.new(state.run_time)
21
+
22
+ io.puts <<PROGRESS
23
+ #{SEPARATOR}
24
+ Iteration #{state.iteration}
25
+ #{state.enabled_examples} / #{state.total_examples} examples enabled
26
+ Running for #{run_time}
27
+ PROGRESS
28
+ end
29
+
30
+ private
31
+
32
+ class Duration
33
+ attr_reader :hours, :minutes, :seconds
34
+
35
+ def initialize(duration_as_seconds)
36
+ total_seconds = duration_as_seconds.to_f.ceil.to_i
37
+
38
+ @seconds = total_seconds % 60
39
+ @minutes = (total_seconds / 60) % 60
40
+ @hours = total_seconds / (60 * 60)
41
+ end
42
+
43
+ def to_s
44
+ "%02d:%02d:%02d" % [hours, minutes, seconds]
45
+ end
46
+ end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module RSpecSearchAndDestroy
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -1,14 +1,15 @@
1
1
  require 'spec_helper'
2
2
  require 'rspec-search-and-destroy/bisector.rb'
3
+ require 'rspec-search-and-destroy/binary_chop_example_selector.rb'
3
4
 
4
5
  describe RSpecSearchAndDestroy::Bisector do
5
6
  subject(:bisector) do
6
7
  RSpecSearchAndDestroy::Bisector.new(output, selector, executor)
7
8
  end
8
9
 
9
- let(:output) { double("output") }
10
+ let(:output) { double("output").as_null_object }
10
11
  let(:selector) { double("selector") }
11
- let(:executor) { double("executor") }
12
+ let(:executor) { double("executor").as_null_object }
12
13
 
13
14
  let(:failing_example) { double("failing example") }
14
15
 
@@ -34,7 +35,7 @@ describe RSpecSearchAndDestroy::Bisector do
34
35
  end
35
36
 
36
37
  context "when executing examples" do
37
- let(:potential_causes) { 2.times.map {|i| double("potential example #{i}")} }
38
+ let(:potential_causes) { build_examples(2) }
38
39
  let(:enabled_examples) { [potential_causes.first] }
39
40
  let(:disabled_examples) { [potential_causes.last] }
40
41
 
@@ -46,7 +47,6 @@ describe RSpecSearchAndDestroy::Bisector do
46
47
  # they are just needed to prevent failure
47
48
  results = double("results", :failed? => true)
48
49
  executor.stub(:load_run_results).and_return(results)
49
- output.stub(:found)
50
50
  end
51
51
 
52
52
  it "executes enabled examples" do
@@ -75,7 +75,6 @@ describe RSpecSearchAndDestroy::Bisector do
75
75
 
76
76
  context "when the executed tests fail" do
77
77
  before do
78
- executor.stub(:run_examples)
79
78
  results = double("results", :failed? => true)
80
79
  executor.stub(:load_run_results).and_return(results)
81
80
  end
@@ -90,7 +89,6 @@ describe RSpecSearchAndDestroy::Bisector do
90
89
 
91
90
  context "when the executed tests do not fail" do
92
91
  before do
93
- executor.stub(:run_examples)
94
92
  results = double("results", :failed? => false)
95
93
  executor.stub(:load_run_results).and_return(results)
96
94
  end
@@ -103,4 +101,36 @@ describe RSpecSearchAndDestroy::Bisector do
103
101
  end
104
102
  end
105
103
  end
104
+
105
+ context "when reporting progress" do
106
+ let(:potential_causes) { build_examples(3) }
107
+ let(:selector) { RSpecSearchAndDestroy::BinaryChopExampleSelector.new }
108
+
109
+ before do
110
+ results = double("results", :failed? => false)
111
+ executor.stub(:load_run_results).and_return(results)
112
+ end
113
+
114
+ it "reports once for each iteration" do
115
+ progress_1 = BisectionProgress.new(iteration: 1,
116
+ total_examples: 3,
117
+ enabled_examples: 1)
118
+
119
+ progress_2 = BisectionProgress.new(iteration: 2,
120
+ total_examples: 3,
121
+ enabled_examples: 1)
122
+
123
+ expect(output).to receive(:progress)
124
+ .with(progress_1).ordered
125
+
126
+ expect(output).to receive(:progress)
127
+ .with(progress_2).ordered
128
+
129
+ bisector.bisect(potential_causes, failing_example)
130
+ end
131
+ end
132
+
133
+ def build_examples(count)
134
+ count.times.map {|i| double("potential example #{i}")}
135
+ end
106
136
  end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+ require 'rspec-search-and-destroy/io_output.rb'
3
+
4
+ module RSpecSearchAndDestroy
5
+ describe IOOutput do
6
+ let(:output) { IOOutput.new(io) }
7
+ let(:io) { StringIO.new }
8
+ subject(:string) { io.string }
9
+
10
+ context "when reporting the culprit" do
11
+ let(:causal_example) { {location: "cause location"} }
12
+ let(:failed_example) { {location: "fail location"} }
13
+
14
+ before do
15
+ output.found(causal_example, failed_example)
16
+ end
17
+
18
+ it "includes the example that causes the problem" do
19
+ expect(string).to match /Run\s+cause location/
20
+ end
21
+
22
+ it "includes the example that fails" do
23
+ expect(string).to match /Before\s+fail location/
24
+ end
25
+ end
26
+
27
+ context "when reporting progress" do
28
+ let(:progress) do
29
+ BisectionProgress.new(iteration: 5,
30
+ enabled_examples: 54,
31
+ total_examples: 999)
32
+ end
33
+
34
+ before do
35
+ output.progress(progress)
36
+ end
37
+
38
+ it "includes the current iteration" do
39
+ expect(string).to match /Iteration 5/
40
+ end
41
+
42
+ it "includes the number of enabled examples" do
43
+ expect(string).to match /54.*examples/
44
+ end
45
+
46
+ it "includes the total number of examples" do
47
+ expect(string).to match /999.*examples/
48
+ end
49
+
50
+ it "includes the running time" do
51
+ expect(string).to match /Running for \d{2}:\d{2}:\d{2}/
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'rspec-sad'
2
+ require 'rspec-search-and-destroy'
3
3
 
4
4
  describe RSpecSearchAndDestroy::ReorderAndFilter do
5
5
  subject(:ordering_block) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-search-and-destroy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-08 00:00:00.000000000 Z
12
+ date: 2013-09-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: childprocess
@@ -98,9 +98,11 @@ files:
98
98
  - features/running_rspec_without_sad.feature
99
99
  - features/support/env.rb
100
100
  - features/support/steps.rb
101
- - lib/rspec-sad.rb
101
+ - lib/rspec-search-and-destroy.rb
102
102
  - lib/rspec-search-and-destroy/binary_chop_example_selector.rb
103
+ - lib/rspec-search-and-destroy/bisection_progress.rb
103
104
  - lib/rspec-search-and-destroy/bisector.rb
105
+ - lib/rspec-search-and-destroy/io_output.rb
104
106
  - lib/rspec-search-and-destroy/location_source.rb
105
107
  - lib/rspec-search-and-destroy/order_formatter.rb
106
108
  - lib/rspec-search-and-destroy/reorder_and_filter.rb
@@ -110,6 +112,7 @@ files:
110
112
  - rspec-search-and-destroy.gemspec
111
113
  - spec/binary_chop_example_selector_spec.rb
112
114
  - spec/bisector_spec.rb
115
+ - spec/io_output_spec.rb
113
116
  - spec/rspec_example_ordering_spec.rb
114
117
  - spec/spec_helper.rb
115
118
  homepage: https://github.com/shepmaster/rspec-search-and-destroy
@@ -147,5 +150,6 @@ test_files:
147
150
  - features/support/steps.rb
148
151
  - spec/binary_chop_example_selector_spec.rb
149
152
  - spec/bisector_spec.rb
153
+ - spec/io_output_spec.rb
150
154
  - spec/rspec_example_ordering_spec.rb
151
155
  - spec/spec_helper.rb