rspec-bisect 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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: