rspec-bisect 0.1.2 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 38940973e6003e17ff03d56726279191d9af09cc
4
- data.tar.gz: 0b8e43a67e09a6d25f070ef62a85222cea27909b
3
+ metadata.gz: 3ae26473ff4df0634a51d1cb149db8de1df9a5f0
4
+ data.tar.gz: d0c40d6ca08d91bbbfedb30616e6c7f2529f9881
5
5
  SHA512:
6
- metadata.gz: 941276fbcd9fb96e271095d6ee8d07fffdc46c3a1e4cb4368c1e2c23bb5539883b65ab88d9fdec52af46a72672506f60f3a1e80e578f3f3b5ac507442b9e3306
7
- data.tar.gz: d5af173c24f9320302cab01327db0b44061f5c654dd80aeec31b7485d2ebd3f465ac5894af6988ec3909e53313aa24aea538e61b95215f166f68bd37267d399b
6
+ metadata.gz: 4d8e886acfb232845c89347698189aacf22480101c7c0812ca8434702b4060fee8b79ec8b0b5599f39e07601944323f7fb807212dd3a7122ca4aea3d02cdca78
7
+ data.tar.gz: fbd35cf90b3794d4559d397c6342b82b96673ee50b3c53253e353b21dbbd498b18c41f8e248c0339ad81058d56dcaa9dabddaaae933def8ad579f3c701380f6f
data/.gitignore CHANGED
@@ -17,4 +17,8 @@ mkmf.log
17
17
  .idea
18
18
 
19
19
  # Compiled gems
20
- *.gem
20
+ *.gem
21
+
22
+ # Bundled Gems
23
+ vendor
24
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -1,136 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'json'
4
- require 'colorize'
5
- require 'optparse'
6
- require 'ruby-progressbar'
3
+ require 'rspec/bisect'
7
4
 
8
- @options = {}
9
- def options
10
- @options
11
- end
12
-
13
- OptionParser.new do |opts|
14
- opts.banner = 'Usage: rspec-bisect [options]'
15
-
16
- opts.on('-s', '--seed N', Integer, 'Seed that causes order dependencies') do |s|
17
- options[:seed] = s
18
- end
19
-
20
- opts.on('--help', 'Show this message') do
21
- puts opts
22
- exit
23
- end
24
- end.parse!
25
-
26
- if options[:seed].nil?
27
- puts 'Running tests with no seed'
28
- else
29
- puts "Running tests with seed #{options[:seed]}"
30
- end
31
-
32
- def rspec_seed_argument
33
- options[:seed].nil? ? '' : "--seed #{options[:seed]}"
34
- end
35
-
36
- result = `rspec --format json #{rspec_seed_argument}`
37
- parsed = JSON.parse result
38
-
39
- examples = parsed['examples']
40
- failure_count = parsed['summary']['failure_count']
41
- if failure_count > 0
42
- puts "#{failure_count} failing test#{failure_count > 1 ? 's' : ''}.".red
43
- else
44
- puts 'No failing tests.'.green
45
- end
46
-
47
- failing_examples = examples.select { |e| e['status'] == 'failed' }
48
-
49
- def examples_as_rspec_params(examples)
50
- examples.map { |e| "#{e['file_path']}:#{e['line_number']}" }.join ' '
51
- end
52
-
53
- def run_examples_command(examples)
54
- "rspec #{examples_as_rspec_params(examples)} #{rspec_seed_argument}"
55
- end
56
-
57
- def run_examples(examples)
58
- `#{run_examples_command(examples)}`
59
- end
60
-
61
- def last_command_passed?
62
- $?.exitstatus == 0
63
- end
64
-
65
- def last_command_failed?
66
- not last_command_passed?
67
- end
68
-
69
- def progress_bar(additional_options)
70
- ProgressBar.create({format: '%t |%w>%i| %c/%C |%e'}.merge(additional_options))
71
- end
72
-
73
- dependent_examples_progress = progress_bar title: 'Detecting Dependent Examples',
74
- total: failing_examples.size
75
-
76
- order_dependent_examples = failing_examples.select do |example|
77
- run_examples([example])
78
- passed = last_command_passed?
79
- dependent_examples_progress.increment
80
- passed
81
- end
82
-
83
- if order_dependent_examples.size > 0
84
- puts "Order dependenc#{ order_dependent_examples.size > 1 ? 'ies' : 'y'} detected:"
85
- order_dependent_examples.each do |example|
86
- puts "\t#{example['full_description']}".red
87
- end
88
- else
89
- puts 'No order dependencies.'.green
90
- end
91
-
92
- order_dependent_examples.each do |example|
93
- puts
94
- puts "Culprits for #{example['full_description']}:"
95
-
96
- culprit_progress = progress_bar title: 'Determining culprits',
97
- total: nil,
98
- format: '%t |%i| %c potential culprits'
99
-
100
- culprits = examples.take_while do |e|
101
- example['file_path'] != e['file_path'] ||
102
- example['line_number'] != e['line_number']
103
- end
104
-
105
- culprit_progress.progress = culprits.size
106
-
107
- culprit_count_theory = 1
108
- while culprits.size > culprit_count_theory
109
- found_useless_group = false
110
- culprits.each_slice(culprits.size / (culprit_count_theory + 1)) do |excluded_culprits|
111
- culprit_progress.progress = culprits.size
112
-
113
- culprit_group = culprits - excluded_culprits
114
- run_examples culprit_group + [example]
115
-
116
- culprit_progress.progress = culprits.size
117
- if last_command_failed?
118
- culprits = culprit_group
119
-
120
- found_useless_group = true
121
- break
122
- end
123
- end
124
-
125
- culprit_count_theory += 1 unless found_useless_group
126
- end
127
-
128
- culprit_progress.stop
129
-
130
- culprits.each { |candidate| puts candidate['full_description'].green }
131
-
132
- puts example['full_description'].red
133
-
134
- puts (run_examples_command culprits + [example]).red
135
- end
5
+ include RSpec::Bisect::Reporters
6
+ reporter = ConsoleReporter.new
136
7
 
8
+ RSpec::Bisect::Runner.new(reporter: reporter).execute!
@@ -1,6 +1,9 @@
1
- require "rspec/bisect/version"
1
+ require 'rspec/bisect/version'
2
+ require 'rspec/bisect/runner'
3
+ require 'rspec/bisect/reporters'
4
+ require 'rspec/bisect/result'
2
5
 
3
- module Rspec
6
+ module RSpec
4
7
  module Bisect
5
8
  # Your code goes here...
6
9
  end
