rspec-search-and-destroy 0.0.1 → 0.0.2

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/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ script: cucumber
data/bin/rspec-sad CHANGED
@@ -3,6 +3,10 @@
3
3
  $LOAD_PATH << "$PWD/../lib/"
4
4
  require 'rspec-sad'
5
5
 
6
+ require 'rspec-search-and-destroy/binary_chop_example_selector'
7
+ require 'rspec-search-and-destroy/rspec_driver'
8
+ require 'rspec-search-and-destroy/bisector'
9
+
6
10
  include RSpecSearchAndDestroy
7
11
 
8
12
  class TTYOutput
@@ -0,0 +1,41 @@
1
+ Feature: `before(:all)` blocks are disabled when all of the examples are also disabled
2
+
3
+ Scenario: Run it
4
+ Given a file named "spec/spec_helper.rb" with:
5
+ """ruby
6
+ require 'rspec-sad'
7
+
8
+ RSpec.configure do |config|
9
+ RSpecSearchAndDestroy.configure(config)
10
+ end
11
+ """
12
+ And a file named "spec/before_all_spec.rb" with:
13
+ """ruby
14
+ require 'spec_helper'
15
+
16
+ describe 'Tests that have before :all' do
17
+ context do
18
+ before(:all) { puts 'example 1 - before :all' }
19
+ it 'leaves bad global state' do
20
+ $global_state = true
21
+ expect($global_state).to be true
22
+ end
23
+ end
24
+
25
+ context do
26
+ before(:all) { puts 'example 2 - before :all' }
27
+ it do
28
+ expect(true).to be true
29
+ end
30
+ end
31
+
32
+ context do
33
+ before(:all) { puts 'example 3 - before :all' }
34
+ it 'relies on global state' do
35
+ expect($global_state).to be false
36
+ end
37
+ end
38
+ end
39
+ """
40
+ When I run `rspec-sad`
41
+ Then the output should contain "example 2 - before :all" 1 time
@@ -0,0 +1,34 @@
1
+ Feature: Bisecting a single file
2
+
3
+ Scenario: Run it
4
+ Given a file named "spec/spec_helper.rb" with:
5
+ """ruby
6
+ require 'rspec-sad'
7
+
8
+ RSpec.configure do |config|
9
+ RSpecSearchAndDestroy.configure(config)
10
+ end
11
+ """
12
+ And a file named "spec/single_file_spec.rb" with:
13
+ """ruby
14
+ require 'spec_helper'
15
+
16
+ describe "Tests that fail when run in a specific order" do
17
+ it "leaves bad global state" do
18
+ $global_state = true
19
+ expect($global_state).to be true
20
+ end
21
+
22
+ it "just takes up space" do
23
+ expect(true).to be true
24
+ end
25
+
26
+ it "fails when run last" do
27
+ expect($global_state).to be false
28
+ end
29
+ end
30
+ """
31
+ When I run `rspec-sad`
32
+ Then the output should contain "Culprit found"
33
+ And the output should contain "Run ./spec/single_file_spec.rb:4"
34
+ And the output should contain "Before ./spec/single_file_spec.rb:13"
@@ -0,0 +1,46 @@
1
+ Feature: Bisecting multiple files
2
+
3
+ Scenario: Run it
4
+ Given a file named "spec/spec_helper.rb" with:
5
+ """ruby
6
+ require 'rspec-sad'
7
+
8
+ RSpec.configure do |config|
9
+ RSpecSearchAndDestroy.configure(config)
10
+ end
11
+ """
12
+ And a file named "spec/file_1_spec.rb" with:
13
+ """ruby
14
+ require 'spec_helper'
15
+
16
+ describe 'group 1' do
17
+ it '1 - sets bad global state' do
18
+ $global_state = true
19
+ expect($global_state).to be_true
20
+ end
21
+ end
22
+ """
23
+ And a file named "spec/file_2_spec.rb" with:
24
+ """ruby
25
+ require 'spec_helper'
26
+
27
+ describe 'group 2' do
28
+ it '2 - just takes up space' do
29
+ expect(true).to be_true
30
+ end
31
+ end
32
+ """
33
+ And a file named "spec/file_3_spec.rb" with:
34
+ """ruby
35
+ require 'spec_helper'
36
+
37
+ describe 'group 3' do
38
+ it '3 - fails because of global state' do
39
+ expect($global_state).to be_false
40
+ end
41
+ end
42
+ """
43
+ When I run `rspec-sad`
44
+ Then the output should contain "Culprit found"
45
+ And the output should contain "Run ./spec/file_1_spec.rb:4"
46
+ And the output should contain "Before ./spec/file_3_spec.rb:4"
@@ -0,0 +1 @@
1
+ require 'aruba/cucumber'
@@ -0,0 +1,4 @@
1
+ Then(/^the output should contain "(.*?)" (\d+) times?$/) do |expected_output, expected_count|
2
+ actual_count = all_output.scan(expected_output).length
3
+ expect(actual_count).to eql expected_count.to_i
4
+ end
data/lib/rspec-sad.rb CHANGED
@@ -1,9 +1,8 @@
1
- require "rspec-search-and-destroy/version"
2
- require "rspec-search-and-destroy/bisector"
3
- require "rspec-search-and-destroy/binary_chop_example_selector"
1
+ require 'rspec-search-and-destroy/version'
4
2
 
