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.
- data/Gemfile +16 -11
- data/History.markdown +22 -0
- data/License.txt +2 -1
- data/{README.markdown → README.md} +11 -3
- data/Rakefile +1 -0
- data/Upgrade.markdown +35 -2
- data/features/hooks/around_hooks.feature +18 -2
- data/lib/rspec/core/configuration.rb +38 -36
- data/lib/rspec/core/configuration_options.rb +2 -1
- data/lib/rspec/core/deprecation.rb +1 -1
- data/lib/rspec/core/example.rb +19 -9
- data/lib/rspec/core/example_group.rb +14 -26
- data/lib/rspec/core/extensions/kernel.rb +23 -3
- data/lib/rspec/core/formatters/base_text_formatter.rb +43 -30
- data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
- data/lib/rspec/core/formatters/html_formatter.rb +10 -8
- data/lib/rspec/core/hooks.rb +2 -2
- data/lib/rspec/core/metadata.rb +46 -34
- data/lib/rspec/core/option_parser.rb +2 -2
- data/lib/rspec/core/rake_task.rb +1 -1
- data/lib/rspec/core/ruby_project.rb +2 -2
- data/lib/rspec/core/runner.rb +2 -2
- data/lib/rspec/core/subject.rb +4 -3
- data/lib/rspec/core/version.rb +1 -1
- data/rspec-core.gemspec +1 -1
- data/spec/rspec/core/configuration_options_spec.rb +7 -5
- data/spec/rspec/core/configuration_spec.rb +58 -69
- data/spec/rspec/core/example_group_spec.rb +22 -7
- data/spec/rspec/core/example_spec.rb +1 -1
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +2 -2
- data/spec/rspec/core/kernel_extensions_spec.rb +6 -3
- data/spec/rspec/core/metadata_spec.rb +13 -0
- data/spec/rspec/core/pending_example_spec.rb +1 -1
- data/spec/rspec/core/rake_task_spec.rb +2 -3
- data/spec/spec_helper.rb +1 -0
- metadata +9 -11
- data/.treasure_map.rb +0 -23
- data/specs.watchr +0 -58
@@ -1,5 +1,25 @@
|
|
1
1
|
module Kernel
|
2
|
-
|
3
|
-
|
4
|
-
|
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
|
19
|
-
|
20
|
-
|
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.
|
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.
|
90
|
-
output.puts grey(" # #{format_caller(pending_example.
|
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
|
-
|
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[:
|
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][:
|
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'
|
data/lib/rspec/core/hooks.rb
CHANGED
@@ -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)
|
data/lib/rspec/core/metadata.rb
CHANGED
@@ -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]
|
31
|
-
self[:example_group]
|
32
|
-
self[:example_group]
|
33
|
-
|
34
|
-
self[:example_group]
|
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,
|
64
|
-
dup.configure_for_example(description,
|
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,
|
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
|
-
|
72
|
-
|
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=
|
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
|
-
|
154
|
-
|
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('--
|
100
|
-
options[:
|
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|
|
data/lib/rspec/core/rake_task.rb
CHANGED
@@ -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
|
30
|
+
def ascend_until # :nodoc:
|
31
31
|
Pathname(File.expand_path('.')).ascend do |path|
|
32
|
-
return path if
|
32
|
+
return path if yield(path)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
data/lib/rspec/core/runner.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/rspec/core/subject.rb
CHANGED
@@ -88,9 +88,10 @@ module RSpec
|
|
88
88
|
# onto the subject in an expression.
|
89
89
|
#
|
90
90
|
# describe Person do
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
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" }
|
data/lib/rspec/core/version.rb
CHANGED
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.
|
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 "
|
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[ --
|
195
|
-
drb_argv.should eq(%w[ --color --profile --backtrace --
|
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
|
|