rspec-core 2.1.0 → 2.2.0

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 (38) hide show
  1. data/Gemfile +16 -11
  2. data/History.markdown +22 -0
  3. data/License.txt +2 -1
  4. data/{README.markdown → README.md} +11 -3
  5. data/Rakefile +1 -0
  6. data/Upgrade.markdown +35 -2
  7. data/features/hooks/around_hooks.feature +18 -2
  8. data/lib/rspec/core/configuration.rb +38 -36
  9. data/lib/rspec/core/configuration_options.rb +2 -1
  10. data/lib/rspec/core/deprecation.rb +1 -1
  11. data/lib/rspec/core/example.rb +19 -9
  12. data/lib/rspec/core/example_group.rb +14 -26
  13. data/lib/rspec/core/extensions/kernel.rb +23 -3
  14. data/lib/rspec/core/formatters/base_text_formatter.rb +43 -30
  15. data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
  16. data/lib/rspec/core/formatters/html_formatter.rb +10 -8
  17. data/lib/rspec/core/hooks.rb +2 -2
  18. data/lib/rspec/core/metadata.rb +46 -34
  19. data/lib/rspec/core/option_parser.rb +2 -2
  20. data/lib/rspec/core/rake_task.rb +1 -1
  21. data/lib/rspec/core/ruby_project.rb +2 -2
  22. data/lib/rspec/core/runner.rb +2 -2
  23. data/lib/rspec/core/subject.rb +4 -3
  24. data/lib/rspec/core/version.rb +1 -1
  25. data/rspec-core.gemspec +1 -1
  26. data/spec/rspec/core/configuration_options_spec.rb +7 -5
  27. data/spec/rspec/core/configuration_spec.rb +58 -69
  28. data/spec/rspec/core/example_group_spec.rb +22 -7
  29. data/spec/rspec/core/example_spec.rb +1 -1
  30. data/spec/rspec/core/formatters/documentation_formatter_spec.rb +2 -2
  31. data/spec/rspec/core/kernel_extensions_spec.rb +6 -3
  32. data/spec/rspec/core/metadata_spec.rb +13 -0
  33. data/spec/rspec/core/pending_example_spec.rb +1 -1
  34. data/spec/rspec/core/rake_task_spec.rb +2 -3
  35. data/spec/spec_helper.rb +1 -0
  36. metadata +9 -11
  37. data/.treasure_map.rb +0 -23
  38. data/specs.watchr +0 -58
@@ -1,5 +1,25 @@
1
1
  module Kernel
2
- def debugger(*args)
3
- RSpec.configuration.error_stream.puts "debugger statement ignored, use -d or --debug option to enable debugging\n#{caller(0)[1]}"
4
- end unless respond_to?(:debugger)
2
+
3
+ private
4
+
5
+ def method_missing(m, *a)
6
+ if m.to_s == 'debugger'
7
+ begin
8
+ require 'ruby-debug'
9
+ debugger
10
+ rescue LoadError => e
11
+ warn <<-EOM
12
+ #{'*'*50}
13
+ The debugger statement on the following line was ignored:
14
+
15
+ #{caller(0).detect {|l| l !~ /method_missing/}}
16
+
17
+ To use the debugger statement, you must install ruby-debug.
18
+ #{'*'*50}
19
+ EOM
20
+ end
21
+ else
22
+ super
23
+ end
24
+ end
5
25
  end
@@ -15,32 +15,9 @@ module RSpec
15
15
  output.puts
16
16
  output.puts "Failures:"
17
17
  failed_examples.each_with_index do |example, index|
