rspec-core 2.0.1 → 2.1.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 +8 -3
- data/Guardfile +5 -0
- data/History.markdown +32 -2
- data/README.markdown +10 -3
- data/Rakefile +12 -13
- data/Upgrade.markdown +175 -121
- data/bin/autospec +13 -0
- data/bin/rspec +24 -1
- data/features/command_line/line_number_appended_to_path.feature +3 -1
- data/features/command_line/line_number_option.feature +3 -1
- data/features/command_line/tag.feature +74 -0
- data/features/filtering/exclusion_filters.feature +1 -1
- data/features/filtering/implicit_filters.feature +166 -0
- data/features/hooks/around_hooks.feature +51 -44
- data/features/metadata/described_class.feature +3 -0
- data/features/pending/pending_examples.feature +76 -0
- data/features/step_definitions/additional_cli_steps.rb +11 -0
- data/features/subject/attribute_of_subject.feature +8 -0
- data/features/subject/explicit_subject.feature +8 -13
- data/features/subject/implicit_receiver.feature +29 -0
- data/features/subject/implicit_subject.feature +6 -7
- data/lib/rspec/core.rb +3 -21
- data/lib/rspec/core/backward_compatibility.rb +22 -3
- data/lib/rspec/core/command_line.rb +1 -0
- data/lib/rspec/core/configuration.rb +34 -6
- data/lib/rspec/core/configuration_options.rb +1 -3
- data/lib/rspec/core/example.rb +0 -5
- data/lib/rspec/core/example_group.rb +9 -8
- data/lib/rspec/core/expecting/with_rspec.rb +11 -0
- data/lib/rspec/core/extensions/object.rb +1 -1
- data/lib/rspec/core/formatters/base_formatter.rb +1 -6
- data/lib/rspec/core/hooks.rb +1 -1
- data/lib/rspec/core/metadata.rb +15 -5
- data/lib/rspec/core/option_parser.rb +17 -0
- data/lib/rspec/core/pending.rb +10 -1
- data/lib/rspec/core/rake_task.rb +32 -10
- data/lib/rspec/core/reporter.rb +1 -0
- data/lib/rspec/core/subject.rb +58 -59
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +9 -4
- data/rspec-core.gemspec +4 -11
- data/spec/rspec/core/command_line_spec.rb +16 -5
- data/spec/rspec/core/configuration_options_spec.rb +6 -0
- data/spec/rspec/core/configuration_spec.rb +89 -6
- data/spec/rspec/core/deprecations_spec.rb +17 -1
- data/spec/rspec/core/example_group_spec.rb +29 -14
- data/spec/rspec/core/example_spec.rb +0 -7
- data/spec/rspec/core/formatters/html_formatted-1.8.6.html +49 -33
- data/spec/rspec/core/formatters/html_formatted-1.8.7.html +5 -5
- data/spec/rspec/core/formatters/html_formatted-1.9.1.html +46 -26
- data/spec/rspec/core/formatters/html_formatted-1.9.2.html +5 -5
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +49 -33
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +19 -19
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +56 -33
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +26 -38
- data/spec/rspec/core/metadata_spec.rb +153 -132
- data/spec/rspec/core/pending_example_spec.rb +133 -25
- data/spec/rspec/core/rake_task_spec.rb +25 -32
- data/spec/rspec/core/subject_spec.rb +15 -0
- data/spec/rspec/core/world_spec.rb +72 -61
- data/spec/spec_helper.rb +0 -14
- metadata +25 -135
- data/features/hooks/halt.feature +0 -26
data/lib/rspec/core/example.rb
CHANGED
@@ -4,14 +4,15 @@ module RSpec
|
|
4
4
|
extend Extensions::ModuleEvalWithArgs
|
5
5
|
include Extensions::InstanceEvalWithArgs
|
6
6
|
extend Hooks
|
7
|
-
|
7
|
+
extend Subject::ClassMethods
|
8
|
+
include Subject::InstanceMethods
|
8
9
|
include Let
|
9
10
|
include Pending
|
10
11
|
|
11
12
|
attr_accessor :example
|
12
13
|
|
13
14
|
def running_example
|
14
|
-
RSpec.deprecate(
|
15
|
+
RSpec.deprecate("running_example", "example")
|
15
16
|
example
|
16
17
|
end
|
17
18
|
|
@@ -19,9 +20,9 @@ module RSpec
|
|
19
20
|
RSpec.world
|
20
21
|
end
|
21
22
|
|
22
|
-
def self.
|
23
|
+
def self.register
|
23
24
|
RSpec::Core::Runner.autorun
|
24
|
-
world.
|
25
|
+
world.register(self)
|
25
26
|
end
|
26
27
|
|
27
28
|
class << self
|
@@ -68,8 +69,8 @@ module RSpec
|
|
68
69
|
raise "Could not find shared example group named \#{name.inspect}" unless shared_block
|
69
70
|
|
70
71
|
group = describe("#{report_label || "it should behave like"} \#{name}") do
|
71
|
-
module_eval_with_args
|
72
|
-
module_eval
|
72
|
+
module_eval_with_args(*args, &shared_block)
|
73
|
+
module_eval(&customization_block) if customization_block
|
73
74
|
end
|
74
75
|
group.metadata[:shared_group_name] = name
|
75
76
|
group
|
@@ -267,8 +268,8 @@ An error occurred in an after(:all) hook.
|
|
267
268
|
end.all?
|
268
269
|
end
|
269
270
|
|
270
|
-
def self.
|
271
|
-
metadata.
|
271
|
+
def self.apply?(predicate, filters)
|
272
|
+
metadata.apply?(predicate, filters)
|
272
273
|
end
|
273
274
|
|
274
275
|
def self.declaration_line_numbers
|
@@ -3,7 +3,7 @@ module RSpec
|
|
3
3
|
module ObjectExtensions
|
4
4
|
def describe(*args, &example_group_block)
|
5
5
|
args << {} unless args.last.is_a?(Hash)
|
6
|
-
RSpec::Core::ExampleGroup.describe(*args, &example_group_block)
|
6
|
+
RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -12,7 +12,7 @@ module RSpec
|
|
12
12
|
attr_reader :failed_examples, :pending_examples
|
13
13
|
|
14
14
|
def initialize(output)
|
15
|
-
@output = output
|
15
|
+
@output = output || StringIO.new
|
16
16
|
@example_count = @pending_count = @failure_count = 0
|
17
17
|
@examples = []
|
18
18
|
@failed_examples = []
|
@@ -45,11 +45,6 @@ module RSpec
|
|
45
45
|
def example_group_finished(example_group)
|
46
46
|
end
|
47
47
|
|
48
|
-
def add_example_group(example_group)
|
49
|
-
RSpec.deprecate("add_example_group", "example_group_started")
|
50
|
-
example_group_started(example_group)
|
51
|
-
end
|
52
|
-
|
53
48
|
def example_started(example)
|
54
49
|
examples << example
|
55
50
|
end
|
data/lib/rspec/core/hooks.rb
CHANGED
data/lib/rspec/core/metadata.rb
CHANGED
@@ -32,7 +32,7 @@ module RSpec
|
|
32
32
|
self[:example_group][:full_description] = full_description_from(*args)
|
33
33
|
|
34
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(caller)
|
35
|
+
self[:example_group][:file_path], self[:example_group][:line_number] = file_and_line_number_from(user_metadata.delete(:caller) || caller)
|
36
36
|
self[:example_group][:location] = location_from(self[:example_group])
|
37
37
|
|
38
38
|
update(user_metadata)
|
@@ -68,13 +68,13 @@ EOM
|
|
68
68
|
store(:description, description.to_s)
|
69
69
|
store(:full_description, "#{self[:example_group][:full_description]} #{self[:description]}")
|
70
70
|
store(:execution_result, {})
|
71
|
-
self[:file_path], self[:line_number] = file_and_line_number_from(caller)
|
71
|
+
self[:file_path], self[:line_number] = file_and_line_number_from(options.delete(:caller) || caller)
|
72
72
|
self[:location] = location_from(self)
|
73
73
|
update(options)
|
74
74
|
end
|
75
75
|
|
76
|
-
def
|
77
|
-
filters.
|
76
|
+
def apply?(predicate, filters)
|
77
|
+
filters.send(predicate) do |key, value|
|
78
78
|
apply_condition(key, value)
|
79
79
|
end
|
80
80
|
end
|
@@ -96,7 +96,17 @@ EOM
|
|
96
96
|
when Regexp
|
97
97
|
metadata[key] =~ value
|
98
98
|
when Proc
|
99
|
-
value.
|
99
|
+
if value.arity == 2
|
100
|
+
# Pass the metadata hash to allow the proc to check if it even has the key.
|
101
|
+
# This is necessary for the implicit :if exclusion filter:
|
102
|
+
# { } # => run the example
|
103
|
+
# { :if => nil } # => exclude the example
|
104
|
+
# The value of metadata[:if] is the same in these two cases but
|
105
|
+
# they need to be treated differently.
|
106
|
+
value.call(metadata[key], metadata) rescue false
|
107
|
+
else
|
108
|
+
value.call(metadata[key]) rescue false
|
109
|
+
end
|
100
110
|
when Fixnum
|
101
111
|
if key == :line_number
|
102
112
|
relevant_line_numbers(metadata).include?(world.preceding_declaration_line(value))
|
@@ -99,6 +99,23 @@ module RSpec::Core
|
|
99
99
|
parser.on('--autotest') do |o|
|
100
100
|
options[:autotest] = true
|
101
101
|
end
|
102
|
+
|
103
|
+
parser.on('--fail-fast', 'Use the fail_fast option to tell RSpec to abort the run on first failure.') do |o|
|
104
|
+
options[:fail_fast] = true
|
105
|
+
end
|
106
|
+
|
107
|
+
parser.on('-t', '--tag TAG[:VALUE]', 'Run examples with the specified tag',
|
108
|
+
'To exclude examples, add ~ before the tag (e.g. ~slow)',
|
109
|
+
'(TAG is always converted to a symbol)') do |tag|
|
110
|
+
filter_type = tag =~ /^~/ ? :exclusion_filter : :filter
|
111
|
+
|
112
|
+
name,value = tag.gsub(/^(~@|~|@)/, '').split(':')
|
113
|
+
name = name.to_sym
|
114
|
+
value = true if value.nil?
|
115
|
+
|
116
|
+
options[filter_type] ||= {}
|
117
|
+
options[filter_type][name] = value
|
118
|
+
end
|
102
119
|
end
|
103
120
|
end
|
104
121
|
end
|
data/lib/rspec/core/pending.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module RSpec
|
2
2
|
module Core
|
3
3
|
module Pending
|
4
|
-
|
4
|
+
DEFAULT_MESSAGE = 'No reason given'
|
5
|
+
|
6
|
+
def pending(*args)
|
7
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
8
|
+
message = args.first || DEFAULT_MESSAGE
|
9
|
+
|
10
|
+
if options[:unless] || (options.has_key?(:if) && !options[:if])
|
11
|
+
return block_given? ? yield : nil
|
12
|
+
end
|
13
|
+
|
5
14
|
example.metadata[:pending] = true
|
6
15
|
example.metadata[:execution_result][:pending_message] = message
|
7
16
|
if block_given?
|
data/lib/rspec/core/rake_task.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
require 'rspec/core'
|
3
4
|
require 'rspec/core/deprecation'
|
4
5
|
require 'rake'
|
5
6
|
require 'rake/tasklib'
|
@@ -20,7 +21,22 @@ module RSpec
|
|
20
21
|
# 'spec/**/*_spec.rb'
|
21
22
|
attr_accessor :pattern
|
22
23
|
|
24
|
+
# By default, if there is a Gemfile, the generated command will include
|
25
|
+
# 'bundle exec'. Set this to true to ignore the presence of a Gemfile, and
|
26
|
+
# not add 'bundle exec' to the command.
|
27
|
+
#
|
28
|
+
# default:
|
29
|
+
# false
|
30
|
+
attr_accessor :skip_bundler
|
31
|
+
|
32
|
+
# Name of Gemfile to use
|
33
|
+
#
|
34
|
+
# default:
|
35
|
+
# Gemfile
|
36
|
+
attr_accessor :gemfile
|
37
|
+
|
23
38
|
# Deprecated. Use ruby_opts="-w" instead.
|
39
|
+
#
|
24
40
|
# When true, requests that the specs be run with the warning flag set.
|
25
41
|
# e.g. "ruby -w"
|
26
42
|
#
|
@@ -29,7 +45,7 @@ module RSpec
|
|
29
45
|
attr_reader :warning
|
30
46
|
|
31
47
|
def warning=(true_or_false)
|
32
|
-
RSpec.deprecate("warning", 'ruby_opts="-w"')
|
48
|
+
RSpec.deprecate("RSpec::Core::RakeTask#warning=", 'ruby_opts="-w"')
|
33
49
|
@warning = true_or_false
|
34
50
|
end
|
35
51
|
|
@@ -57,7 +73,7 @@ module RSpec
|
|
57
73
|
|
58
74
|
# Path to rcov.
|
59
75
|
#
|
60
|
-
#
|
76
|
+
# default:
|
61
77
|
# 'rcov'
|
62
78
|
attr_accessor :rcov_path
|
63
79
|
|
@@ -86,16 +102,22 @@ module RSpec
|
|
86
102
|
attr_accessor :rspec_opts
|
87
103
|
|
88
104
|
# Deprecated. Use rspec_opts instead.
|
105
|
+
#
|
106
|
+
# Command line options to pass to rspec.
|
107
|
+
#
|
108
|
+
# default:
|
109
|
+
# nil
|
89
110
|
def spec_opts=(opts)
|
90
|
-
RSpec.deprecate(
|
111
|
+
RSpec.deprecate('RSpec::Core::RakeTask#spec_opts=', 'rspec_opts=')
|
91
112
|
@rspec_opts = opts
|
92
113
|
end
|
93
114
|
|
94
115
|
def initialize(*args)
|
95
116
|
@name = args.shift || :spec
|
96
117
|
@pattern, @rcov_path, @rcov_opts, @ruby_opts, @rspec_opts = nil, nil, nil, nil, nil
|
97
|
-
@warning, @rcov = false, false
|
118
|
+
@warning, @rcov, @skip_bundler = false, false, false
|
98
119
|
@verbose, @fail_on_error = true, true
|
120
|
+
@gemfile = 'Gemfile'
|
99
121
|
|
100
122
|
yield self if block_given?
|
101
123
|
|
@@ -136,10 +158,10 @@ module RSpec
|
|
136
158
|
cmd_parts = [ruby_opts]
|
137
159
|
cmd_parts << "-w" if warning?
|
138
160
|
cmd_parts << "-S"
|
139
|
-
cmd_parts << "bundle exec" if
|
161
|
+
cmd_parts << "bundle exec" if gemfile? unless skip_bundler
|
140
162
|
cmd_parts << runner
|
141
163
|
if rcov
|
142
|
-
cmd_parts << ["-Ispec", rcov_opts]
|
164
|
+
cmd_parts << ["-Ispec", "-Ilib", rcov_opts]
|
143
165
|
else
|
144
166
|
cmd_parts << rspec_opts
|
145
167
|
end
|
@@ -157,10 +179,6 @@ module RSpec
|
|
157
179
|
rcov ? rcov_path : rspec_path
|
158
180
|
end
|
159
181
|
|
160
|
-
def bundler?
|
161
|
-
File.exist?("./Gemfile")
|
162
|
-
end
|
163
|
-
|
164
182
|
def warning?
|
165
183
|
warning
|
166
184
|
end
|
@@ -169,6 +187,10 @@ module RSpec
|
|
169
187
|
lambda {|s| s == ""}
|
170
188
|
end
|
171
189
|
|
190
|
+
def gemfile?
|
191
|
+
File.exist?(gemfile)
|
192
|
+
end
|
193
|
+
|
172
194
|
end
|
173
195
|
end
|
174
196
|
end
|
data/lib/rspec/core/reporter.rb
CHANGED
data/lib/rspec/core/subject.rb
CHANGED
@@ -1,69 +1,68 @@
|
|
1
|
-
require 'ostruct'
|
2
|
-
|
3
1
|
module RSpec
|
4
2
|
module Core
|
5
3
|
module Subject
|
4
|
+
module InstanceMethods
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
# Returns the subject defined by the example group. The subject block is
|
7
|
+
# only executed once per example, the result of which is cached and
|
8
|
+
# returned by any subsequent calls to +subject+.
|
9
|
+
#
|
10
|
+
# If a class is passed to +describe+ and no subject is explicitly
|
11
|
+
# declared in the example group, then +subject+ will return a new
|
12
|
+
# instance of that class.
|
13
|
+
#
|
14
|
+
# == Examples
|
15
|
+
#
|
16
|
+
# # explicit subject defined by the subject method
|
17
|
+
# describe Person do
|
18
|
+
# subject { Person.new(:birthdate => 19.years.ago) }
|
19
|
+
# it "should be eligible to vote" do
|
20
|
+
# subject.should be_eligible_to_vote
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # implicit subject => { Person.new }
|
25
|
+
# describe Person do
|
26
|
+
# it "should be eligible to vote" do
|
27
|
+
# subject.should be_eligible_to_vote
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
def subject
|
31
|
+
@original_subject ||= instance_eval(&self.class.subject)
|
12
32
|
end
|
13
|
-
end
|
14
33
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# If a class is passed to +describe+ and no subject is explicitly
|
20
|
-
# declared in the example group, then +subject+ will return a new
|
21
|
-
# instance of that class.
|
22
|
-
#
|
23
|
-
# == Examples
|
24
|
-
#
|
25
|
-
# # explicit subject defined by the subject method
|
26
|
-
# describe Person do
|
27
|
-
# subject { Person.new(:birthdate => 19.years.ago) }
|
28
|
-
# it "should be eligible to vote" do
|
29
|
-
# subject.should be_eligible_to_vote
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
|
-
# # implicit subject => { Person.new }
|
34
|
-
# describe Person do
|
35
|
-
# it "should be eligible to vote" do
|
36
|
-
# subject.should be_eligible_to_vote
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
def subject
|
40
|
-
@original_subject ||= instance_eval(&self.class.subject)
|
41
|
-
end
|
34
|
+
begin
|
35
|
+
require 'rspec/expectations/extensions/kernel'
|
36
|
+
alias_method :__should_for_example_group__, :should
|
37
|
+
alias_method :__should_not_for_example_group__, :should_not
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
39
|
+
# When +should+ is called with no explicit receiver, the call is
|
40
|
+
# delegated to the object returned by +subject+. Combined with
|
41
|
+
# an implicit subject (see +subject+), this supports very concise
|
42
|
+
# expressions.
|
43
|
+
#
|
44
|
+
# == Examples
|
45
|
+
#
|
46
|
+
# describe Person do
|
47
|
+
# it { should be_eligible_to_vote }
|
48
|
+
# end
|
49
|
+
def should(matcher=nil, message=nil)
|
50
|
+
self == subject ? self.__should_for_example_group__(matcher) : subject.should(matcher,message)
|
51
|
+
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
53
|
+
# Just like +should+, +should_not+ delegates to the subject (implicit or
|
54
|
+
# explicit) of the example group.
|
55
|
+
#
|
56
|
+
# == Examples
|
57
|
+
#
|
58
|
+
# describe Person do
|
59
|
+
# it { should_not be_eligible_to_vote }
|
60
|
+
# end
|
61
|
+
def should_not(matcher=nil, message=nil)
|
62
|
+
self == subject ? self.__should_not_for_example_group__(matcher) : subject.should_not(matcher,message)
|
63
|
+
end
|
64
|
+
rescue LoadError
|
65
|
+
end
|
67
66
|
end
|
68
67
|
|
69
68
|
module ClassMethods
|
@@ -150,7 +149,7 @@ module RSpec
|
|
150
149
|
|
151
150
|
attr_reader :explicit_subject_block # :nodoc:
|
152
151
|
|
153
|
-
|
152
|
+
private
|
154
153
|
|
155
154
|
def explicit_subject
|
156
155
|
group = self
|