5
- require 'rspec'
6
- require 'rspec/core/formatters/base_formatter'
3
+ require 'rspec-search-and-destroy/order_formatter'
4
+ require 'rspec-search-and-destroy/location_source'
5
+ require 'rspec-search-and-destroy/reorder_and_filter'
7
6
 
8
7
  module RSpecSearchAndDestroy
9
8
  def self.configure(config)
@@ -12,146 +11,9 @@ module RSpecSearchAndDestroy
12
11
  source = LocationSource.new
13
12
  if source.enabled?
14
13
  ordering = ReorderAndFilter.new(source)
15
- config.order_examples(&ordering.block)
16
- end
17
- end
18
-
19
- class OrderFormatter < RSpec::Core::Formatters::BaseFormatter
20
- def stop
21
- File.open(filename, 'wb') do |f|
22
- Marshal.dump(results, f)
23
- end
24
-
25
- super
26
- end
27
-
28
- private
29
-
30
- def filename
31
- ENV['RSPEC_SAD_RESULTS'] or raise "No result filename provided"
32
- end
33
-
34
- def results
35
- examples.map do |e|
36
- {
37
- location: e.location,
38
- failed: !!e.exception
39
- }
40
- end
41
- end
42
- end
43
-
44
- class LocationSource
45
- def enabled?
46
- filename && File.exist?(filename)
47
- end
48
-
49
- def example_locations_to_run
50
- raise "LocationSource is not currently enabled" unless enabled?
51
-
52
- File.open(filename, 'rb') do |f|
53
- Marshal.load(f)
54
- end
55
- end
56
-
57
- private
58
-
59
- def filename
60
- ENV['RSPEC_SAD_EXAMPLES']
61
- end
62
- end
63
-
64
- class ReorderAndFilter
65
- attr_reader :source
66
-
67
- def initialize(source)
68
- @source = source
69
- end
70
-
71
- def block
72
- lambda do |examples|
73
- locations = source.example_locations_to_run
74
-
75
- enabled_examples = examples.select do |e|
76
- locations.include? e.location
77
- end
78
-
79
- enabled_examples.sort_by do |e|
80
- locations.index(e.location)
81
- end
82
- end
83
- end
84
- end
85
14
 
86
- class RSpecResults
87
- attr_reader :results
88
-
89
- def initialize(results)
90
- @results = results
91
- end
92
-
93
- def causal_examples
94
- results.slice(0, failure_index)
95
- end
96
-
97
- def failed_example
98
- results[failure_index]
99
- end
100
-
101
- def failed?
102
- results.find {|result| result[:failed] }
103
- end
104
-
105
- private
106
-
107
- def failure_index
108
- @failure_index ||= results.find_index { |r| r[:failed] }
109
- end
110
- end
111
-
112
- class RSpecDriver
113
- RESULT_FILE = '/tmp/example-results'
114
- EXAMPLE_FILE = '/tmp/examples-to-run'
115
-
116
- def load_run_results
117
- File.open(RESULT_FILE, 'rb') do |f|
118
- RSpecResults.new(Marshal.load(f))
119
- end
120
- end
121
-
122
- def initial_run
123
- cleanup
124
- run_rspec
125
- end
126
-
127
- def run_examples(examples)
128
- locations = examples.map {|x| x[:location]}
129
-
130
- File.open(EXAMPLE_FILE, 'wb') do |f|
131
- Marshal.dump(locations, f)
132
- end
133
-
134
- run_rspec
135
- end
136
-
137
- def cleanup
138
- [EXAMPLE_FILE, RESULT_FILE].each do |fname|
139
- File.delete(fname) if File.exist? fname
140
- end
141
- end
142
-
143
- private
144
-
145
- def run_rspec
146
- env = {
147
- "RSPEC_SAD_EXAMPLES" => EXAMPLE_FILE,
148
- "RSPEC_SAD_RESULTS" => RESULT_FILE
149
- }
150
- cmd = "rspec"
151
-
152
- success = system(env, cmd)
153
-
154
- raise "unable to run command: #{cmd}" if success.nil?
15
+ config.files_or_directories_to_run = source.example_locations_to_run
16
+ config.order_examples(&ordering.block)
155
17
  end
