rspec-search-and-destroy 0.0.3 → 0.0.4

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.
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