18
- output.puts if index > 0
19
- exception = example.execution_result[:exception_encountered]
20
- short_padding = ' '
21
- padding = ' '
22
- if exception.is_a?(RSpec::Core::PendingExampleFixedError)
23
- output.puts "#{short_padding}#{index.next}) #{example.full_description} FIXED"
24
- output.puts "#{padding}Expected pending '#{example.metadata[:execution_result][:pending_message]}' to fail. No Error was raised."
25
- else
26
- output.puts "#{short_padding}#{index.next}) #{example.full_description}"
27
- output.puts "#{padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
28
- exception.message.split("\n").each do |line|
29
- output.puts "#{padding}#{red(line)}"
30
- end
31
-
32
- example.example_group.ancestors.push(example.example_group).each do |group|
33
- if group.metadata[:shared_group_name]
34
- output.puts "#{padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
35
- "#{backtrace_line(group.metadata[:example_group][:location])}"
36
- break
37
- end
38
- end
39
- end
40
-
41
- format_backtrace(exception.backtrace, example).each do |backtrace_info|
42
- output.puts grey("#{padding}# #{backtrace_info}")
43
- end
18
+ output.puts
19
+ dump_pending_example_fixed(example, index) || dump_failure(example, index)
20
+ dump_backtrace(example)
44
21
  end
45
22
  end
46
23
 
@@ -69,7 +46,7 @@ module RSpec
69
46
  output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
70
47
  sorted_examples.each do |example|
71
48
  output.puts " #{example.full_description}"
72
- output.puts grey(" #{red(format_seconds(example.execution_result[:run_time]))} #{red("seconds")} #{format_caller(example.metadata[:location])}")
49
+ output.puts grey(" #{red(format_seconds(example.execution_result[:run_time]))} #{red("seconds")} #{format_caller(example.location)}")
73
50
  end
74
51
  end
75
52
 
@@ -86,8 +63,8 @@ module RSpec
86
63
  output.puts "Pending:"
87
64
  pending_examples.each do |pending_example|
88
65
  output.puts yellow(" #{pending_example.full_description}")
89
- output.puts grey(" # #{pending_example.metadata[:execution_result][:pending_message]}")
90
- output.puts grey(" # #{format_caller(pending_example.metadata[:location])}")
66
+ output.puts grey(" # #{pending_example.execution_result[:pending_message]}")
67
+ output.puts grey(" # #{format_caller(pending_example.location)}")
91
68
  end
92
69
  end
93
70
  end
@@ -134,6 +111,14 @@ module RSpec
134
111
  color(text, "\e[90m")
135
112
  end
136
113
 
114
+ def short_padding
115
+ ' '
116
+ end
117
+
118
+ def long_padding
119
+ ' '
120
+ end
121
+
137
122
  private
138
123
 
139
124
  def pluralize(count, string)
@@ -144,8 +129,36 @@ module RSpec
144
129
  backtrace_line(caller_info.to_s.split(':in `block').first)
145
130
  end
146
131
 
147
- end
132
+ def dump_backtrace(example)
133
+ format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info|
134
+ output.puts grey("#{long_padding}# #{backtrace_info}")
135
+ end
136
+ end
137
+
138
+ def dump_pending_example_fixed(example, index)
139
+ if RSpec::Core::PendingExampleFixedError === example.execution_result[:exception]
140
+ output.puts "#{short_padding}#{index.next}) #{example.full_description} FIXED"
141
+ output.puts blue("#{long_padding}Expected pending '#{example.metadata[:execution_result][:pending_message]}' to fail. No Error was raised.")
142
+ true
143
+ end
144
+ end
145
+
146
+ def dump_failure(example, index)
147
+ exception = example.execution_result[:exception]
148
+ output.puts "#{short_padding}#{index.next}) #{example.full_description}"
149
+ output.puts "#{long_padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
150
+ exception.message.split("\n").each { |line| output.puts "#{long_padding}#{red(line)}" }
148
151
 
152
+ example.example_group.ancestors.push(example.example_group).each do |group|
153
+ if group.metadata[:shared_group_name]
154
+ output.puts "#{long_padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
155
+ "#{backtrace_line(group.metadata[:example_group][:location])}"
156
+ break
157
+ end
158
+ end
159
+ end
160
+
161
+ end
149
162
  end
150
163
  end
151
164
  end
@@ -36,7 +36,7 @@ module RSpec
36
36
 
37
37
  def example_failed(example)
38
38
  super(example)
39
- output.puts failure_output(example, example.execution_result[:exception_encountered])
39
+ output.puts failure_output(example, example.execution_result[:exception])
40
40
  end