@@ -0,0 +1,2 @@
1
+ require 'rspec/bisect/reporters/reporter'
2
+ require 'rspec/bisect/reporters/console_reporter'
@@ -0,0 +1,23 @@
1
+ require 'colorize'
2
+
3
+ module RSpec
4
+ module Bisect
5
+ module Reporters
6
+ class ConsoleReporter
7
+ include Reporter
8
+
9
+ def report(text)
10
+ puts text
11
+ end
12
+
13
+ def report_success(text)
14
+ report text.green
15
+ end
16
+
17
+ def report_failure(text)
18
+ report text.red
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ module RSpec
2
+ module Bisect
3
+ module Reporters
4
+ module Reporter
5
+ def seed(seed)
6
+ if seed.nil?
7
+ report 'Running tests with no seed'
8
+ else
9
+ report "Running tests with seed #{seed}"
10
+ end
11
+ end
12
+
13
+ def failing_tests(failure_count)
14
+ if failure_count > 0
15
+ report_failure "#{failure_count} failing test#{failure_count > 1 ? 's' : ''}.".red
16
+ else
17
+ report_success 'No failing tests.'
18
+ end
19
+ end
20
+
21
+ def order_dependent_examples(examples)
22
+ if examples.size > 0
23
+ report "Order dependenc#{ examples.size > 1 ? 'ies' : 'y'} detected:"
24
+ examples.each do |example|
25
+ report_failure "\t#{example['full_description']}"
26
+ end
27
+ else
28
+ report_success 'No order dependencies.'
29
+ end
30
+ end
31
+
32
+ def determining_culprits(example)
33
+ report ''
34
+ report "Culprits for #{example['full_description']}:"
35
+ end
36
+
37
+ def culprits(culprits, example)
38
+ culprits.each { |culprit| puts culprit['full_description'].green }
39
+
40
+ report_failure example['full_description']
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,19 @@
1
+ module RSpec
2
+ module Bisect
3
+ class Result < Struct.new(:result_string)
4
+ class ParserError < StandardError; end
5
+
6
+ def as_json
7
+ parsed_lines = result_string.split("\n").lazy.map do |line|
8
+ begin
9
+ JSON.parse line
10
+ rescue JSON::ParserError
11
+ #ignored
12
+ end
13
+ end
14
+ parsed_result = parsed_lines.reject { |result| result.nil? }.first
15
+ parsed_result || raise(ParserError.new('Could not parse json'))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,130 @@
1
+ require 'json'
2
+ require 'optparse'
3
+ require 'ruby-progressbar'
4
+
5
+ module RSpec
6
+ module Bisect
7
+ class Runner
8
+ attr_accessor :reporter,
9
+ :result_parser
10
+
11
+ def initialize(reporter: reporter, result_parser: result_parser)
12
+ self.reporter = reporter
13
+ self.result_parser = result_parser
14
+ end
15
+
16
+ def execute!
17
+ @options = {}
18
+ def options
19
+ @options
20
+ end
21
+
22
+ OptionParser.new do |opts|
23
+ opts.banner = 'Usage: rspec-bisect [options]'
24
+
25
+ opts.on('-s', '--seed N', Integer, 'Seed that causes order dependencies') do |s|
26
+ options[:seed] = s
27
+ end
28
+
29
+ opts.on('--help', 'Show this message') do
30
+ puts opts
31
+ exit
32
+ end
33
+ end.parse!
34
+
35
+ reporter.seed options[:seed]
36
+
37
+ def rspec_seed_argument
38
+ options[:seed].nil? ? '' : "--seed #{options[:seed]}"
39
+ end
40
+
41
+ result = Result.new `rspec --format json #{rspec_seed_argument}`
42
+ parsed = result.as_json
43
+
44
+ examples = parsed['examples']
45
+ failure_count = parsed['summary']['failure_count']
46
+ reporter.failing_tests failure_count
47
+
48
+ failing_examples = examples.select { |e| e['status'] == 'failed' }
49
+
50
+ def examples_as_rspec_params(examples)
51
+ examples.map { |e| "#{e['file_path']}:#{e['line_number']}" }.join ' '
52
+ end
53
+
54
+ def run_examples_command(examples)
55
+ "rspec #{examples_as_rspec_params(examples)} #{rspec_seed_argument}"
56
+ end
57
+
58
+ def run_examples(examples)
59
+ `#{run_examples_command(examples)}`
60
+ end
61
+
62
+ def last_command_passed?
63
+ $?.exitstatus == 0
64
+ end
65
+
66
+ def last_command_failed?
67
+ not last_command_passed?
68
+ end
69
+
70
+ def progress_bar(additional_options)
71
+ ProgressBar.create({format: '%t |%w>%i| %c/%C |%e'}.merge(additional_options))
72
+ end
73
+
74
+ dependent_examples_progress = progress_bar title: 'Detecting Dependent Examples',
75
+ total: failing_examples.size
76
+
77
+ order_dependent_examples = failing_examples.select do |example|
78
+ run_examples([example])
79
+ passed = last_command_passed?
80
+ dependent_examples_progress.increment
81
+ passed
82
+ end
83
+
84
+ reporter.order_dependent_examples order_dependent_examples
85
+
86
+ order_dependent_examples.each do |example|
87
+ reporter.determining_culprits example
88
+
89
+ culprit_progress = progress_bar title: 'Determining culprits',
90
+ total: nil,
91
+ format: '%t |%i| %c potential culprits'
92
+
93
+ culprits = examples.take_while do |e|
94
+ example['file_path'] != e['file_path'] ||
95
+ example['line_number'] != e['line_number']
96
+ end
97
+
98
+ culprit_progress.progress = culprits.size
99
+
100
+ culprit_count_theory = 1
101
+ while culprits.size > culprit_count_theory
102
+ found_useless_group = false
103
+ culprits.each_slice(culprits.size / (culprit_count_theory + 1)) do |excluded_culprits|
104
+ culprit_progress.progress = culprits.size
105
+
106
+ culprit_group = culprits - excluded_culprits
107
+ run_examples culprit_group + [example]
108
+
109
+ culprit_progress.progress = culprits.size
110
+ if last_command_failed?
111
+ culprits = culprit_group
112
+
113
+ found_useless_group = true
114
+ break
115
+ end
116
+ end
117
+
118
+ culprit_count_theory += 1 unless found_useless_group
119
+ end
120
+
121
+ culprit_progress.stop
122
+
123
+ reporter.culprits culprits, example
124
+
125
+ reporter.report_failure run_examples_command culprits + [example]
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,5 +1,5 @@
1
1
  module Rspec
2
2
  module Bisect
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
5
5
  end
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "cucumber", "1.3.17"
24
24
  spec.add_development_dependency "aruba", "0.6.1"
25
- spec.add_dependency "rspec", "~> 3"
25
+ spec.add_dependency "rspec", "> 2.12"
26
26
  spec.add_dependency "colorize", "0.7.3"
27
27
  spec.add_dependency "ruby-progressbar", "1.6.1"
28
28
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ require 'json'
4
+ require 'rspec/bisect/result'
5
+
6
+ describe RSpec::Bisect::Result do
7
+ describe '#as_json' do
8
+ subject { described_class.new(result).as_json }
9
+
10
+ context 'with one line of json' do
11
+ let(:result) { { some: 'json' }.to_json }
12
+
13
+ it { is_expected.to eq({'some' => 'json'}) }
14
+ end
15
+
16
+ context 'with deprecation warnings' do
17
+ let(:result) do
18
+ "Don't use should, use expect instead
19
+ {\"some\": \"json\"}"
20
+ end
21
+
22
+ it { is_expected.to eq({'some' => 'json'}) }
23
+ end
24
+
25
+ context 'with bad output after json' do
26
+ let(:result) do
27
+ "{\"some\": \"json\"}
28
+ Something else to mess up our code..."
29
+ end
30
+
31
+ it { is_expected.to eq({'some' => 'json'}) }
32
+ end
33
+
34
+ context 'with no json' do
35
+ let(:result) do
36
+ "There's no json here
37
+ Go away"
38
+ end
39
+
40
+ it 'raises an exception' do
41
+ expect { subject }.to raise_error(RSpec::Bisect::Result::ParserError, 'Could not parse json')
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,89 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, consider making
10
+ # a separate helper file that requires the additional dependencies and performs
11
+ # the additional setup, and require it from the spec files that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # rspec-expectations config goes here. You can use an alternate
19
+ # assertion/expectation library such as wrong or the stdlib/minitest
20
+ # assertions if you prefer.
21
+ config.expect_with :rspec do |expectations|
22
+ # This option will default to `true` in RSpec 4. It makes the `description`
23
+ # and `failure_message` of custom matchers include text for helper methods
24
+ # defined using `chain`, e.g.:
25
+ # be_bigger_than(2).and_smaller_than(4).description
26
+ # # => "be bigger than 2 and smaller than 4"
27
+ # ...rather than:
28
+ # # => "be bigger than 2"
29
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
30
+ end
31
+
32
+ # rspec-mocks config goes here. You can use an alternate test double
33
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
34
+ config.mock_with :rspec do |mocks|
35
+ # Prevents you from mocking or stubbing a method that does not exist on
36
+ # a real object. This is generally recommended, and will default to
37
+ # `true` in RSpec 4.
38
+ mocks.verify_partial_doubles = true
39
+ end
40
+
41
+ # The settings below are suggested to provide a good initial experience
42
+ # with RSpec, but feel free to customize to your heart's content.
43
+ =begin
44
+ # These two settings work together to allow you to limit a spec run
45
+ # to individual examples or groups you care about by tagging them with
46
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
47
+ # get run.
48
+ config.filter_run :focus
49
+ config.run_all_when_everything_filtered = true
50
+
51
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
52
+ # For more details, see:
53
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
54
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
55
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
56
+ config.disable_monkey_patching!
57
+
58
+ # This setting enables warnings. It's recommended, but in some cases may
59
+ # be too noisy due to issues in dependencies.
60
+ config.warnings = true
61
+
62
+ # Many RSpec users commonly either run the entire suite or an individual
63
+ # file, and it's useful to allow more verbose output when running an
64
+ # individual spec file.
65
+ if config.files_to_run.one?
66
+ # Use the documentation formatter for detailed output,
67
+ # unless a formatter has already been configured
68
+ # (e.g. via a command-line flag).
69
+ config.default_formatter = 'doc'
70
+ end
71
+
72
+ # Print the 10 slowest examples and example groups at the
73
+ # end of the spec run, to help surface which specs are running
74
+ # particularly slow.
75
+ config.profile_examples = 10
76
+
77
+ # Run specs in random order to surface order dependencies. If you find an
78
+ # order dependency and want to debug it, you can fix the order by providing
79
+ # the seed, which is printed after each run.
80
+ # --seed 1234
81
+ config.order = :random
82
+
83
+ # Seed global randomization in this process using the `--seed` CLI option.
84
+ # Setting this allows you to use `--seed` to deterministically reproduce
85
+ # test failures related to randomization by passing the same `--seed` value
86
+ # as the one that triggered the failure.
87
+ Kernel.srand config.seed
88
+ =end
89
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-bisect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shelby Doolittle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-31 00:00:00.000000000 Z
11
+ date: 2015-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -70,16 +70,16 @@ dependencies:
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">"
74
74
  - !ruby/object:Gem::Version
75
- version: '3'
75
+ version: '2.12'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">"
81
81
  - !ruby/object:Gem::Version
82
- version: '3'
82
+ version: '2.12'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: colorize
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -118,6 +118,7 @@ extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
120
  - ".gitignore"
121
+ - ".rspec"
121
122
  - Gemfile
122
123
  - LICENSE.txt
123
124
  - README.md
@@ -133,8 +134,15 @@ files:
133
134
  - features/step_definitions/rspec-bisect_steps.rb
134
135
  - features/support/env.rb
135
136
  - lib/rspec/bisect.rb
137
+ - lib/rspec/bisect/reporters.rb
138
+ - lib/rspec/bisect/reporters/console_reporter.rb
139
+ - lib/rspec/bisect/reporters/reporter.rb
140
+ - lib/rspec/bisect/result.rb
141
+ - lib/rspec/bisect/runner.rb
136
142
  - lib/rspec/bisect/version.rb
137
143
  - rspec-bisect.gemspec
144
+ - spec/lib/rspec/bisect/result_spec.rb
145
+ - spec/spec_helper.rb
138
146
  homepage: https://github.com/shelbyd/rspec-bisect
139
147
  licenses:
140
148
  - MIT
@@ -169,4 +177,6 @@ test_files:
169
177
  - features/no_tests.feature
170
178
  - features/step_definitions/rspec-bisect_steps.rb
171
179
  - features/support/env.rb
180
+ - spec/lib/rspec/bisect/result_spec.rb
181
+ - spec/spec_helper.rb
172
182
  has_rdoc: