rspec-core 2.0.0.beta.22 → 2.0.0.rc

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.
Files changed (67) hide show
  1. data/Gemfile +2 -2
  2. data/{History.md → History.markdown} +24 -2
  3. data/Rakefile +1 -0
  4. data/Upgrade.markdown +36 -3
  5. data/bin/rspec +1 -2
  6. data/features/command_line/configure.feature +4 -4
  7. data/features/command_line/example_name_option.feature +17 -3
  8. data/features/command_line/exit_status.feature +13 -28
  9. data/features/command_line/line_number_appended_to_path.feature +12 -16
  10. data/features/command_line/line_number_option.feature +4 -5
  11. data/features/command_line/rake_task.feature +68 -0
  12. data/features/configuration/custom_settings.feature +2 -4
  13. data/features/configuration/fail_fast.feature +77 -0
  14. data/features/configuration/read_options_from_file.feature +2 -5
  15. data/features/example_groups/basic_structure.feature +54 -0
  16. data/features/example_groups/shared_example_group.feature +38 -27
  17. data/features/filtering/exclusion_filters.feature +40 -4
  18. data/features/filtering/inclusion_filters.feature +36 -27
  19. data/features/filtering/run_all_when_everything_filtered.feature +46 -0
  20. data/features/hooks/before_and_after_hooks.feature +21 -1
  21. data/features/pending/pending_examples.feature +24 -5
  22. data/lib/rspec/autorun.rb +2 -0
  23. data/lib/rspec/core.rb +6 -4
  24. data/lib/rspec/core/configuration.rb +69 -23
  25. data/lib/rspec/core/configuration_options.rb +1 -0
  26. data/lib/rspec/core/example.rb +0 -1
  27. data/lib/rspec/core/example_group.rb +23 -8
  28. data/lib/rspec/core/formatters/base_formatter.rb +14 -4
  29. data/lib/rspec/core/formatters/base_text_formatter.rb +2 -0
  30. data/lib/rspec/core/formatters/documentation_formatter.rb +2 -0
  31. data/lib/rspec/core/formatters/progress_formatter.rb +1 -0
  32. data/lib/rspec/core/metadata.rb +18 -11
  33. data/lib/rspec/core/option_parser.rb +6 -1
  34. data/lib/rspec/core/rake_task.rb +10 -10
  35. data/lib/rspec/core/runner.rb +20 -1
  36. data/lib/rspec/core/subject.rb +26 -3
  37. data/lib/rspec/core/version.rb +1 -1
  38. data/lib/rspec/core/world.rb +2 -1
  39. data/spec/autotest/failed_results_re_spec.rb +1 -1
  40. data/spec/rspec/core/configuration_spec.rb +13 -0
  41. data/spec/rspec/core/example_group_spec.rb +107 -26
  42. data/spec/rspec/core/example_spec.rb +11 -24
  43. data/spec/rspec/core/formatters/base_formatter_spec.rb +17 -1
  44. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +6 -5
  45. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +3 -2
  46. data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +25 -22
  47. data/spec/rspec/core/formatters/html_formatted-1.8.7.html +23 -20
  48. data/spec/rspec/core/formatters/html_formatted-1.9.1.html +25 -22
  49. data/spec/rspec/core/formatters/html_formatted-1.9.2.html +25 -2
  50. data/spec/rspec/core/formatters/html_formatter_spec.rb +10 -2
  51. data/spec/rspec/core/formatters/progress_formatter_spec.rb +1 -0
  52. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -0
  53. data/spec/rspec/core/hooks_filtering_spec.rb +5 -5
  54. data/spec/rspec/core/hooks_spec.rb +4 -4
  55. data/spec/rspec/core/metadata_spec.rb +20 -0
  56. data/spec/rspec/core/option_parser_spec.rb +16 -0
  57. data/spec/rspec/core/rake_task_spec.rb +0 -1
  58. data/spec/rspec/core/reporter_spec.rb +1 -1
  59. data/spec/rspec/core/runner_spec.rb +18 -0
  60. data/spec/rspec/core/shared_example_group_spec.rb +2 -2
  61. data/spec/spec_helper.rb +14 -3
  62. metadata +54 -45
  63. data/.rspec +0 -1
  64. data/features/example_groups/describe_aliases.feature +0 -25
  65. data/features/example_groups/nested_groups.feature +0 -44
  66. data/lib/rspec/core/around_proxy.rb +0 -14
  67. data/lib/rspec/core/formatters.rb +0 -8
@@ -0,0 +1,46 @@
1
+ Feature: run all when everything filtered
2
+
3
+ Use the run_all_when_everything_filtered configuration option to do just
4
+ that. This works well when paired with an inclusion filter like ":focus =>
5
+ true", as it will run all the examples when none match the inclusion filter.
6
+
7
+ Background:
8
+ Given a file named "spec/spec_helper.rb" with:
9
+ """
10
+ RSpec.configure do |c|
11
+ c.filter_run :focus => true
12
+ c.run_all_when_everything_filtered = true
13
+ end
14
+ """
15
+
16
+ Scenario: no examples match filter (runs all examples)
17
+ Given a file named "spec/sample_spec.rb" with:
18
+ """
19
+ require "spec_helper"
20
+
21
+ describe "group 1" do
22
+ it "group 1 example 1" do
23
+ end
24
+
25
+ it "group 1 example 2" do
26
+ end
27
+ end
28
+
29
+ describe "group 2" do
30
+ it "group 2 example 1" do
31
+ end
32
+ end
33
+ """
34
+ When I run "rspec spec/sample_spec.rb --format doc"
35
+ Then the output should contain "No examples were matched by {:focus=>true}, running all"
36
+ And the output should contain "3 examples, 0 failures"
37
+ And the output should contain:
38
+ """
39
+ group 1
40
+ group 1 example 1
41
+ group 1 example 2
42
+
43
+ group 2
44
+ group 2 example 1
45
+ """
46
+
@@ -114,15 +114,33 @@ Feature: before and after hooks
114
114
  after(:all) do
115
115
  puts "after all ran"
116
116
  end
117
+
118
+ describe "nested group" do
119
+ it "fails this third example" do
120
+ end
121
+
122
+ it "fails this fourth example" do
123
+ end
124
+
125
+ describe "yet another level deep" do
126
+ it "fails this last example" do
127
+ end
128
+ end
129
+ end
117
130
  end
118
131
  """
119
132
  When I run "rspec ./before_all_spec.rb --format documentation"
120
- Then the output should contain "2 examples, 2 failures"
133
+ Then the output should contain "5 examples, 5 failures"
121
134
  And the output should contain:
122
135
  """
123
136
  an error in before(:all)
124
137
  fails this example (FAILED - 1)
125
138
  fails this example, too (FAILED - 2)
139
+ nested group
140
+ fails this third example (FAILED - 3)
141
+ fails this fourth example (FAILED - 4)
142
+ yet another level deep
143
+ fails this last example (FAILED - 5)
126
144
  after all ran
127
145
  """
128
146
 
@@ -132,6 +150,8 @@ Feature: before and after hooks
132
150
  """
133
151
  an error in before(:all)
134
152
  fails this example, too (FAILED - 1)
153
+ nested group
154
+ yet another level deep
135
155
  after all ran
136
156
  """
137
157
 
@@ -1,6 +1,6 @@
1
1
  Feature: pending examples
2
2
 
3
- RSpec offers three ways to indicate that an example is disabled pending
3
+ RSpec offers four ways to indicate that an example is disabled pending
4
4
  some action.
5
5
 
6
6
  Scenario: pending implementation
@@ -10,7 +10,7 @@ Feature: pending examples
10
10
  it "is a pending example"
11
11
  end
12
12
  """
13
- When I run "rspec ./example_without_block_spec.rb"
13
+ When I run "rspec example_without_block_spec.rb"
14
14
  Then the exit status should be 0
15
15
  And the output should contain "1 example, 0 failures, 1 pending"
16
16
  And the output should contain "Not Yet Implemented"
@@ -26,7 +26,7 @@ Feature: pending examples
26
26
  end
27
27
  end
28
28
  """
29
- When I run "rspec ./pending_without_block_spec.rb"
29
+ When I run "rspec pending_without_block_spec.rb"
30
30
  Then the exit status should be 0
31
31
  And the output should contain "1 example, 0 failures, 1 pending"
32
32
  And the output should contain:
@@ -48,7 +48,7 @@ Feature: pending examples
48
48
  end
49
49
  end
50
50
  """
51
- When I run "rspec ./pending_with_failing_block_spec.rb"
51
+ When I run "rspec pending_with_failing_block_spec.rb"
52
52
  Then the exit status should be 0
53
53
  And the output should contain "1 example, 0 failures, 1 pending"
54
54
  And the output should contain:
@@ -70,9 +70,28 @@ Feature: pending examples
70
70
  end
71
71
  end