41
41
 
42
42
  def failure_output(example, exception)
@@ -7,13 +7,6 @@ module RSpec
7
7
  class HtmlFormatter < BaseTextFormatter
8
8
  include ERB::Util # for the #h method
9
9
 
10
- def method_missing(m, *a, &b)
11
- # no-op
12
- end
13
-
14
- def message(message)
15
- end
16
-
17
10
  def initialize(output)
18
11
  super(output)
19
12
  @example_group_number = 0
@@ -21,6 +14,15 @@ module RSpec
21
14
  @header_red = nil
22
15
  end
23
16
 
17
+ private
18
+ def method_missing(m, *a, &b)
19
+ # no-op
20
+ end
21
+
22
+ public
23
+ def message(message)
24
+ end
25
+
24
26
  # The number of the currently running example_group
25
27
  def example_group_number
26
28
  @example_group_number
@@ -71,7 +73,7 @@ module RSpec
71
73
 
72
74
  def example_failed(example)
73
75
  counter = 0
74
- exception = example.metadata[:execution_result][:exception_encountered]
76
+ exception = example.metadata[:execution_result][:exception]
75
77
  extra = extra_failure_content(exception)
76
78
  failure_style = 'failed'
77
79
  failure_style = RSpec::Core::PendingExampleFixedError === exception ? 'pending_fixed' : 'failed'
@@ -57,7 +57,7 @@ module RSpec
57
57
 
58
58
  class BeforeHooks < HookCollection
59
59
  def run_all(example_group_instance)
60
- each {|h| h.run_in(example_group_instance) }
60
+ each {|h| h.run_in(example_group_instance) } unless empty?
61
61
  end
62
62
 
63
63
  def run_all!(example_group_instance)
@@ -67,7 +67,7 @@ module RSpec
67
67
 
68
68
  class AfterHooks < HookCollection
69
69
  def run_all(example_group_instance)
70
- reverse.each {|h| h.run_in(example_group_instance) }
70
+ reverse.each {|h| h.run_in(example_group_instance) } unless empty?
71
71
  end
72
72
 
73
73
  def run_all!(example_group_instance)
@@ -2,14 +2,46 @@ module RSpec
2
2
  module Core
3
3
  class Metadata < Hash
4
4
 
5
+ module LocationKeys
6
+ def [](key)
7
+ return super if has_key?(key)
8
+ case key
9
+ when :location
10
+ store(:location, location)
11
+ when :file_path, :line_number
12
+ file_path, line_number = file_and_line_number
13
+ store(:file_path, file_path)
14
+ store(:line_number, line_number)
15
+ self[key]
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def location
22
+ "#{self[:file_path]}:#{self[:line_number]}"
23
+ end
24
+
25
+ def file_and_line_number
26
+ first_caller_from_outside_rspec =~ /(.+?):(\d+)(|:\d+)/
27
+ return [$1, $2.to_i]
28
+ end
29
+
30
+ def first_caller_from_outside_rspec
31
+ self[:caller].detect {|l| l !~ /\/lib\/rspec\/core/}
32
+ end
33
+ end
34
+
5
35
  def initialize(superclass_metadata=nil)
6
36
  @superclass_metadata = superclass_metadata
7
37
  if @superclass_metadata
8
38
  update(@superclass_metadata)
9
39
  example_group = {:example_group => @superclass_metadata[:example_group]}
40
+ else
41
+ example_group = {}
10
42
  end
11
43
 
12
- store(:example_group, example_group || {})
44
+ store(:example_group, example_group.extend(LocationKeys))
13
45
  yield self if block_given?
14
46
  end
15
47
 
@@ -27,13 +59,11 @@ module RSpec
27
59
  user_metadata = args.last.is_a?(Hash) ? args.pop : {}
28
60
  ensure_valid_keys(user_metadata)
29
61
 
