rspec-core 2.3.1 → 2.4.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/History.markdown +22 -0
- data/Rakefile +2 -2
- data/features/command_line/README.md +6 -0
- data/features/command_line/configure.feature +16 -14
- data/features/command_line/example_name_option.feature +3 -3
- data/features/command_line/format_option.feature +73 -0
- data/features/command_line/line_number_appended_to_path.feature +1 -1
- data/features/command_line/line_number_option.feature +2 -2
- data/features/command_line/tag.feature +7 -7
- data/features/configuration/read_options_from_file.feature +29 -16
- data/features/hooks/before_and_after_hooks.feature +9 -14
- data/features/hooks/filtering.feature +174 -0
- data/features/step_definitions/additional_cli_steps.rb +4 -0
- data/features/subject/attribute_of_subject.feature +68 -18
- data/lib/rspec/core/command_line_configuration.rb +16 -16
- data/lib/rspec/core/configuration.rb +14 -15
- data/lib/rspec/core/configuration_options.rb +46 -22
- data/lib/rspec/core/example.rb +16 -6
- data/lib/rspec/core/example_group.rb +11 -11
- data/lib/rspec/core/formatters/base_text_formatter.rb +2 -1
- data/lib/rspec/core/hooks.rb +8 -8
- data/lib/rspec/core/option_parser.rb +13 -3
- data/lib/rspec/core/pending.rb +2 -0
- data/lib/rspec/core/rake_task.rb +1 -1
- data/lib/rspec/core/subject.rb +2 -0
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +2 -2
- data/spec/rspec/core/configuration_options_spec.rb +147 -151
- data/spec/rspec/core/configuration_spec.rb +67 -19
- data/spec/rspec/core/example_spec.rb +12 -10
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +25 -1
- data/spec/rspec/core/formatters/html_formatted-1.8.6.html +5 -5
- data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +37 -24
- data/spec/rspec/core/formatters/html_formatted-1.8.7.html +5 -5
- data/spec/rspec/core/formatters/html_formatted-1.9.1.html +5 -5
- data/spec/rspec/core/formatters/html_formatted-1.9.2.html +5 -5
- data/spec/rspec/core/formatters/html_formatter_spec.rb +7 -7
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +19 -19
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +51 -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 +26 -26
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +26 -26
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +7 -7
- data/spec/rspec/core/hooks_filtering_spec.rb +54 -0
- data/spec/rspec/core/option_parser_spec.rb +53 -17
- data/spec/rspec/core/rake_task_spec.rb +21 -0
- data/spec/spec_helper.rb +1 -1
- metadata +14 -8
@@ -14,3 +14,7 @@ Then /^the example(s)? should( all)? pass$/ do |*|
|
|
14
14
|
Then %q{the output should contain "0 failures"}
|
15
15
|
Then %q{the exit status should be 0}
|
16
16
|
end
|
17
|
+
|
18
|
+
Then /^the file "([^"]*)" should contain:$/ do |file, partial_content|
|
19
|
+
check_file_content(file, partial_content, true)
|
20
|
+
end
|
@@ -1,29 +1,43 @@
|
|
1
1
|
Feature: attribute of subject
|
2
2
|
|
3
3
|
Use the its() method as a short-hand to generate a nested example group with
|
4
|
-
a single example that specifies the expected value of an attribute of the
|
5
|
-
This can be used with an implicit or explicit subject.
|
4
|
+
a single example that specifies the expected value of an attribute of the
|
5
|
+
subject. This can be used with an implicit or explicit subject.
|
6
6
|
|
7
|
-
its() accepts a symbol or a string, and a block representing the example.
|
8
|
-
a string with dots to specify a nested attribute (i.e. an attribute of the
|
9
|
-
attribute of the subject).
|
7
|
+
its() accepts a symbol or a string, and a block representing the example.
|
10
8
|
|
11
|
-
|
9
|
+
its(:size) { should eq(1) }
|
10
|
+
its("length") { should eq(1) }
|
11
|
+
|
12
|
+
You can use a string with dots to specify a nested attribute (i.e. an
|
13
|
+
attribute of the attribute of the subject).
|
14
|
+
|
15
|
+
its("phone_numbers.size") { should eq(2) }
|
16
|
+
|
17
|
+
When the subject is a hash, you can pass in an array with a single key to
|
18
|
+
access the value at that key in the hash.
|
19
|
+
|
20
|
+
its([:key]) { should eq(value) }
|
21
|
+
|
22
|
+
Scenario: specify value of an attribute
|
12
23
|
Given a file named "example_spec.rb" with:
|
13
24
|
"""
|
14
25
|
describe Array do
|
15
|
-
|
26
|
+
context "when first created" do
|
27
|
+
its(:size) { should eq(0) }
|
28
|
+
end
|
16
29
|
end
|
17
30
|
"""
|
18
31
|
When I run "rspec example_spec.rb --format documentation"
|
19
32
|
Then the output should contain:
|
20
33
|
"""
|
21
34
|
Array
|
22
|
-
|
23
|
-
|
35
|
+
when first created
|
36
|
+
size
|
37
|
+
should == 0
|
24
38
|
"""
|
25
39
|
|
26
|
-
Scenario: nested attribute
|
40
|
+
Scenario: specify value of a nested attribute
|
27
41
|
Given a file named "example_spec.rb" with:
|
28
42
|
"""
|
29
43
|
class Person
|
@@ -34,19 +48,55 @@ Feature: attribute of subject
|
|
34
48
|
end
|
35
49
|
|
36
50
|
describe Person do
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
51
|
+
context "with one phone number (555-1212)"do
|
52
|
+
subject do
|
53
|
+
person = Person.new
|
54
|
+
person.phone_numbers << "555-1212"
|
55
|
+
person
|
56
|
+
end
|
42
57
|
|
43
|
-
|
58
|
+
its("phone_numbers.first") { should eq("555-1212") }
|
59
|
+
end
|
44
60
|
end
|
45
61
|
"""
|
46
62
|
When I run "rspec example_spec.rb --format documentation"
|
47
63
|
Then the output should contain:
|
48
64
|
"""
|
49
65
|
Person
|
50
|
-
|
51
|
-
|
66
|
+
with one phone number (555-1212)
|
67
|
+
phone_numbers.first
|
68
|
+
should == 555-1212
|
69
|
+
"""
|
70
|
+
|
71
|
+
Scenario: specify value of an attribute of a hash
|
72
|
+
Given a file named "example_spec.rb" with:
|
73
|
+
"""
|
74
|
+
describe Hash do
|
75
|
+
context "with two items" do
|
76
|
+
subject do
|
77
|
+
{:one => 'one', :two => 'two'}
|
78
|
+
end
|
79
|
+
|
80
|
+
its(:size) { should eq(2) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
"""
|
84
|
+
When I run "rspec example_spec.rb"
|
85
|
+
Then the output should contain "1 example, 0 failures"
|
86
|
+
|
87
|
+
Scenario: specify value for key in a hash
|
88
|
+
Given a file named "example_spec.rb" with:
|
89
|
+
"""
|
90
|
+
describe Hash do
|
91
|
+
context "with keys :one and 'two'" do
|
92
|
+
subject do
|
93
|
+
{:one => 1, "two" => 2}
|
94
|
+
end
|
95
|
+
|
96
|
+
its([:one]) { should eq(1) }
|
97
|
+
its(["two"]) { should eq(2) }
|
98
|
+
end
|
99
|
+
end
|
52
100
|
"""
|
101
|
+
When I run "rspec example_spec.rb"
|
102
|
+
Then the output should contain "2 examples, 0 failures"
|
@@ -16,7 +16,7 @@ module RSpec
|
|
16
16
|
"#{@command}" is not valid a valid argument to "rspec --configure".
|
17
17
|
Supported options are:
|
18
18
|
|
19
|
-
rspec --configure autotest # generates
|
19
|
+
rspec --configure autotest # generates .rspec file
|
20
20
|
|
21
21
|
#{"*"*50}
|
22
22
|
MESSAGE
|
@@ -26,26 +26,26 @@ MESSAGE
|
|
26
26
|
class Autotest
|
27
27
|
class << self
|
28
28
|
def generate
|
29
|
-
|
30
|
-
|
31
|
-
puts "autotest/discover.rb has been added"
|
29
|
+
create_dot_rspec_file
|
30
|
+
remove_autotest_dir_if_present
|
32
31
|
end
|
33
32
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
file << 'Autotest.add_discovery { "rspec2" }'
|
33
|
+
def create_dot_rspec_file
|
34
|
+
puts "Autotest loads RSpec's Autotest subclass when there is a .rspec file in the project's root directory."
|
35
|
+
if File.exist?('./.rspec')
|
36
|
+
puts ".rspec file already exists, so nothing was changed."
|
37
|
+
else
|
38
|
+
FileUtils.touch('./.rspec')
|
39
|
+
puts ".rspec file did not exist, so it was created."
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
def remove_autotest_dir_if_present
|
44
|
+
if discover_file_exists?
|
45
|
+
print "Delete obsolete autotest/discover.rb [y/n]? "
|
46
|
+
exit if gets !~ /y/i
|
47
|
+
FileUtils.rm_rf(discover_file_path)
|
48
|
+
end
|
49
49
|
end
|
50
50
|
|
51
51
|
def discover_file_exists?
|
@@ -24,7 +24,7 @@ module RSpec
|
|
24
24
|
add_setting :drb
|
25
25
|
add_setting :drb_port
|
26
26
|
add_setting :profile_examples
|
27
|
-
add_setting :fail_fast
|
27
|
+
add_setting :fail_fast
|
28
28
|
add_setting :run_all_when_everything_filtered
|
29
29
|
add_setting :filter
|
30
30
|
add_setting :exclusion_filter
|
@@ -240,6 +240,7 @@ module RSpec
|
|
240
240
|
return unless bool
|
241
241
|
begin
|
242
242
|
require 'ruby-debug'
|
243
|
+
Debugger.start
|
243
244
|
rescue LoadError
|
244
245
|
raise <<-EOM
|
245
246
|
|
@@ -262,28 +263,26 @@ EOM
|
|
262
263
|
filter_run({ :full_description => /#{description}/ }, true)
|
263
264
|
end
|
264
265
|
|
265
|
-
|
266
|
-
|
267
|
-
def formatter_class
|
268
|
-
@formatter_class ||= begin
|
269
|
-
require 'rspec/core/formatters/progress_formatter'
|
270
|
-
RSpec::Core::Formatters::ProgressFormatter
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
def formatter=(formatter_to_use)
|
275
|
-
self.formatter_class =
|
266
|
+
def add_formatter(formatter_to_use, output=nil)
|
267
|
+
formatter_class =
|
276
268
|
built_in_formatter(formatter_to_use) ||
|
277
269
|
custom_formatter(formatter_to_use) ||
|
278
270
|
(raise ArgumentError, "Formatter '#{formatter_to_use}' unknown - maybe you meant 'documentation' or 'progress'?.")
|
271
|
+
|
272
|
+
formatters << formatter_class.new(output ? File.new(output, 'w') : self.output)
|
279
273
|
end
|
280
274
|
|
281
|
-
|
282
|
-
|
275
|
+
alias_method :formatter=, :add_formatter
|
276
|
+
|
277
|
+
def formatters
|
278
|
+
@formatters ||= []
|
283
279
|
end
|
284
280
|
|
285
281
|
def reporter
|
286
|
-
@reporter ||=
|
282
|
+
@reporter ||= begin
|
283
|
+
add_formatter('progress') if formatters.empty?
|
284
|
+
Reporter.new(*formatters)
|
285
|
+
end
|
287
286
|
end
|
288
287
|
|
289
288
|
def files_or_directories_to_run=(*files)
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'optparse'
|
2
1
|
# http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
|
2
|
+
require 'optparse'
|
3
3
|
|
4
4
|
module RSpec
|
5
5
|
module Core
|
@@ -18,8 +18,14 @@ module RSpec
|
|
18
18
|
keys = options.keys
|
19
19
|
keys.unshift(:requires) if keys.delete(:requires)
|
20
20
|
keys.unshift(:libs) if keys.delete(:libs)
|
21
|
+
formatters = options[:formatters] if keys.delete(:formatters)
|
21
22
|
keys.each do |key|
|
22
|
-
config.send("#{key}=", options[key])
|
23
|
+
config.send("#{key}=", options[key]) if config.respond_to?("#{key}=")
|
24
|
+
end
|
25
|
+
if formatters
|
26
|
+
formatters.each do |pair|
|
27
|
+
config.add_formatter(*pair)
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
|
@@ -30,9 +36,17 @@ module RSpec
|
|
30
36
|
argv << "--backtrace" if options[:full_backtrace]
|
31
37
|
argv << "--tty" if options[:tty]
|
32
38
|
argv << "--fail-fast" if options[:fail_fast]
|
33
|
-
argv << "--format" << options[:formatter] if options[:formatter]
|
34
39
|
argv << "--line_number" << options[:line_number] if options[:line_number]
|
40
|
+
argv << "--options" << options[:custom_options_file] if options[:custom_options_file]
|
35
41
|
argv << "--example" << options[:full_description].source if options[:full_description]
|
42
|
+
if options[:formatters]
|
43
|
+
options[:formatters].each do |pair|
|
44
|
+
argv << "--format" << pair.shift
|
45
|
+
unless pair.empty?
|
46
|
+
argv << "--out" << pair.shift
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
36
50
|
(options[:libs] || []).each do |path|
|
37
51
|
argv << "-I" << path
|
38
52
|
end
|
@@ -44,12 +58,17 @@ module RSpec
|
|
44
58
|
|
45
59
|
def parse_options
|
46
60
|
@options = begin
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
61
|
+
options_to_merge = []
|
62
|
+
if custom_options_file
|
63
|
+
options_to_merge << custom_options
|
64
|
+
else
|
65
|
+
options_to_merge << global_options
|
66
|
+
options_to_merge << local_options
|
67
|
+
end
|
68
|
+
options_to_merge << env_options
|
69
|
+
options_to_merge << command_line_options
|
51
70
|
|
52
|
-
|
71
|
+
options_to_merge.inject do |merged, options|
|
53
72
|
merged.merge(options)
|
54
73
|
end
|
55
74
|
end
|
@@ -57,28 +76,34 @@ module RSpec
|
|
57
76
|
|
58
77
|
private
|
59
78
|
|
60
|
-
def
|
79
|
+
def env_options
|
61
80
|
ENV["SPEC_OPTS"] ? Parser.parse!(ENV["SPEC_OPTS"].split) : {}
|
62
81
|
end
|
63
82
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
83
|
+
def command_line_options
|
84
|
+
@command_line_options ||= begin
|
85
|
+
options = Parser.parse!(@args)
|
86
|
+
options[:files_or_directories_to_run] = @args
|
87
|
+
options
|
88
|
+
end
|
68
89
|
end
|
69
90
|
|
70
|
-
def
|
71
|
-
|
91
|
+
def custom_options
|
92
|
+
options_from(custom_options_file)
|
72
93
|
end
|
73
94
|
|
74
|
-
def
|
75
|
-
|
95
|
+
def local_options
|
96
|
+
@local_options ||= options_from(LOCAL_OPTIONS_FILE)
|
76
97
|
end
|
77
98
|
|
78
|
-
def
|
99
|
+
def global_options
|
100
|
+
@global_options ||= options_from(GLOBAL_OPTIONS_FILE)
|
101
|
+
end
|
102
|
+
|
103
|
+
def options_from(path)
|
79
104
|
Parser.parse(args_from_options_file(path))
|
80
105
|
end
|
81
|
-
|
106
|
+
|
82
107
|
def args_from_options_file(path)
|
83
108
|
return [] unless File.exist?(path)
|
84
109
|
config_string = options_file_as_erb_string(path)
|
@@ -90,9 +115,8 @@ module RSpec
|
|
90
115
|
ERB.new(IO.read(path)).result(binding)
|
91
116
|
end
|
92
117
|
|
93
|
-
def
|
94
|
-
|
95
|
-
LOCAL_OPTIONS_FILE
|
118
|
+
def custom_options_file
|
119
|
+
command_line_options[:custom_options_file]
|
96
120
|
end
|
97
121
|
end
|
98
122
|
end
|
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, :options
|
5
|
+
attr_reader :metadata, :options, :example_group_instance
|
6
6
|
|
7
7
|
def self.delegate_to_metadata(*keys)
|
8
8
|
keys.each do |key|
|
@@ -23,6 +23,15 @@ module RSpec
|
|
23
23
|
@example_group_class
|
24
24
|
end
|
25
25
|
|
26
|
+
def around_hooks
|
27
|
+
@around_hooks ||= example_group.around_hooks_for(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def apply?(predicate, filters)
|
31
|
+
@metadata.apply?(predicate, filters) ||
|
32
|
+
@example_group_class.apply?(predicate, filters)
|
33
|
+
end
|
34
|
+
|
26
35
|
alias_method :pending?, :pending
|
27
36
|
|
28
37
|
def run(example_group_instance, reporter)
|
@@ -69,8 +78,9 @@ module RSpec
|
|
69
78
|
class Procsy < Proc
|
70
79
|
attr_reader :metadata
|
71
80
|
alias_method :run, :call
|
72
|
-
def initialize(metadata)
|
81
|
+
def initialize(metadata, &block)
|
73
82
|
@metadata = metadata
|
83
|
+
super(&block)
|
74
84
|
end
|
75
85
|
end
|
76
86
|
|
@@ -84,10 +94,10 @@ module RSpec
|
|
84
94
|
end
|
85
95
|
|
86
96
|
def with_around_hooks
|
87
|
-
if
|
97
|
+
if around_hooks.empty?
|
88
98
|
yield
|
89
99
|
else
|
90
|
-
@example_group_class.eval_around_eachs(
|
100
|
+
@example_group_class.eval_around_eachs(self, Procsy.new(metadata)).call
|
91
101
|
end
|
92
102
|
end
|
93
103
|
|
@@ -123,11 +133,11 @@ module RSpec
|
|
123
133
|
|
124
134
|
def run_before_each
|
125
135
|
@example_group_instance.setup_mocks_for_rspec if @example_group_instance.respond_to?(:setup_mocks_for_rspec)
|
126
|
-
@example_group_class.eval_before_eachs(
|
136
|
+
@example_group_class.eval_before_eachs(self)
|
127
137
|
end
|
128
138
|
|
129
139
|
def run_after_each
|
130
|
-
@example_group_class.eval_after_eachs(
|
140
|
+
@example_group_class.eval_after_eachs(self)
|
131
141
|
@example_group_instance.verify_mocks_for_rspec if @example_group_instance.respond_to?(:verify_mocks_for_rspec)
|
132
142
|
ensure
|
133
143
|
@example_group_instance.teardown_mocks_for_rspec if @example_group_instance.respond_to?(:teardown_mocks_for_rspec)
|
@@ -177,22 +177,22 @@ module RSpec
|
|
177
177
|
store_before_all_ivars(example_group_instance)
|
178
178
|
end
|
179
179
|
|
180
|
-
def self.eval_around_eachs(
|
181
|
-
around_hooks.reverse.inject(initial_procsy) do |procsy, around_hook|
|
180
|
+
def self.eval_around_eachs(example, initial_procsy)
|
181
|
+
example.around_hooks.reverse.inject(initial_procsy) do |procsy, around_hook|
|
182
182
|
Example::Procsy.new(procsy.metadata) do
|
183
|
-
example_group_instance.instance_eval_with_args(procsy, &around_hook)
|
183
|
+
example.example_group_instance.instance_eval_with_args(procsy, &around_hook)
|
184
184
|
end
|
185
185
|
end
|
186
186
|
end
|
187
187
|
|
188
|
-
def self.eval_before_eachs(
|
189
|
-
world.run_hook_filtered(:before, :each, self, example_group_instance)
|
190
|
-
ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example_group_instance) }
|
188
|
+
def self.eval_before_eachs(example)
|
189
|
+
world.run_hook_filtered(:before, :each, self, example.example_group_instance, example)
|
190
|
+
ancestors.reverse.each { |ancestor| ancestor.run_hook(:before, :each, example.example_group_instance) }
|
191
191
|
end
|
192
192
|
|
193
|
-
def self.eval_after_eachs(
|
194
|
-
ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example_group_instance) }
|
195
|
-
world.run_hook_filtered(:after, :each, self, example_group_instance)
|
193
|
+
def self.eval_after_eachs(example)
|
194
|
+
ancestors.each { |ancestor| ancestor.run_hook(:after, :each, example.example_group_instance) }
|
195
|
+
world.run_hook_filtered(:after, :each, self, example.example_group_instance, example)
|
196
196
|
end
|
197
197
|
|
198
198
|
def self.eval_after_alls(example_group_instance)
|
@@ -215,8 +215,8 @@ An error occurred in an after(:all) hook.
|
|
215
215
|
world.run_hook_filtered(:after, :all, self, example_group_instance) if top_level?
|
216
216
|
end
|
217
217
|
|
218
|
-
def self.
|
219
|
-
|
218
|
+
def self.around_hooks_for(example)
|
219
|
+
world.find_hook(:around, :each, self, example) + ancestors.reverse.inject([]){|l,a| l + a.find_hook(:around, :each, self, example)}
|
220
220
|
end
|
221
221
|
|
222
222
|
def self.run(reporter)
|