72
72
  """
73
- When I run "rspec ./pending_with_passing_block_spec.rb"
73
+ When I run "rspec pending_with_passing_block_spec.rb"
74
74
  Then the exit status should not be 0
75
75
  And the output should contain "1 example, 1 failure"
76
76
  And the output should contain "FIXED"
77
77
  And the output should contain "Expected pending 'something else getting finished' to fail. No Error was raised."
78
78
  And the output should contain "pending_with_passing_block_spec.rb:3"
79
+
80
+ Scenario: temporarily pending by changing "it" to "xit"
81
+ Given a file named "pending_with_xit_spec.rb" with:
82
+ """
83
+ describe "an example" do
84
+ xit "is pending using xit" do
85
+ true.should be(true)
86
+ end
87
+ end
88
+ """
89
+ When I run "rspec pending_with_xit_spec.rb"
90
+ Then the exit status should be 0
91
+ And the output should contain "1 example, 0 failures, 1 pending"
92
+ And the output should contain:
93
+ """
94
+ Pending:
95
+ an example is pending using xit
96
+ """
97
+
@@ -0,0 +1,2 @@
1
+ require 'rspec/core'
2
+ RSpec::Core::Runner.autorun
@@ -2,7 +2,6 @@ require 'rspec/core/extensions'
2
2
  require 'rspec/core/load_path'
3
3
  require 'rspec/core/deprecation'
4
4
  require 'rspec/core/reporter'
5
- require 'rspec/core/formatters'
6
5
 
7
6
  require 'rspec/core/hooks'
8
7
  require 'rspec/core/subject'
@@ -10,7 +9,6 @@ require 'rspec/core/let'
10
9
  require 'rspec/core/metadata'
11
10
  require 'rspec/core/pending'
12
11
 
13
- require 'rspec/core/around_proxy'
14
12
  require 'rspec/core/world'
15
13
  require 'rspec/core/configuration'
16
14
  require 'rspec/core/command_line_configuration'
@@ -49,8 +47,12 @@ module RSpec
49
47
 
50
48
  end
51
49
 
52
- class << self
53
- attr_accessor :wants_to_quit
50
+ def self.wants_to_quit
51
+ world.wants_to_quit
52
+ end
53
+
54
+ def self.wants_to_quit=(maybe)
55
+ world.wants_to_quit=(maybe)
54
56
  end
55
57
 
56
58
  def self.world
@@ -20,10 +20,12 @@ module RSpec
20
20
  add_setting :error_stream
21
21
  add_setting :output_stream
22
22
  add_setting :output, :alias => :output_stream
23
+ add_setting :out, :alias => :output_stream
23
24
  add_setting :drb
24
25
  add_setting :drb_port
25
26
  add_setting :color_enabled
26
27
  add_setting :profile_examples
28
+ add_setting :fail_fast, :default => false
27
29
  add_setting :run_all_when_everything_filtered
28
30
  add_setting :mock_framework, :default => :rspec
29
31
  add_setting :filter
@@ -31,7 +33,6 @@ module RSpec
31
33
  add_setting :filename_pattern, :default => '**/*_spec.rb'
32
34
  add_setting :files_to_run
33
35
  add_setting :include_or_extend_modules
34
- add_setting :formatter_class, :default => RSpec::Core::Formatters::ProgressFormatter
35
36
  add_setting :backtrace_clean_patterns
36
37
 
37
38
  def initialize
@@ -180,30 +181,20 @@ EOM
180
181
  filter_run :full_description => /#{description}/
181
182
  end
182
183
 
183
- def formatter=(formatter_to_use)
184
- if string_const?(formatter_to_use) && (class_name = eval(formatter_to_use)).is_a?(Class)
185
- formatter_class = class_name
186
- elsif formatter_to_use.is_a?(Class)
187
- formatter_class = formatter_to_use
188
- else
189
- formatter_class = case formatter_to_use.to_s
190
- when 'd', 'doc', 'documentation', 's', 'n', 'spec', 'nested'
191
- RSpec::Core::Formatters::DocumentationFormatter
192
- when 'h', 'html'
193
- RSpec::Core::Formatters::HtmlFormatter
194
- when 't', 'textmate'
195
- RSpec::Core::Formatters::TextMateFormatter
196
- when 'p', 'progress'
197
- RSpec::Core::Formatters::ProgressFormatter
198
- else
199
- raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?."
200
- end
201
- end
202
- self.formatter_class = formatter_class
184
+ attr_writer :formatter_class
185
+
186
+ def formatter_class
187
+ @formatter_class ||= begin
188
+ require 'rspec/core/formatters/progress_formatter'
189
+ RSpec::Core::Formatters::ProgressFormatter
190
+ end
203
191
  end
204
192
 
205
- def string_const?(str)
206
- str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
193
+ def formatter=(formatter_to_use)
194
+ self.formatter_class =
195
+ built_in_formatter(formatter_to_use) ||
196
+ custom_formatter(formatter_to_use) ||
197
+ (raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.")
207
198
  end
208
199
 
209
200
  def formatter
@@ -307,6 +298,61 @@ EOM
307
298
  def load_spec_files
308
299
  files_to_run.map {|f| load File.expand_path(f) }
309
300
  end
301
+
302
+ private
303
+
304
+ def built_in_formatter(key)
305
+ case key.to_s
306
+ when 'd', 'doc', 'documentation', 's', 'n', 'spec', 'nested'
307
+ require 'rspec/core/formatters/documentation_formatter'
308
+ RSpec::Core::Formatters::DocumentationFormatter
309
+ when 'h', 'html'
310
+ require 'rspec/core/formatters/html_formatter'
311
+ RSpec::Core::Formatters::HtmlFormatter
312
+ when 't', 'textmate'
313
+ require 'rspec/core/formatters/text_mate_formatter'
314
+ RSpec::Core::Formatters::TextMateFormatter
315
+ when 'p', 'progress'
316
+ require 'rspec/core/formatters/progress_formatter'
317
+ RSpec::Core::Formatters::ProgressFormatter
318
+ end
319
+ end
320
+
321
+ def custom_formatter(formatter_ref)
322
+ if Class === formatter_ref
323
+ formatter_ref
324
+ elsif string_const?(formatter_ref)
325
+ begin
326
+ eval(formatter_ref)
327
+ rescue NameError
328
+ require path_for(formatter_ref)
329
+ eval(formatter_ref)
330
+ end
331
+ end
332
+ end
333
+
334
+ def string_const?(str)
335
+ str.is_a?(String) && /\A[A-Z][a-zA-Z0-9_:]*\z/ =~ str
336
+ end
337
+
338
+ def path_for(const_ref)
339
+ underscore_with_fix_for_non_standard_rspec_naming(const_ref)
340
+ end
341
+
342
+ def underscore_with_fix_for_non_standard_rspec_naming(string)
343
+ underscore(string).sub(%r{(^|/)r_spec($|/)}, '\\1rspec\\2')
344
+ end
345
+
346
+ # activesupport/lib/active_support/inflector/methods.rb, line 48
347
+ def underscore(camel_cased_word)
348
+ word = camel_cased_word.to_s.dup
349
+ word.gsub!(/::/, '/')
350
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
351
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
352
+ word.tr!("-", "_")
353
+ word.downcase!
354
+ word
355
+ end
310
356
  end
311
357
  end
312
358
  end
@@ -84,6 +84,7 @@ module RSpec
84
84
  end
85
85
 
86
86
  def options_file_as_erb_string(path)
87
+ require 'erb'
87
88
  ERB.new(IO.read(path)).result(binding)
88
89
  end
89
90
 
@@ -37,7 +37,6 @@ module RSpec
37
37
  end
38
38
 
39
39
  def run(example_group_instance, reporter)
40
- return if RSpec.wants_to_quit
41
40
  @example_group_instance = example_group_instance
42
41
  @example_group_instance.example = self
43
42
 
@@ -20,7 +20,8 @@ module RSpec
20
20
  end
21
21
 
22
22
  def self.inherited(klass)
23
- world.example_groups << klass if klass.superclass == ExampleGroup
23
+ RSpec::Core::Runner.autorun
24
+ world.example_groups << klass if klass.top_level?
24
25
  end
25
26
 
26
27
  class << self
@@ -59,6 +60,7 @@ module RSpec
59
60
  alias_example_to :specify
60
61
  alias_example_to :focused, :focused => true
61
62
  alias_example_to :pending, :pending => true
63
+ alias_example_to :xit, :pending => true
62
64
 
63
65
  def self.define_shared_group_method(new_name, report_label=nil)
64
66
  module_eval(<<-END_RUBY, __FILE__, __LINE__)
@@ -93,7 +95,7 @@ module RSpec
93
95
  end
94
96
 
95
97
  def self.descendant_filtered_examples
96
- filtered_examples + children.collect{|c| c.descendant_filtered_examples}
98
+ @descendant_filtered_examples ||= filtered_examples + children.collect{|c| c.descendant_filtered_examples}.flatten
97
99
  end
98
100
 
99
101
  def self.metadata
@@ -101,7 +103,7 @@ module RSpec
101
103
  end
102
104
 
103
105
  def self.superclass_metadata
104
- self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
106
+ @superclass_metadata ||= self.superclass.respond_to?(:metadata) ? self.superclass.metadata : nil
105
107
  end
106
108
 
107
109
  def self.describe(*args, &example_group_block)
@@ -136,7 +138,7 @@ module RSpec
136
138
  end
137
139
 
138
140
  def self.descendants
139
- [self] + children.collect {|c| c.descendants}.flatten
141
+ @_descendants ||= [self] + children.collect {|c| c.descendants}.flatten
140
142
  end
141
143
 
142
144
  def self.ancestors
@@ -144,7 +146,7 @@ module RSpec
144
146
  end
145
147
 
146
148
  def self.top_level?
147
- ancestors.size == 1
149
+ @top_level ||= superclass == ExampleGroup
148
150
  end
149
151
 
150
152
  def self.set_it_up(*args)
@@ -199,7 +201,7 @@ module RSpec
199
201
  end
200
202
 
201
203
  def self.around_hooks
202
- (world.find_hook(:around, :each, self) + ancestors.reverse.map{|a| a.find_hook(:around, :each, self)}).flatten
204
+ @around_hooks ||= (world.find_hook(:around, :each, self) + ancestors.reverse.map{|a| a.find_hook(:around, :each, self)}).flatten
203
205
  end
204
206
 
205
207
  def self.run(reporter)
@@ -226,13 +228,26 @@ module RSpec
226
228
 
227
229
  def self.fail_filtered_examples(exception, reporter)
228
230
  filtered_examples.each { |example| example.fail_fast(reporter, exception) }
231
+
232
+ children.each do |child|
233
+ reporter.example_group_started(child)
234
+ child.fail_filtered_examples(exception, reporter)
235
+ reporter.example_group_finished(child)
236
+ end
237
+ end
238
+
239
+ def self.fail_fast?
240
+ RSpec.configuration.fail_fast?
229
241
  end
230
242
 
231
243
  def self.run_examples(instance, reporter)
232
244
  filtered_examples.map do |example|
245
+ next if RSpec.wants_to_quit
233
246
  begin
234
247
  set_ivars(instance, before_all_ivars)
235
- example.run(instance, reporter)
248
+ succeeded = example.run(instance, reporter)
249
+ RSpec.wants_to_quit = true if fail_fast? && !succeeded
250
+ succeeded
236
251
  ensure
237
252
  clear_ivars(instance)
238
253
  clear_memoized(instance)
@@ -245,7 +260,7 @@ module RSpec
245
260
  end
246
261
 
247
262
  def self.declaration_line_numbers
248
- [metadata[:example_group][:line_number]] +
263
+ @declaration_line_numbers ||= [metadata[:example_group][:line_number]] +
249
264
  examples.collect {|e| e.metadata[:line_number]} +
250
265
  children.collect {|c| c.declaration_line_numbers}.flatten
251
266
  end
@@ -1,3 +1,5 @@
1
+ require 'rspec/core/formatters/helpers'
2
+
1
3
  module RSpec
2
4
  module Core
3
5
  module Formatters
@@ -117,12 +119,12 @@ module RSpec
117
119
  end
118
120
 
119
121
  def read_failed_line(exception, example)
120
- original_file = example.file_path.to_s.downcase
121
- matching_line = exception.backtrace.detect { |line| line.match(/(.+?):(\d+)(|:\d+)/)[1].downcase == original_file.downcase }
122
-
123
- return "Unable to find matching line from backtrace" if matching_line.nil?
122
+ unless matching_line = find_failed_line(exception.backtrace, example.file_path)
123
+ return "Unable to find matching line from backtrace"
124
+ end
124
125
 
125
126
  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
127
+
126
128
  if File.exist?(file_path)
127
129
  open(file_path, 'r') { |f| f.readlines[line_number.to_i - 1] }
128
130
  else
@@ -130,6 +132,14 @@ module RSpec
130
132
  end
131
133
  end
132
134
 
135
+ def find_failed_line(backtrace, path)
136
+ backtrace.detect { |line|
137
+ match = line.match(/(.+?):(\d+)(|:\d+)/)
138
+ match && match[1].downcase == path.downcase
139
+ }
140
+
141
+ end
142
+
133
143
  def start_sync_output
134
144
  @old_sync, output.sync = output.sync, true if output_supports_sync
135
145
  end