30
- self[:example_group][:describes] = described_class_from(*args)
31
- self[:example_group][:description] = description_from(*args)
32
- self[:example_group][:full_description] = full_description_from(*args)
33
-
34
- self[:example_group][:block] = user_metadata.delete(:example_group_block)
35
- self[:example_group][:file_path], self[:example_group][:line_number] = file_and_line_number_from(user_metadata.delete(:caller) || caller)
36
- self[:example_group][:location] = location_from(self[:example_group])
62
+ self[:example_group].store(:caller, user_metadata.delete(:caller) || caller)
63
+ self[:example_group].store(:describes, described_class_from(*args))
64
+ self[:example_group].store(:description, description_from(*args))
65
+ self[:example_group].store(:full_description, full_description_from(*args))
66
+ self[:example_group].store(:block, user_metadata.delete(:example_group_block))
37
67
 
38
68
  update(user_metadata)
39
69
  end
@@ -60,17 +90,16 @@ EOM
60
90
  end
61
91
  end
62
92
 
63
- def for_example(description, options)
64
- dup.configure_for_example(description,options)
93
+ def for_example(description, user_metadata)
94
+ dup.extend(LocationKeys).configure_for_example(description, user_metadata)
65
95
  end
66
96
 
67
- def configure_for_example(description, options)
97
+ def configure_for_example(description, user_metadata)
68
98
  store(:description, description.to_s)
69
99
  store(:full_description, "#{self[:example_group][:full_description]} #{self[:description]}")
70
100
  store(:execution_result, {})
71
- self[:file_path], self[:line_number] = file_and_line_number_from(options.delete(:caller) || caller)
72
- self[:location] = location_from(self)
73
- update(options)
101
+ store(:caller, user_metadata.delete(:caller) || caller)
102
+ update(user_metadata)
74
103
  end
75
104
 
76
105
  def apply?(predicate, filters)
@@ -88,8 +117,7 @@ EOM
88
117
  end
89
118
  end
90
119
 
91
- def apply_condition(key, value, metadata=nil)
92
- metadata ||= self
120
+ def apply_condition(key, value, metadata=self)
93
121
  case value
94
122
  when Hash
95
123
  value.all? { |k, v| apply_condition(k, v, metadata[key]) }
@@ -150,26 +178,10 @@ EOM
150
178
  end
151
179
 
152
180
  def described_class_from(*args)
153
- if args.first.is_a?(String) || args.first.is_a?(Symbol)
154
- superclass_metadata[:example_group][:describes]
155
- else
156
- args.first
181
+ superclass_metadata[:example_group][:describes] || begin
182
+ args.first unless args.first.is_a?(String) || args.first.is_a?(Symbol)
157
183
  end
158
184
  end
159
-
160
- def file_and_line_number_from(list)
161
- entry = first_caller_from_outside_rspec_from_caller(list)
162
- entry =~ /(.+?):(\d+)(|:\d+)/
163
- return [$1, $2.to_i]
164
- end
165
-
166
- def first_caller_from_outside_rspec_from_caller(list)
167
- list.detect {|l| l !~ /\/lib\/rspec\/core/}
168
- end
169
-
170
- def location_from(metadata)
171
- "#{metadata[:file_path]}:#{metadata[:line_number]}"
172
- end
173
185
  end
174
186
  end
175
187
  end
@@ -96,8 +96,8 @@ module RSpec::Core
96
96
  options[:drb_port] = o.to_i
97
97
  end
98
98
 
99
- parser.on('--autotest') do |o|
100
- options[:autotest] = true
99
+ parser.on('--tty') do |o|
100
+ options[:tty] = true
101
101
  end
102
102
 
103
103
  parser.on('--fail-fast', 'Use the fail_fast option to tell RSpec to abort the run on first failure.') do |o|
@@ -161,7 +161,7 @@ module RSpec
161
161
  cmd_parts << "bundle exec" if gemfile? unless skip_bundler
162
162
  cmd_parts << runner
163
163
  if rcov
164
- cmd_parts << ["-Ispec", "-Ilib", rcov_opts]
164
+ cmd_parts << ["-Ispec:lib", rcov_opts]
165
165
  else
166
166
  cmd_parts << rspec_opts
167
167
  end
@@ -27,9 +27,9 @@ module RSpec
27
27
  ascend_until {|path| File.exists?(File.join(path, dir))}
28
28
  end
