rspec-core 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|