rspec-core 2.0.0.beta.12 → 2.0.0.beta.13
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +14 -0
- data/Rakefile +15 -12
- data/VERSION +1 -1
- data/features/command_line/example_name_option.feature +17 -3
- data/features/command_line/exit_status.feature +49 -0
- data/features/hooks/before_and_after_hooks.feature +51 -19
- data/features/hooks/halt.feature +1 -1
- data/features/support/env.rb +5 -3
- data/lib/rspec/core/command_line.rb +14 -5
- data/lib/rspec/core/configuration.rb +14 -24
- data/lib/rspec/core/configuration_options.rb +13 -8
- data/lib/rspec/core/drb_command_line.rb +2 -3
- data/lib/rspec/core/example.rb +5 -5
- data/lib/rspec/core/example_group.rb +23 -25
- data/lib/rspec/core/formatters/base_text_formatter.rb +13 -4
- data/lib/rspec/core/hooks.rb +57 -24
- data/lib/rspec/core/metadata.rb +1 -1
- data/lib/rspec/core/pending.rb +3 -3
- data/lib/rspec/core/rake_task.rb +48 -11
- data/lib/rspec/core/runner.rb +19 -8
- data/lib/rspec/core/subject.rb +3 -3
- data/lib/rspec/core/world.rb +3 -7
- data/rspec-core.gemspec +16 -12
- data/spec/rspec/core/command_line_spec.rb +72 -0
- data/spec/rspec/core/configuration_options_spec.rb +12 -3
- data/spec/rspec/core/configuration_spec.rb +6 -1
- data/spec/rspec/core/deprecations_spec.rb +19 -0
- data/spec/rspec/core/drb_command_line_spec.rb +1 -1
- data/spec/rspec/core/example_group_spec.rb +120 -12
- data/spec/rspec/core/example_spec.rb +27 -17
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +23 -0
- data/spec/rspec/core/metadata_spec.rb +32 -0
- data/spec/rspec/core/runner_spec.rb +2 -1
- data/spec/rspec/core/shared_example_group_spec.rb +1 -1
- data/spec/spec_helper.rb +49 -51
- data/specs.watchr +1 -1
- metadata +31 -27
data/lib/rspec/core/example.rb
CHANGED
@@ -2,7 +2,7 @@ module RSpec
|
|
2
2
|
module Core
|
3
3
|
class Example
|
4
4
|
|
5
|
-
attr_reader :metadata, :example_block
|
5
|
+
attr_reader :metadata, :example_block, :options
|
6
6
|
|
7
7
|
def self.delegate_to_metadata(*keys)
|
8
8
|
keys.each do |key|
|
@@ -33,7 +33,7 @@ module RSpec
|
|
33
33
|
def run(example_group_instance, reporter)
|
34
34
|
@in_block = false
|
35
35
|
@example_group_instance = example_group_instance
|
36
|
-
@example_group_instance.
|
36
|
+
@example_group_instance.example = self
|
37
37
|
|
38
38
|
run_started
|
39
39
|
|
@@ -43,10 +43,10 @@ module RSpec
|
|
43
43
|
run_before_each
|
44
44
|
pending_declared_in_example = catch(:pending_declared_in_example) do
|
45
45
|
@in_block = true
|
46
|
-
if @example_group_class.
|
46
|
+
if @example_group_class.hooks[:around][:each].empty?
|
47
47
|
@example_group_instance.instance_eval(&example_block) unless pending
|
48
48
|
else
|
49
|
-
@example_group_class.
|
49
|
+
@example_group_class.hooks[:around][:each].first.call(AroundProxy.new(self, &example_block))
|
50
50
|
end
|
51
51
|
throw :pending_declared_in_example, false
|
52
52
|
end
|
@@ -62,7 +62,7 @@ module RSpec
|
|
62
62
|
rescue Exception => e
|
63
63
|
exception ||= e
|
64
64
|
ensure
|
65
|
-
@example_group_instance.
|
65
|
+
@example_group_instance.example = nil
|
66
66
|
end
|
67
67
|
|
68
68
|
if exception
|
@@ -6,7 +6,12 @@ module RSpec
|
|
6
6
|
include Let
|
7
7
|
include Pending
|
8
8
|
|
9
|
-
attr_accessor :
|
9
|
+
attr_accessor :example
|
10
|
+
|
11
|
+
def running_example
|
12
|
+
RSpec.deprecate('running_example', 'example')
|
13
|
+
example
|
14
|
+
end
|
10
15
|
|
11
16
|
def self.world
|
12
17
|
RSpec.world
|
@@ -135,36 +140,30 @@ module RSpec
|
|
135
140
|
@before_all_ivars ||= {}
|
136
141
|
end
|
137
142
|
|
138
|
-
def self.eval_before_alls(
|
143
|
+
def self.eval_before_alls(example)
|
139
144
|
return if descendant_filtered_examples.empty?
|
140
|
-
superclass.before_all_ivars.each { |ivar, val|
|
141
|
-
world.
|
145
|
+
superclass.before_all_ivars.each { |ivar, val| example.instance_variable_set(ivar, val) }
|
146
|
+
world.run_hook_filtered(:before, :all, self, example)
|
142
147
|
|
143
|
-
|
144
|
-
|
145
|
-
end
|
146
|
-
running_example.instance_variables.each { |ivar| before_all_ivars[ivar] = running_example.instance_variable_get(ivar) }
|
148
|
+
run_hook!(:before, :all, example, :reverse => true)
|
149
|
+
example.instance_variables.each { |ivar| before_all_ivars[ivar] = example.instance_variable_get(ivar) }
|
147
150
|
end
|
148
151
|
|
149
|
-
def self.eval_before_eachs(
|
150
|
-
world.
|
151
|
-
ancestors.reverse.each { |ancestor| ancestor.
|
152
|
+
def self.eval_before_eachs(example)
|
153
|
+
world.run_hook_filtered(:before, :each, self, example)
|
154
|
+
ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example) }
|
152
155
|
end
|
153
156
|
|
154
|
-
def self.eval_after_eachs(
|
155
|
-
ancestors.each { |ancestor| ancestor.
|
156
|
-
world.
|
157
|
+
def self.eval_after_eachs(example)
|
158
|
+
ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example, :reverse => true) }
|
159
|
+
world.run_hook_filtered(:after, :each, self, example)
|
157
160
|
end
|
158
161
|
|
159
|
-
def self.eval_after_alls(
|
162
|
+
def self.eval_after_alls(example)
|
160
163
|
return if descendant_filtered_examples.empty?
|
161
|
-
before_all_ivars.each { |ivar, val|
|
162
|
-
ancestors.each
|
163
|
-
|
164
|
-
running_example.instance_eval &ancestor.after_alls.pop
|
165
|
-
end
|
166
|
-
end
|
167
|
-
world.run_hook(:after, :all, self, running_example)
|
164
|
+
before_all_ivars.each { |ivar, val| example.instance_variable_set(ivar, val) }
|
165
|
+
ancestors.each {|ancestor| ancestor.run_hook!(:after, :all, example) }
|
166
|
+
world.run_hook_filtered(:after, :all, self, example)
|
168
167
|
end
|
169
168
|
|
170
169
|
def self.run(reporter)
|
@@ -172,9 +171,8 @@ module RSpec
|
|
172
171
|
reporter.add_example_group(self)
|
173
172
|
begin
|
174
173
|
eval_before_alls(example_group_instance)
|
175
|
-
|
176
|
-
|
177
|
-
result_for_this_group && (children.empty? ? true : results_for_descendants)
|
174
|
+
run_examples(example_group_instance, reporter) &&
|
175
|
+
children.map {|child| child.run(reporter)}.all?
|
178
176
|
ensure
|
179
177
|
eval_after_alls(example_group_instance)
|
180
178
|
end
|
@@ -38,12 +38,10 @@ module RSpec
|
|
38
38
|
def dump_summary
|
39
39
|
failure_count = failed_examples.size
|
40
40
|
pending_count = pending_examples.size
|
41
|
-
|
42
41
|
|
43
|
-
|
42
|
+
output.puts "\nFinished in #{format_seconds(duration)} seconds\n"
|
44
43
|
|
45
|
-
summary =
|
46
|
-
summary << ", #{pending_count} pending" if pending_count > 0
|
44
|
+
summary = summary_line(example_count, failure_count, pending_count)
|
47
45
|
|
48
46
|
if failure_count == 0
|
49
47
|
if pending_count > 0
|
@@ -68,6 +66,17 @@ module RSpec
|
|
68
66
|
output.flush
|
69
67
|
end
|
70
68
|
|
69
|
+
def summary_line(example_count, failure_count, pending_count)
|
70
|
+
summary = pluralize(example_count, "example")
|
71
|
+
summary << ", " << pluralize(failure_count, "failure")
|
72
|
+
summary << ", #{pending_count} pending" if pending_count > 0
|
73
|
+
summary
|
74
|
+
end
|
75
|
+
|
76
|
+
def pluralize(count, string)
|
77
|
+
"#{count} #{string}#{'s' unless count == 1}"
|
78
|
+
end
|
79
|
+
|
71
80
|
def format_caller(caller_info)
|
72
81
|
caller_info.to_s.split(':in `block').first
|
73
82
|
end
|
data/lib/rspec/core/hooks.rb
CHANGED
@@ -1,49 +1,82 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
3
|
module Hooks
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
class Hook
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options, block)
|
8
|
+
@options = options
|
9
|
+
@block = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def options_apply?(group)
|
13
|
+
!group || group.all_apply?(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
@block.call
|
18
|
+
end
|
7
19
|
|
8
|
-
|
9
|
-
|
20
|
+
def to_proc
|
21
|
+
@block
|
22
|
+
end
|
10
23
|
end
|
11
24
|
|
12
|
-
def
|
13
|
-
@
|
25
|
+
def hooks
|
26
|
+
@hooks ||= {
|
27
|
+
:around => { :each => [] },
|
28
|
+
:before => { :each => [], :all => [], :suite => [] },
|
29
|
+
:after => { :each => [], :all => [], :suite => [] }
|
30
|
+
}
|
14
31
|
end
|
15
32
|
|
16
|
-
def
|
17
|
-
|
33
|
+
def before(scope=:each, options={}, &block)
|
34
|
+
hooks[:before][scope] << Hook.new(options, block)
|
18
35
|
end
|
19
36
|
|
20
|
-
def
|
21
|
-
|
37
|
+
def after(scope=:each, options={}, &block)
|
38
|
+
hooks[:after][scope] << Hook.new(options, block)
|
22
39
|
end
|
23
40
|
|
24
|
-
def
|
25
|
-
|
41
|
+
def around(scope=:each, &block)
|
42
|
+
RSpec::deprecate("around", "before and after")
|
43
|
+
hooks[:around][scope] << block
|
26
44
|
end
|
27
45
|
|
28
|
-
|
29
|
-
|
46
|
+
# Runs all of the blocks stored with the hook in the context of the
|
47
|
+
# example. If no example is provided, just calls the hook directly.
|
48
|
+
def run_hook(hook, scope, example=nil, options={})
|
49
|
+
if options[:reverse]
|
50
|
+
hooks[hook][scope].reverse.each &run_hook_in(example)
|
51
|
+
else
|
52
|
+
hooks[hook][scope].each &run_hook_in(example)
|
53
|
+
end
|
30
54
|
end
|
31
55
|
|
32
|
-
|
33
|
-
|
56
|
+
# Just like run_hook, except it removes the blocks as it evalutes them,
|
57
|
+
# ensuring that they will only be run once.
|
58
|
+
def run_hook!(hook, scope, example, options={})
|
59
|
+
until hooks[hook][scope].empty?
|
60
|
+
if options[:reverse]
|
61
|
+
example.instance_eval &hooks[hook][scope].shift
|
62
|
+
else
|
63
|
+
example.instance_eval &hooks[hook][scope].pop
|
64
|
+
end
|
65
|
+
end
|
34
66
|
end
|
35
67
|
|
36
|
-
def
|
37
|
-
|
68
|
+
def run_hook_filtered(hook, scope, group, example)
|
69
|
+
find_hook(hook, scope, group).each &run_hook_in(example)
|
38
70
|
end
|
39
71
|
|
40
|
-
def
|
41
|
-
|
72
|
+
def find_hook(hook, scope, group)
|
73
|
+
hooks[hook][scope].select {|hook| hook.options_apply?(group)}
|
42
74
|
end
|
43
75
|
|
44
|
-
|
45
|
-
|
46
|
-
|
76
|
+
private
|
77
|
+
|
78
|
+
def run_hook_in(example)
|
79
|
+
lambda {|hook| example ? example.instance_eval(&hook) : hook.call}
|
47
80
|
end
|
48
81
|
end
|
49
82
|
end
|
data/lib/rspec/core/metadata.rb
CHANGED
data/lib/rspec/core/pending.rb
CHANGED
@@ -2,12 +2,12 @@ module RSpec
|
|
2
2
|
module Core
|
3
3
|
module Pending
|
4
4
|
def pending(message = 'No reason given')
|
5
|
-
|
6
|
-
|
5
|
+
example.metadata[:pending] = true
|
6
|
+
example.metadata[:execution_result][:pending_message] = message
|
7
7
|
if block_given?
|
8
8
|
begin
|
9
9
|
result = yield
|
10
|
-
|
10
|
+
example.metadata[:pending] = false
|
11
11
|
rescue Exception => e
|
12
12
|
end
|
13
13
|
raise RSpec::Core::PendingExampleFixedError.new if result
|
data/lib/rspec/core/rake_task.rb
CHANGED
@@ -35,16 +35,20 @@ module RSpec
|
|
35
35
|
# Use rcov for code coverage? defaults to false
|
36
36
|
attr_accessor :rcov
|
37
37
|
|
38
|
+
# Path to rcov. You can set this to 'bundle exec rcov' if you bundle rcov.
|
39
|
+
attr_accessor :rcov_path
|
40
|
+
|
38
41
|
# The options to pass to rcov. Defaults to blank
|
39
42
|
attr_accessor :rcov_opts
|
40
43
|
|
41
44
|
def initialize(*args)
|
42
45
|
@name = args.shift || :spec
|
43
|
-
@pattern, @rcov_opts, @ruby_opts = nil, nil, nil
|
46
|
+
@pattern, @rcov_path, @rcov_opts, @ruby_opts = nil, nil, nil, nil
|
44
47
|
@warning, @rcov = false, false
|
45
48
|
@fail_on_error = true
|
46
49
|
|
47
50
|
yield self if block_given?
|
51
|
+
@rcov_path ||= 'rcov'
|
48
52
|
@pattern ||= './spec/**/*_spec.rb'
|
49
53
|
define
|
50
54
|
end
|
@@ -58,18 +62,30 @@ module RSpec
|
|
58
62
|
if files_to_run.empty?
|
59
63
|
puts "No examples matching #{pattern} could be found"
|
60
64
|
else
|
61
|
-
cmd_parts = [
|
62
|
-
cmd_parts += rcov ? [rcov_opts] : [ruby_opts]
|
63
|
-
cmd_parts << '-Ilib'
|
64
|
-
cmd_parts << '-Ispec'
|
65
|
+
cmd_parts = [ '-Ilib', '-Ispec' ]
|
65
66
|
cmd_parts << "-w" if warning
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
67
|
+
|
68
|
+
if rcov
|
69
|
+
command_to_run = rcov_command(cmd_parts)
|
70
|
+
command_to_run.inspect if verbose
|
71
|
+
|
72
|
+
unless system(command_to_run)
|
73
|
+
STDERR.puts failure_message if failure_message
|
74
|
+
raise("#{command_to_run} failed") if fail_on_error
|
75
|
+
end
|
76
|
+
else
|
77
|
+
cmd_parts.concat(files_to_run)
|
78
|
+
puts cmd.inspect if verbose
|
79
|
+
|
80
|
+
require 'rspec/core'
|
81
|
+
RSpec::Core::Runner.disable_at_exit_hook!
|
82
|
+
|
83
|
+
unless RSpec::Core::Runner.run(cmd_parts, $stderr, $stdout)
|
84
|
+
STDERR.puts failure_message if failure_message
|
85
|
+
raise("RSpec::Core::Runner.run with args #{cmd_parts.inspect} failed") if fail_on_error
|
86
|
+
end
|
72
87
|
end
|
88
|
+
|
73
89
|
end
|
74
90
|
end
|
75
91
|
end
|
@@ -81,6 +97,27 @@ module RSpec
|
|
81
97
|
FileList[ pattern ].to_a
|
82
98
|
end
|
83
99
|
|
100
|
+
private
|
101
|
+
|
102
|
+
def rcov_command(cmd_parts)
|
103
|
+
cmd_parts.unshift runner_options
|
104
|
+
cmd_parts.unshift runner
|
105
|
+
cmd_parts.unshift bundler
|
106
|
+
cmd_parts += files_to_run.map { |fn| %["#{fn}"] }
|
107
|
+
cmd_parts.join(" ")
|
108
|
+
end
|
109
|
+
|
110
|
+
def runner
|
111
|
+
rcov ? rcov_path : RUBY
|
112
|
+
end
|
113
|
+
|
114
|
+
def runner_options
|
115
|
+
rcov ? [rcov_opts] : [ruby_opts]
|
116
|
+
end
|
117
|
+
|
118
|
+
def bundler
|
119
|
+
File.exist?("./Gemfile") ? "bundle exec " : ""
|
120
|
+
end
|
84
121
|
end
|
85
122
|
|
86
123
|
end
|
data/lib/rspec/core/runner.rb
CHANGED
@@ -4,12 +4,20 @@ module RSpec
|
|
4
4
|
module Core
|
5
5
|
class Runner
|
6
6
|
|
7
|
+
def self.at_exit_hook_disabled?
|
8
|
+
@no_at_exit_hook ||= false
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.disable_at_exit_hook!
|
12
|
+
@no_at_exit_hook = true
|
13
|
+
end
|
14
|
+
|
7
15
|
def self.installed_at_exit?
|
8
16
|
@installed_at_exit ||= false
|
9
17
|
end
|
10
18
|
|
11
19
|
def self.autorun
|
12
|
-
return if installed_at_exit? || running_in_drb?
|
20
|
+
return if at_exit_hook_disabled? || installed_at_exit? || running_in_drb?
|
13
21
|
@installed_at_exit = true
|
14
22
|
at_exit { run(ARGV, $stderr, $stdout) ? exit(0) : exit(1) }
|
15
23
|
end
|
@@ -20,19 +28,22 @@ module RSpec
|
|
20
28
|
end
|
21
29
|
|
22
30
|
def self.run(args, err, out)
|
23
|
-
|
24
|
-
|
31
|
+
options = ConfigurationOptions.new(args)
|
32
|
+
options.parse_options
|
33
|
+
|
34
|
+
if options.options[:drb]
|
35
|
+
run_over_drb(options, err, out) || run_in_process(options, err, out)
|
25
36
|
else
|
26
|
-
run_in_process(
|
37
|
+
run_in_process(options, err, out)
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
def self.run_over_drb(
|
31
|
-
DRbCommandLine.new(
|
41
|
+
def self.run_over_drb(options, err, out)
|
42
|
+
DRbCommandLine.new(options).run(err, out)
|
32
43
|
end
|
33
44
|
|
34
|
-
def self.run_in_process(
|
35
|
-
CommandLine.new(
|
45
|
+
def self.run_in_process(options, err, out)
|
46
|
+
CommandLine.new(options).run(err, out)
|
36
47
|
end
|
37
48
|
|
38
49
|
end
|
data/lib/rspec/core/subject.rb
CHANGED
@@ -80,12 +80,12 @@ module RSpec
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def attribute_of_subject
|
83
|
-
original_subject.send(
|
83
|
+
original_subject.send(example.description) if using_attribute?
|
84
84
|
end
|
85
85
|
|
86
86
|
def using_attribute?
|
87
|
-
|
88
|
-
|
87
|
+
example.in_block? &&
|
88
|
+
example.metadata[:attribute_of_subject]
|
89
89
|
end
|
90
90
|
|
91
91
|
end
|
data/lib/rspec/core/world.rb
CHANGED
@@ -67,15 +67,11 @@ module RSpec
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
end
|
70
|
-
|
71
|
-
|
72
|
-
find_hook(hook, scope, group).each { |blk| example.instance_eval(&blk) }
|
73
|
-
end
|
70
|
+
|
71
|
+
include RSpec::Core::Hooks
|
74
72
|
|
75
73
|
def find_hook(hook, scope, group)
|
76
|
-
RSpec.configuration.
|
77
|
-
group.all_apply?(filters)
|
78
|
-
end.map { |filters, block| block }
|
74
|
+
RSpec.configuration.find_hook(hook, scope, group)
|
79
75
|
end
|
80
76
|
|
81
77
|
private
|