29
29
 
30
- def ascend_until(&block) # :nodoc:
30
+ def ascend_until # :nodoc:
31
31
  Pathname(File.expand_path('.')).ascend do |path|
32
- return path if block.call(path)
32
+ return path if yield(path)
33
33
  end
34
34
  end
35
35
 
@@ -23,8 +23,8 @@ module RSpec
23
23
  end
24
24
 
25
25
  def self.running_in_drb?
26
- (DRb.current_server rescue false) &&
27
- !!((DRb.current_server.uri) =~ /druby\:\/\/127.0.0.1\:/)
26
+ (DRb.current_server rescue false) &&
27
+ DRb.current_server.uri =~ /druby\:\/\/127.0.0.1\:/
28
28
  end
29
29
 
30
30
  def self.trap_interrupt
@@ -88,9 +88,10 @@ module RSpec
88
88
  # onto the subject in an expression.
89
89
  #
90
90
  # describe Person do
91
- # let(:person) do
92
- # person = Person.new
93
- # person.phone_numbers << "555-1212"
91
+ # subject do
92
+ # Person.new.tap do |person|
93
+ # person.phone_numbers << "555-1212"
94
+ # end
94
95
  # end
95
96
  #
96
97
  # its("phone_numbers.first") { should == "555-1212" }
@@ -1,7 +1,7 @@
1
1
  module RSpec # :nodoc:
2
2
  module Core # :nodoc:
3
3
  module Version # :nodoc:
4
- STRING = '2.1.0'
4
+ STRING = '2.2.0'
5
5
  end
6
6
  end
7
7
  end
data/rspec-core.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
19
19
  s.files = `git ls-files`.split("\n")
20
20
  s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
21
21
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
- s.extra_rdoc_files = [ "README.markdown" ]
22
+ s.extra_rdoc_files = [ "README.md" ]
23
23
  s.rdoc_options = ["--charset=UTF-8"]
24
24
  s.require_path = "lib"
25
25
 
@@ -165,13 +165,11 @@ describe RSpec::Core::ConfigurationOptions do
165
165
  end
166
166
  end
167
167
 
168
- it "sends all the arguments other than --drb back to the parser after parsing options" do
168
+ it "does not send --drb back to the parser after parsing options" do
169
169
  config_options_object("--drb", "--color").drb_argv.should_not include("--drb")
170
170
  end
171
171
  end
172
172
 
173
-
174
- # TODO #drb_argv may not be the best name
175
173
  # TODO ensure all options are output
176
174
  # TODO check if we need to spec that the short options are "expanded" ("-v" becomes "--version" currently)
177
175
  describe "#drb_argv" do
@@ -180,6 +178,10 @@ describe RSpec::Core::ConfigurationOptions do
180
178
  config_options_object(*%w[ a --drb b --color c ]).drb_argv.should =~ %w[ --color a b c ]
181
179
  end
182
180
 
181
+ it "includes --fail-fast" do
182
+ config_options_object(*%w[--fail-fast]).drb_argv.should include("--fail-fast")
183
+ end
184
+
183
185
  context "--drb specified in ARGV" do
184
186
  it "renders all the original arguments except --drb" do
185
187
  config_options_object(*%w[ --drb --color --format s --line_number 1 --example pattern --profile --backtrace -I path/a -I path/b --require path/c --require path/d]).
@@ -191,8 +193,8 @@ describe RSpec::Core::ConfigurationOptions do
191
193
  it "renders all the original arguments except --drb" do
192
194
  File.stub(:exist?) { true }
193
195
  IO.stub(:read) { "--drb --color" }
194
- config_options_object(*%w[ --autotest --format s --line_number 1 --example pattern --profile --backtrace ]).
195
- drb_argv.should eq(%w[ --color --profile --backtrace --autotest --format s --line_number 1 --example pattern ])
196
+ config_options_object(*%w[ --tty --format s --line_number 1 --example pattern --profile --backtrace ]).
197
+ drb_argv.should eq(%w[ --color --profile --backtrace --tty --format s --line_number 1 --example pattern ])
196
198
  end
197
199
  end
198
200