156
18
  end
157
19
  end
@@ -0,0 +1,21 @@
1
+ module RSpecSearchAndDestroy
2
+ class LocationSource
3
+ def enabled?
4
+ filename && File.exist?(filename)
5
+ end
6
+
7
+ def example_locations_to_run
8
+ raise "LocationSource is not currently enabled" unless enabled?
9
+
10
+ File.open(filename, 'rb') do |f|
11
+ Marshal.load(f)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def filename
18
+ ENV['RSPEC_SAD_EXAMPLES']
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,28 @@
1
+ require 'rspec/core/formatters/base_formatter'
2
+
3
+ module RSpecSearchAndDestroy
4
+ class OrderFormatter < RSpec::Core::Formatters::BaseFormatter
5
+ def stop
6
+ File.open(filename, 'wb') do |f|
7
+ Marshal.dump(results, f)
8
+ end
9
+
10
+ super
11
+ end
12
+
13
+ private
14
+
15
+ def filename
16
+ ENV['RSPEC_SAD_RESULTS'] or raise "No result filename provided"
17
+ end
18
+
19
+ def results
20
+ examples.map do |e|
21
+ {
22
+ location: e.location,
23
+ failed: !!e.exception
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ module RSpecSearchAndDestroy
2
+ class ReorderAndFilter
3
+ attr_reader :source
4
+
5
+ def initialize(source)
6
+ @source = source
7
+ end
8
+
9
+ def block
10
+ lambda do |examples|
11
+ locations = source.example_locations_to_run
12
+
13
+ enabled_examples = examples.select do |e|
14
+ locations.include? e.location
15
+ end
16
+
17
+ enabled_examples.sort_by do |e|
18
+ locations.index(e.location)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,56 @@
1
+ require_relative 'rspec_results'
2
+
3
+ module RSpecSearchAndDestroy
4
+ class RSpecDriver
5
+ RESULT_FILE = '/tmp/example-results'
6
+ EXAMPLE_FILE = '/tmp/examples-to-run'
7
+
8
+ def load_run_results
9
+ unless File.exist? RESULT_FILE
10
+ raise <<ERR
11
+ The RSpec result file was not created. Please ensure that SAD is
12
+ added to your RSpec configuration.
13
+ ERR
14
+ end
15
+
16
+ File.open(RESULT_FILE, 'rb') do |f|
17
+ RSpecResults.new(Marshal.load(f))
18
+ end
19
+ end
20
+
21
+ def initial_run
22
+ cleanup
23
+ run_rspec
24
+ end
25
+
26
+ def run_examples(examples)
27
+ locations = examples.map {|x| x[:location]}
28
+
29
+ File.open(EXAMPLE_FILE, 'wb') do |f|
30
+ Marshal.dump(locations, f)
31
+ end
32
+
33
+ run_rspec
34
+ end
35
+
36
+ def cleanup
37
+ [EXAMPLE_FILE, RESULT_FILE].each do |fname|
38
+ File.delete(fname) if File.exist? fname
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def run_rspec
45
+ env = {
46
+ "RSPEC_SAD_EXAMPLES" => EXAMPLE_FILE,
47
+ "RSPEC_SAD_RESULTS" => RESULT_FILE
48
+ }
49
+ cmd = "rspec"
50
+
51
+ success = system(env, cmd)
52
+
53
+ raise "unable to run command: #{cmd}" if success.nil?
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ module RSpecSearchAndDestroy
2
+ class RSpecResults
3
+ attr_reader :results
4
+
5
+ def initialize(results)
6
+ @results = results
7
+ end
8
+
9
+ def causal_examples
10
+ results.slice(0, failure_index)
11
+ end
12
+
13
+ def failed_example
14
+ results[failure_index]
15
+ end
16
+
17
+ def failed?
18
+ results.find {|result| result[:failed] }
19
+ end
20
+
21
+ private
22
+
23
+ def failure_index
24
+ @failure_index ||= results.find_index { |r| r[:failed] }
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module RSpecSearchAndDestroy
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -5,6 +5,7 @@ require 'rspec-search-and-destroy/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "rspec-search-and-destroy"
8
+ gem.license = 'MIT'
8
9
  gem.version = RSpecSearchAndDestroy::VERSION
9
10
  gem.authors = ["Jake Goulding"]
10
11
  gem.email = ["jake.goulding@gmail.com"]
@@ -17,5 +18,8 @@ Gem::Specification.new do |gem|
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
19
  gem.require_paths = ["lib"]
19
20
 
20
- gem.add_dependency('rspec', '>= 2.14.0')
21
+ gem.add_dependency('rspec', '~> 2.12')
22
+
23
+ gem.add_development_dependency('rspec', '~> 2.14')
24
+ gem.add_development_dependency('aruba')
21
25
  end
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.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,56 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-24 00:00:00.000000000 Z
12
+ date: 2013-09-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.14.0
21
+ version: '2.12'
22
22
  type: :runtime
23
23
  prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.12'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.14'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.14'
46
+ - !ruby/object:Gem::Dependency
47
+ name: aruba
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
24
56
  version_requirements: !ruby/object:Gem::Requirement
25
57
  none: false
26
58
  requirements:
27
59
  - - ! '>='
28
60
  - !ruby/object:Gem::Version
29
- version: 2.14.0
61
+ version: '0'
30
62
  description: ! 'Finds RSpec test ordering bugs '
31
63
  email:
32
64
  - jake.goulding@gmail.com
@@ -37,16 +69,25 @@ extra_rdoc_files: []
37
69
  files:
38
70
  - .gitignore
39
71
  - .rspec
72
+ - .travis.yml
40
73
  - Gemfile
41
74
  - LICENSE.txt
42
75
  - README.md
43
76
  - Rakefile
44
77
  - bin/rspec-sad
45
- - examples/spec/bad_ordering_spec.rb
46
- - examples/spec/spec_helper.rb
78
+ - features/before_all_blocks_are_disabled.feature
79
+ - features/bisecting_a_single_file.feature
80
+ - features/bisecting_multiple_files.feature
81
+ - features/support/env.rb
82
+ - features/support/steps.rb
47
83
  - lib/rspec-sad.rb
48
84
  - lib/rspec-search-and-destroy/binary_chop_example_selector.rb
49
85
  - lib/rspec-search-and-destroy/bisector.rb
86
+ - lib/rspec-search-and-destroy/location_source.rb
87
+ - lib/rspec-search-and-destroy/order_formatter.rb
88
+ - lib/rspec-search-and-destroy/reorder_and_filter.rb
89
+ - lib/rspec-search-and-destroy/rspec_driver.rb
90
+ - lib/rspec-search-and-destroy/rspec_results.rb
50
91
  - lib/rspec-search-and-destroy/version.rb
51
92
  - rspec-search-and-destroy.gemspec
52
93
  - spec/binary_chop_example_selector_spec.rb
@@ -54,7 +95,8 @@ files:
54
95
  - spec/rspec_example_ordering_spec.rb
55
96
  - spec/spec_helper.rb
56
97
  homepage: https://github.com/shepmaster/rspec-search-and-destroy
57
- licenses: []
98
+ licenses:
99
+ - MIT
58
100
  post_install_message:
59
101
  rdoc_options: []
60
102
  require_paths:
@@ -78,6 +120,11 @@ signing_key:
78
120
  specification_version: 3
79
121
  summary: Finds RSpec test ordering bugs
80
122
  test_files:
123
+ - features/before_all_blocks_are_disabled.feature
124
+ - features/bisecting_a_single_file.feature
125
+ - features/bisecting_multiple_files.feature
126
+ - features/support/env.rb
127
+ - features/support/steps.rb
81
128
  - spec/binary_chop_example_selector_spec.rb
82
129
  - spec/bisector_spec.rb
83
130
  - spec/rspec_example_ordering_spec.rb
@@ -1,16 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe "Tests that fail when run in a specific order" do
4
- it "leaves bad global state" do
5
- $fail_next = true
6
- expect($fail_next).to be_true
7
- end
8
-
9
- it "just takes up space" do
10
- expect(true).to be_true
11
- end
12
-
13
- it "fails when run last" do
14
- expect($fail_next).to be_false
15
- end
16
- end
@@ -1,15 +0,0 @@
1
- require 'rspec-sad'
2
-
3
- RSpec.configure do |config|
4
- config.treat_symbols_as_metadata_keys_with_true_values = true
5
- config.run_all_when_everything_filtered = true
6
- config.filter_run :focus
7
-
8
- config.color = true
9
- config.formatter = 'documentation'
10
-
11
- # For this example, run in an order that is guaranteed to be bad
12
- config.order = 'default'
13
-
14
- RSpecSearchAndDestroy.configure(config)
15
- end