rspec-core 2.6.0 → 2.7.0.rc1
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/README.md +1 -1
- data/features/Upgrade.md +11 -0
- data/features/command_line/exit_status.feature +20 -3
- data/features/command_line/format_option.feature +8 -0
- data/features/command_line/line_number_appended_to_path.feature +35 -1
- data/features/command_line/line_number_option.feature +16 -3
- data/features/command_line/pattern_option.feature +31 -0
- data/features/command_line/rake_task.feature +1 -1
- data/features/command_line/ruby.feature +22 -0
- data/features/configuration/default_path.feature +38 -0
- data/features/example_groups/{shared_example_group.feature → shared_examples.feature} +49 -26
- data/features/expectation_framework_integration/configure_expectation_framework.feature +1 -1
- data/features/filtering/inclusion_filters.feature +4 -5
- data/features/formatters/text_formatter.feature +16 -13
- data/features/helper_methods/let.feature +4 -4
- data/features/hooks/around_hooks.feature +1 -1
- data/features/hooks/before_and_after_hooks.feature +3 -3
- data/features/hooks/filtering.feature +13 -6
- data/features/metadata/user_defined.feature +12 -10
- data/features/pending/pending_examples.feature +21 -8
- data/features/step_definitions/additional_cli_steps.rb +1 -1
- data/features/subject/attribute_of_subject.feature +2 -2
- data/features/support/env.rb +1 -2
- data/lib/rspec/core/backward_compatibility.rb +1 -1
- data/lib/rspec/core/configuration.rb +71 -16
- data/lib/rspec/core/configuration_options.rb +46 -16
- data/lib/rspec/core/{extensions/object.rb → dsl.rb} +2 -4
- data/lib/rspec/core/example.rb +10 -7
- data/lib/rspec/core/example_group.rb +34 -18
- data/lib/rspec/core/expecting/with_rspec.rb +0 -2
- data/lib/rspec/core/extensions.rb +0 -1
- data/lib/rspec/core/formatters/base_formatter.rb +8 -4
- data/lib/rspec/core/formatters/base_text_formatter.rb +38 -18
- data/lib/rspec/core/formatters/html_formatter.rb +3 -1
- data/lib/rspec/core/formatters/snippet_extractor.rb +9 -3
- data/lib/rspec/core/formatters/text_mate_formatter.rb +20 -6
- data/lib/rspec/core/hooks.rb +7 -6
- data/lib/rspec/core/let.rb +5 -5
- data/lib/rspec/core/metadata.rb +136 -94
- data/lib/rspec/core/metadata_hash_builder.rb +1 -1
- data/lib/rspec/core/option_parser.rb +11 -7
- data/lib/rspec/core/pending.rb +2 -1
- data/lib/rspec/core/rake_task.rb +26 -15
- data/lib/rspec/core/reporter.rb +5 -6
- data/lib/rspec/core/runner.rb +1 -1
- data/lib/rspec/core/shared_example_group.rb +4 -4
- data/lib/rspec/core/subject.rb +7 -7
- data/lib/rspec/core/version.rb +1 -1
- data/lib/rspec/core/world.rb +9 -13
- data/lib/rspec/core.rb +14 -21
- data/spec/autotest/discover_spec.rb +2 -2
- data/spec/autotest/failed_results_re_spec.rb +29 -21
- data/spec/autotest/rspec_spec.rb +3 -3
- data/spec/rspec/core/command_line_spec.rb +1 -6
- data/spec/rspec/core/configuration_options_spec.rb +111 -27
- data/spec/rspec/core/configuration_spec.rb +161 -37
- data/spec/rspec/core/deprecations_spec.rb +2 -2
- data/spec/rspec/core/drb_command_line_spec.rb +6 -6
- data/spec/rspec/core/example_group_spec.rb +197 -61
- data/spec/rspec/core/example_spec.rb +33 -16
- data/spec/rspec/core/formatters/base_formatter_spec.rb +3 -3
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +222 -71
- data/spec/rspec/core/formatters/helpers_spec.rb +8 -8
- data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +90 -26
- data/spec/rspec/core/formatters/html_formatted-1.8.7.html +12 -11
- data/spec/rspec/core/formatters/html_formatted-1.9.2.html +12 -11
- data/spec/rspec/core/formatters/{html_formatted-1.9.1.html → html_formatted-1.9.3.html} +12 -11
- data/spec/rspec/core/formatters/html_formatter_spec.rb +5 -5
- data/spec/rspec/core/formatters/progress_formatter_spec.rb +2 -2
- data/spec/rspec/core/formatters/snippet_extractor_spec.rb +2 -2
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +91 -27
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7.html +13 -12
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.2.html +29 -28
- data/spec/rspec/core/formatters/{text_mate_formatted-1.9.1.html → text_mate_formatted-1.9.3.html} +29 -28
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +2 -2
- data/spec/rspec/core/hooks_filtering_spec.rb +18 -18
- data/spec/rspec/core/let_spec.rb +19 -6
- data/spec/rspec/core/metadata_spec.rb +146 -61
- data/spec/rspec/core/pending_example_spec.rb +4 -4
- data/spec/rspec/core/rake_task_spec.rb +71 -50
- data/spec/rspec/core/reporter_spec.rb +2 -2
- data/spec/rspec/core/ruby_project_spec.rb +2 -2
- data/spec/rspec/core/runner_spec.rb +4 -1
- data/spec/rspec/core/shared_example_group_spec.rb +15 -119
- data/spec/rspec/core/subject_spec.rb +13 -13
- data/spec/rspec/core/world_spec.rb +31 -22
- data/spec/rspec/core_spec.rb +1 -29
- data/spec/spec_helper.rb +51 -50
- data/spec/support/shared_example_groups.rb +3 -3
- data/spec/support/spec_files.rb +8 -8
- metadata +79 -94
- data/.document +0 -5
- data/.gitignore +0 -12
- data/.rspec +0 -0
- data/.travis.yml +0 -7
- data/Gemfile +0 -50
- data/Guardfile +0 -5
- data/License.txt +0 -23
- data/Rakefile +0 -89
- data/cucumber.yml +0 -2
- data/features/.nav +0 -57
- data/features/Changelog.md +0 -269
- data/rspec-core.gemspec +0 -24
- data/script/FullBuildRakeFile +0 -63
- data/script/console +0 -8
- data/script/cucumber +0 -1
- data/script/full_build +0 -1
- data/script/spec +0 -1
- data/spec/rspec/core/formatters/html_formatted-1.8.6.html +0 -398
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.6.html +0 -398
- data/spec.txt +0 -1126
- /data/{bin → exe}/autospec +0 -0
- /data/{bin → exe}/rspec +0 -0
|
@@ -39,6 +39,18 @@ module RSpec
|
|
|
39
39
|
dump_profile if profile_examples? && failure_count == 0
|
|
40
40
|
output.puts "\nFinished in #{format_seconds(duration)} seconds\n"
|
|
41
41
|
output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
|
|
42
|
+
dump_commands_to_rerun_failed_examples
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def dump_commands_to_rerun_failed_examples
|
|
46
|
+
return if failed_examples.empty?
|
|
47
|
+
output.puts
|
|
48
|
+
output.puts("Failed examples:")
|
|
49
|
+
output.puts
|
|
50
|
+
|
|
51
|
+
failed_examples.each do |example|
|
|
52
|
+
output.puts(red("rspec #{BaseFormatter::relative_path(example.location)}") + " " + cyan("# #{example.full_description}"))
|
|
53
|
+
end
|
|
42
54
|
end
|
|
43
55
|
|
|
44
56
|
def dump_profile
|
|
@@ -46,7 +58,7 @@ module RSpec
|
|
|
46
58
|
output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
|
|
47
59
|
sorted_examples.each do |example|
|
|
48
60
|
output.puts " #{example.full_description}"
|
|
49
|
-
output.puts
|
|
61
|
+
output.puts cyan(" #{red(format_seconds(example.execution_result[:run_time]))} #{red("seconds")} #{format_caller(example.location)}")
|
|
50
62
|
end
|
|
51
63
|
end
|
|
52
64
|
|
|
@@ -63,8 +75,13 @@ module RSpec
|
|
|
63
75
|
output.puts "Pending:"
|
|
64
76
|
pending_examples.each do |pending_example|
|
|
65
77
|
output.puts yellow(" #{pending_example.full_description}")
|
|
66
|
-
output.puts
|
|
67
|
-
output.puts
|
|
78
|
+
output.puts cyan(" # #{pending_example.execution_result[:pending_message]}")
|
|
79
|
+
output.puts cyan(" # #{format_caller(pending_example.location)}")
|
|
80
|
+
if pending_example.execution_result[:exception] \
|
|
81
|
+
&& RSpec.configuration.show_failures_in_pending_blocks?
|
|
82
|
+
dump_failure_info(pending_example)
|
|
83
|
+
dump_backtrace(pending_example)
|
|
84
|
+
end
|
|
68
85
|
end
|
|
69
86
|
end
|
|
70
87
|
end
|
|
@@ -83,20 +100,12 @@ module RSpec
|
|
|
83
100
|
color(text, "\e[1m")
|
|
84
101
|
end
|
|
85
102
|
|
|
86
|
-
def white(text)
|
|
87
|
-
color(text, "\e[37m")
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def green(text)
|
|
91
|
-
color(text, "\e[32m")
|
|
92
|
-
end
|
|
93
|
-
|
|
94
103
|
def red(text)
|
|
95
104
|
color(text, "\e[31m")
|
|
96
105
|
end
|
|
97
106
|
|
|
98
|
-
def
|
|
99
|
-
color(text, "\e[
|
|
107
|
+
def green(text)
|
|
108
|
+
color(text, "\e[32m")
|
|
100
109
|
end
|
|
101
110
|
|
|
102
111
|
def yellow(text)
|
|
@@ -107,8 +116,16 @@ module RSpec
|
|
|
107
116
|
color(text, "\e[34m")
|
|
108
117
|
end
|
|
109
118
|
|
|
110
|
-
def
|
|
111
|
-
color(text, "\e[
|
|
119
|
+
def magenta(text)
|
|
120
|
+
color(text, "\e[35m")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def cyan(text)
|
|
124
|
+
color(text, "\e[36m")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def white(text)
|
|
128
|
+
color(text, "\e[37m")
|
|
112
129
|
end
|
|
113
130
|
|
|
114
131
|
def short_padding
|
|
@@ -131,7 +148,7 @@ module RSpec
|
|
|
131
148
|
|
|
132
149
|
def dump_backtrace(example)
|
|
133
150
|
format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info|
|
|
134
|
-
output.puts
|
|
151
|
+
output.puts cyan("#{long_padding}# #{backtrace_info}")
|
|
135
152
|
end
|
|
136
153
|
end
|
|
137
154
|
|
|
@@ -144,8 +161,12 @@ module RSpec
|
|
|
144
161
|
end
|
|
145
162
|
|
|
146
163
|
def dump_failure(example, index)
|
|
147
|
-
exception = example.execution_result[:exception]
|
|
148
164
|
output.puts "#{short_padding}#{index.next}) #{example.full_description}"
|
|
165
|
+
dump_failure_info(example)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def dump_failure_info(example)
|
|
169
|
+
exception = example.execution_result[:exception]
|
|
149
170
|
output.puts "#{long_padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
|
|
150
171
|
output.puts "#{long_padding}#{red(exception.class.name << ":")}" unless exception.class.name =~ /RSpec/
|
|
151
172
|
exception.message.split("\n").each { |line| output.puts "#{long_padding} #{red(line)}" } if exception.message
|
|
@@ -158,7 +179,6 @@ module RSpec
|
|
|
158
179
|
end
|
|
159
180
|
end
|
|
160
181
|
end
|
|
161
|
-
|
|
162
182
|
end
|
|
163
183
|
end
|
|
164
184
|
end
|
|
@@ -108,8 +108,10 @@ module RSpec
|
|
|
108
108
|
#
|
|
109
109
|
def extra_failure_content(exception)
|
|
110
110
|
require 'rspec/core/formatters/snippet_extractor'
|
|
111
|
+
backtrace = exception.backtrace.map {|line| backtrace_line(line)}
|
|
112
|
+
backtrace.compact!
|
|
111
113
|
@snippet_extractor ||= SnippetExtractor.new
|
|
112
|
-
" <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(
|
|
114
|
+
" <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(backtrace)}</code></pre>"
|
|
113
115
|
end
|
|
114
116
|
|
|
115
117
|
def move_progress
|
|
@@ -4,10 +4,16 @@ module RSpec
|
|
|
4
4
|
# This class extracts code snippets by looking at the backtrace of the passed error
|
|
5
5
|
class SnippetExtractor #:nodoc:
|
|
6
6
|
class NullConverter; def convert(code, pre); code; end; end #:nodoc:
|
|
7
|
-
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
require 'syntax/convertors/html'
|
|
10
|
+
@@converter = Syntax::Convertors::HTML.for_syntax "ruby"
|
|
11
|
+
rescue LoadError => e
|
|
12
|
+
@@converter = NullConverter.new
|
|
13
|
+
end
|
|
8
14
|
|
|
9
|
-
def snippet(
|
|
10
|
-
raw_code, line = snippet_for(
|
|
15
|
+
def snippet(backtrace)
|
|
16
|
+
raw_code, line = snippet_for(backtrace[0])
|
|
11
17
|
highlighted = @@converter.convert(raw_code, false)
|
|
12
18
|
highlighted << "\n<span class=\"comment\"># gem install syntax to get syntax highlighting</span>" if @@converter.is_a?(NullConverter)
|
|
13
19
|
post_process(highlighted, line)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require 'cgi'
|
|
1
2
|
require 'rspec/core/formatters/html_formatter'
|
|
2
3
|
|
|
3
4
|
module RSpec
|
|
@@ -5,15 +6,28 @@ module RSpec
|
|
|
5
6
|
module Formatters
|
|
6
7
|
# Formats backtraces so they're clickable by TextMate
|
|
7
8
|
class TextMateFormatter < HtmlFormatter
|
|
8
|
-
def backtrace_line(line)
|
|
9
|
-
if
|
|
10
|
-
line
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
def backtrace_line(line, skip_textmate_conversion=false)
|
|
10
|
+
if skip_textmate_conversion
|
|
11
|
+
super(line)
|
|
12
|
+
else
|
|
13
|
+
format_backtrace_line_for_textmate(super(line))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
def format_backtrace_line_for_textmate(line)
|
|
18
|
+
return nil unless line
|
|
19
|
+
CGI.escapeHTML(line).sub(/([^:]*\.e?rb):(\d*)/) do
|
|
20
|
+
"<a href=\"txmt://open?url=file://#{File.expand_path($1)}&line=#{$2}\">#{$1}:#{$2}</a> "
|
|
15
21
|
end
|
|
16
22
|
end
|
|
23
|
+
|
|
24
|
+
def extra_failure_content(exception)
|
|
25
|
+
require 'rspec/core/formatters/snippet_extractor'
|
|
26
|
+
backtrace = exception.backtrace.map {|line| backtrace_line(line, :skip_textmate_conversion)}
|
|
27
|
+
backtrace.compact!
|
|
28
|
+
@snippet_extractor ||= SnippetExtractor.new
|
|
29
|
+
" <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(backtrace)}</code></pre>"
|
|
30
|
+
end
|
|
17
31
|
end
|
|
18
32
|
end
|
|
19
33
|
end
|
data/lib/rspec/core/hooks.rb
CHANGED
|
@@ -8,12 +8,12 @@ module RSpec
|
|
|
8
8
|
|
|
9
9
|
def initialize(options, &block)
|
|
10
10
|
@options = options
|
|
11
|
-
raise "no block given for #{
|
|
11
|
+
raise "no block given for #{display_name}" unless block
|
|
12
12
|
@block = block
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def options_apply?(example_or_group)
|
|
16
|
-
|
|
16
|
+
example_or_group.all_apply?(options)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def to_proc
|
|
@@ -23,10 +23,13 @@ module RSpec
|
|
|
23
23
|
def call
|
|
24
24
|
@block.call
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
def display_name
|
|
28
|
+
self.class.name.split('::').last.gsub('Hook','').downcase << " hook"
|
|
29
|
+
end
|
|
26
30
|
end
|
|
27
31
|
|
|
28
32
|
class BeforeHook < Hook
|
|
29
|
-
TYPE = 'before'
|
|
30
33
|
def run_in(example_group_instance)
|
|
31
34
|
if example_group_instance
|
|
32
35
|
example_group_instance.instance_eval(&self)
|
|
@@ -37,7 +40,6 @@ module RSpec
|
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
class AfterHook < Hook
|
|
40
|
-
TYPE = 'after'
|
|
41
43
|
def run_in(example_group_instance)
|
|
42
44
|
if example_group_instance
|
|
43
45
|
example_group_instance.instance_eval_with_rescue(&self)
|
|
@@ -48,7 +50,6 @@ module RSpec
|
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
class AroundHook < Hook
|
|
51
|
-
TYPE = 'around'
|
|
52
53
|
def call(wrapped_example)
|
|
53
54
|
@block.call(wrapped_example)
|
|
54
55
|
end
|
|
@@ -76,7 +77,7 @@ module RSpec
|
|
|
76
77
|
|
|
77
78
|
class AfterHooks < HookCollection
|
|
78
79
|
def run_all(example_group_instance)
|
|
79
|
-
reverse.each {|h| h.run_in(example_group_instance) }
|
|
80
|
+
reverse.each {|h| h.run_in(example_group_instance) }
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def run_all!(example_group_instance)
|
data/lib/rspec/core/let.rb
CHANGED
|
@@ -21,7 +21,7 @@ module RSpec
|
|
|
21
21
|
# end
|
|
22
22
|
def let(name, &block)
|
|
23
23
|
define_method(name) do
|
|
24
|
-
__memoized[
|
|
24
|
+
__memoized.fetch(name) {|k| __memoized[k] = instance_eval(&block) }
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -57,12 +57,12 @@ module RSpec
|
|
|
57
57
|
# let(:thing) { Thing.new }
|
|
58
58
|
#
|
|
59
59
|
# it "is not invoked implicitly" do
|
|
60
|
-
# Thing.count.should
|
|
60
|
+
# Thing.count.should eq(0)
|
|
61
61
|
# end
|
|
62
62
|
#
|
|
63
63
|
# it "can be invoked explicitly" do
|
|
64
64
|
# thing
|
|
65
|
-
# Thing.count.should
|
|
65
|
+
# Thing.count.should eq(1)
|
|
66
66
|
# end
|
|
67
67
|
# end
|
|
68
68
|
#
|
|
@@ -70,12 +70,12 @@ module RSpec
|
|
|
70
70
|
# let!(:thing) { Thing.new }
|
|
71
71
|
#
|
|
72
72
|
# it "is invoked implicitly" do
|
|
73
|
-
# Thing.count.should
|
|
73
|
+
# Thing.count.should eq(1)
|
|
74
74
|
# end
|
|
75
75
|
#
|
|
76
76
|
# it "returns memoized version on first invocation" do
|
|
77
77
|
# thing
|
|
78
|
-
# Thing.count.should
|
|
78
|
+
# Thing.count.should eq(1)
|
|
79
79
|
# end
|
|
80
80
|
# end
|
|
81
81
|
# end
|
data/lib/rspec/core/metadata.rb
CHANGED
|
@@ -2,7 +2,9 @@ module RSpec
|
|
|
2
2
|
module Core
|
|
3
3
|
class Metadata < Hash
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# Used to extend metadata Hashes to support lazy evaluation of locations
|
|
6
|
+
# and descriptions.
|
|
7
|
+
module MetadataHash
|
|
6
8
|
def [](key)
|
|
7
9
|
return super if has_key?(key)
|
|
8
10
|
case key
|
|
@@ -12,12 +14,22 @@ module RSpec
|
|
|
12
14
|
file_path, line_number = file_and_line_number
|
|
13
15
|
store(:file_path, file_path)
|
|
14
16
|
store(:line_number, line_number)
|
|
15
|
-
|
|
17
|
+
super
|
|
18
|
+
when :execution_result
|
|
19
|
+
store(:execution_result, {})
|
|
20
|
+
when :describes
|
|
21
|
+
store(:describes, described_class_for(self))
|
|
22
|
+
when :full_description
|
|
23
|
+
store(:full_description, full_description_for(self))
|
|
24
|
+
when :description
|
|
25
|
+
store(:description, build_description_from(*self[:description_args]))
|
|
16
26
|
else
|
|
17
27
|
super
|
|
18
28
|
end
|
|
19
29
|
end
|
|
20
30
|
|
|
31
|
+
private
|
|
32
|
+
|
|
21
33
|
def location
|
|
22
34
|
"#{self[:file_path]}:#{self[:line_number]}"
|
|
23
35
|
end
|
|
@@ -30,97 +42,105 @@ module RSpec
|
|
|
30
42
|
def first_caller_from_outside_rspec
|
|
31
43
|
self[:caller].detect {|l| l !~ /\/lib\/rspec\/core/}
|
|
32
44
|
end
|
|
45
|
+
|
|
46
|
+
def described_class_for(m)
|
|
47
|
+
m[:example_group][:describes]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def full_description_for(m)
|
|
51
|
+
build_description_from(m[:example_group][:full_description], *m[:description_args])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def build_description_from(*parts)
|
|
55
|
+
parts.map {|p| p.to_s}.reduce do |desc, p|
|
|
56
|
+
p =~ /^(#|::|\.)/ ? "#{desc}#{p}" : "#{desc} #{p}"
|
|
57
|
+
end || ""
|
|
58
|
+
end
|
|
33
59
|
end
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
module GroupMetadataHash
|
|
62
|
+
include MetadataHash
|
|
63
|
+
|
|
64
|
+
def described_class_for(*)
|
|
65
|
+
ancestors.each do |g|
|
|
66
|
+
return g[:describes] if g.has_key?(:describes)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
ancestors.reverse.each do |g|
|
|
70
|
+
candidate = g[:description_args].first
|
|
71
|
+
return candidate unless String === candidate || Symbol === candidate
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def full_description_for(*)
|
|
78
|
+
build_description_from(*ancestors.reverse.map do |a|
|
|
79
|
+
a.has_key?(:full_description) ? a[:full_description] : a[:description_args]
|
|
80
|
+
end.flatten)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
def ancestors
|
|
86
|
+
@ancestors ||= begin
|
|
87
|
+
groups = [group = self]
|
|
88
|
+
while group.has_key?(:example_group)
|
|
89
|
+
groups << group[:example_group]
|
|
90
|
+
group = group[:example_group]
|
|
91
|
+
end
|
|
92
|
+
groups
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def initialize(parent_group_metadata=nil)
|
|
98
|
+
if parent_group_metadata
|
|
99
|
+
update(parent_group_metadata)
|
|
100
|
+
store(:example_group, {:example_group => parent_group_metadata[:example_group]}.extend(GroupMetadataHash))
|
|
40
101
|
else
|
|
41
|
-
example_group
|
|
102
|
+
store(:example_group, {}.extend(GroupMetadataHash))
|
|
42
103
|
end
|
|
43
104
|
|
|
44
|
-
store(:example_group, example_group.extend(LocationKeys))
|
|
45
105
|
yield self if block_given?
|
|
46
106
|
end
|
|
47
107
|
|
|
48
|
-
RESERVED_KEYS = [
|
|
49
|
-
:description,
|
|
50
|
-
:example_group,
|
|
51
|
-
:execution_result,
|
|
52
|
-
:file_path,
|
|
53
|
-
:full_description,
|
|
54
|
-
:line_number,
|
|
55
|
-
:location
|
|
56
|
-
]
|
|
57
|
-
|
|
58
108
|
def process(*args)
|
|
59
109
|
user_metadata = args.last.is_a?(Hash) ? args.pop : {}
|
|
60
110
|
ensure_valid_keys(user_metadata)
|
|
61
111
|
|
|
112
|
+
self[:example_group].store(:description_args, args)
|
|
62
113
|
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))
|
|
67
114
|
|
|
68
115
|
update(user_metadata)
|
|
69
116
|
end
|
|
70
117
|
|
|
71
|
-
def ensure_valid_keys(user_metadata)
|
|
72
|
-
RESERVED_KEYS.each do |key|
|
|
73
|
-
if user_metadata.keys.include?(key)
|
|
74
|
-
raise <<-EOM
|
|
75
|
-
#{"*"*50}
|
|
76
|
-
:#{key} is not allowed
|
|
77
|
-
|
|
78
|
-
RSpec reserves some hash keys for its own internal use,
|
|
79
|
-
including :#{key}, which is used on:
|
|
80
|
-
|
|
81
|
-
#{caller(0)[4]}.
|
|
82
|
-
|
|
83
|
-
Here are all of RSpec's reserved hash keys:
|
|
84
|
-
|
|
85
|
-
#{RESERVED_KEYS.join("\n ")}
|
|
86
|
-
#{"*"*50}
|
|
87
|
-
EOM
|
|
88
|
-
raise ":#{key} is not allowed"
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
118
|
def for_example(description, user_metadata)
|
|
94
|
-
dup.extend(
|
|
119
|
+
dup.extend(MetadataHash).configure_for_example(description, user_metadata)
|
|
95
120
|
end
|
|
96
121
|
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
store(:full_description, "#{self[:example_group][:full_description]} #{self[:description]}")
|
|
100
|
-
store(:execution_result, {})
|
|
101
|
-
store(:caller, user_metadata.delete(:caller) || caller)
|
|
102
|
-
update(user_metadata)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def apply?(predicate, filters)
|
|
106
|
-
filters.send(predicate) do |key, value|
|
|
107
|
-
apply_condition(key, value)
|
|
108
|
-
end
|
|
122
|
+
def any_apply?(filters)
|
|
123
|
+
filters.any? {|k,v| filter_applies?(k,v)}
|
|
109
124
|
end
|
|
110
125
|
|
|
111
|
-
def
|
|
112
|
-
|
|
113
|
-
if metadata[:example_group]
|
|
114
|
-
line_numbers + relevant_line_numbers(metadata[:example_group])
|
|
115
|
-
else
|
|
116
|
-
line_numbers
|
|
117
|
-
end
|
|
126
|
+
def all_apply?(filters)
|
|
127
|
+
filters.all? {|k,v| filter_applies?(k,v)}
|
|
118
128
|
end
|
|
119
129
|
|
|
120
|
-
def
|
|
130
|
+
def filter_applies?(key, value, metadata=self)
|
|
121
131
|
case value
|
|
122
132
|
when Hash
|
|
123
|
-
|
|
133
|
+
if key == :locations
|
|
134
|
+
file_path = (self[:example_group] || {})[:file_path]
|
|
135
|
+
expanded_path = file_path && File.expand_path( file_path )
|
|
136
|
+
if expanded_path && line_numbers = value[expanded_path]
|
|
137
|
+
filter_applies?(:line_numbers, line_numbers)
|
|
138
|
+
else
|
|
139
|
+
true
|
|
140
|
+
end
|
|
141
|
+
else
|
|
142
|
+
value.all? { |k, v| filter_applies?(k, v, metadata[key]) }
|
|
143
|
+
end
|
|
124
144
|
when Regexp
|
|
125
145
|
metadata[key] =~ value
|
|
126
146
|
when Proc
|
|
@@ -135,9 +155,12 @@ EOM
|
|
|
135
155
|
else
|
|
136
156
|
value.call(metadata[key]) rescue false
|
|
137
157
|
end
|
|
138
|
-
when
|
|
139
|
-
|
|
140
|
-
|
|
158
|
+
when String
|
|
159
|
+
metadata[key].to_s == value.to_s
|
|
160
|
+
when Enumerable
|
|
161
|
+
if key == :line_numbers
|
|
162
|
+
preceding_declaration_lines = value.map{|v| world.preceding_declaration_line(v)}
|
|
163
|
+
!(relevant_line_numbers(metadata) & preceding_declaration_lines).empty?
|
|
141
164
|
else
|
|
142
165
|
metadata[key] == value
|
|
143
166
|
end
|
|
@@ -146,42 +169,61 @@ EOM
|
|
|
146
169
|
end
|
|
147
170
|
end
|
|
148
171
|
|
|
149
|
-
|
|
172
|
+
protected
|
|
150
173
|
|
|
151
|
-
def
|
|
152
|
-
|
|
174
|
+
def configure_for_example(description, user_metadata)
|
|
175
|
+
store(:description_args, [description])
|
|
176
|
+
store(:caller, user_metadata.delete(:caller) || caller)
|
|
177
|
+
update(user_metadata)
|
|
153
178
|
end
|
|
154
179
|
|
|
155
|
-
|
|
156
|
-
@superclass_metadata ||= { :example_group => {} }
|
|
157
|
-
end
|
|
180
|
+
private
|
|
158
181
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
182
|
+
RESERVED_KEYS = [
|
|
183
|
+
:description,
|
|
184
|
+
:example_group,
|
|
185
|
+
:execution_result,
|
|
186
|
+
:file_path,
|
|
187
|
+
:full_description,
|
|
188
|
+
:line_number,
|
|
189
|
+
:location
|
|
190
|
+
]
|
|
191
|
+
|
|
192
|
+
def ensure_valid_keys(user_metadata)
|
|
193
|
+
RESERVED_KEYS.each do |key|
|
|
194
|
+
if user_metadata.keys.include?(key)
|
|
195
|
+
raise <<-EOM
|
|
196
|
+
#{"*"*50}
|
|
197
|
+
:#{key} is not allowed
|
|
198
|
+
|
|
199
|
+
RSpec reserves some hash keys for its own internal use,
|
|
200
|
+
including :#{key}, which is used on:
|
|
201
|
+
|
|
202
|
+
#{caller(0)[4]}.
|
|
203
|
+
|
|
204
|
+
Here are all of RSpec's reserved hash keys:
|
|
205
|
+
|
|
206
|
+
#{RESERVED_KEYS.join("\n ")}
|
|
207
|
+
#{"*"*50}
|
|
208
|
+
EOM
|
|
209
|
+
raise ":#{key} is not allowed"
|
|
168
210
|
end
|
|
169
211
|
end
|
|
170
212
|
end
|
|
171
213
|
|
|
172
|
-
def
|
|
173
|
-
|
|
174
|
-
description_from(superclass_metadata[:example_group][:full_description], *args)
|
|
175
|
-
else
|
|
176
|
-
description_from(*args)
|
|
177
|
-
end
|
|
214
|
+
def world
|
|
215
|
+
RSpec.world
|
|
178
216
|
end
|
|
179
217
|
|
|
180
|
-
def
|
|
181
|
-
|
|
182
|
-
|
|
218
|
+
def relevant_line_numbers(metadata)
|
|
219
|
+
line_numbers = [metadata[:line_number]]
|
|
220
|
+
if metadata[:example_group]
|
|
221
|
+
line_numbers + relevant_line_numbers(metadata[:example_group])
|
|
222
|
+
else
|
|
223
|
+
line_numbers
|
|
183
224
|
end
|
|
184
225
|
end
|
|
226
|
+
|
|
185
227
|
end
|
|
186
228
|
end
|
|
187
229
|
end
|
|
@@ -40,8 +40,7 @@ module RSpec::Core
|
|
|
40
40
|
options[:debug] = true
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
parser.on('-e', '--example
|
|
44
|
-
"(PATTERN is compiled into a Ruby regular expression)") do |o|
|
|
43
|
+
parser.on('-e', '--example STRING', "Run examples whose full nested names include STRING") do |o|
|
|
45
44
|
options[:full_description] = Regexp.compile(Regexp.escape(o))
|
|
46
45
|
end
|
|
47
46
|
|
|
@@ -74,8 +73,8 @@ module RSpec::Core
|
|
|
74
73
|
options[:libs] << dir
|
|
75
74
|
end
|
|
76
75
|
|
|
77
|
-
parser.on('-l', '--line_number LINE', 'Specify the line number of
|
|
78
|
-
options[:
|
|
76
|
+
parser.on('-l', '--line_number LINE', 'Specify the line number of an example to run. May be specified multiple times.') do |o|
|
|
77
|
+
(options[:line_numbers] ||= []) << o
|
|
79
78
|
end
|
|
80
79
|
|
|
81
80
|
parser.on('-O', '--options PATH', 'Specify the path to an options file') do |path|
|
|
@@ -86,7 +85,7 @@ module RSpec::Core
|
|
|
86
85
|
options[:profile_examples] = o
|
|
87
86
|
end
|
|
88
87
|
|
|
89
|
-
parser.on('-P', '--pattern PATTERN', 'Load files
|
|
88
|
+
parser.on('-P', '--pattern PATTERN', 'Load files matching this pattern. Default is "spec/**/*_spec.rb"') do |o|
|
|
90
89
|
options[:pattern] = o
|
|
91
90
|
end
|
|
92
91
|
|
|
@@ -100,8 +99,8 @@ module RSpec::Core
|
|
|
100
99
|
exit
|
|
101
100
|
end
|
|
102
101
|
|
|
103
|
-
parser.on('-X', '--drb', 'Run examples via DRb') do |o|
|
|
104
|
-
options[:drb] =
|
|
102
|
+
parser.on('-X', '--[no-]drb', 'Run examples via DRb') do |o|
|
|
103
|
+
options[:drb] = o
|
|
105
104
|
end
|
|
106
105
|
|
|
107
106
|
parser.on('--configure COMMAND', 'Generate configuration files') do |cmd|
|
|
@@ -133,6 +132,11 @@ module RSpec::Core
|
|
|
133
132
|
parser.on('--tty', 'Used internally by rspec when sending commands to other processes') do |o|
|
|
134
133
|
options[:tty] = true
|
|
135
134
|
end
|
|
135
|
+
|
|
136
|
+
parser.on('--default_path PATH', 'Set the default path where RSpec looks for examples.',
|
|
137
|
+
'Can be a path to a file or a directory') do |path|
|
|
138
|
+
options[:default_path] = path
|
|
139
|
+
end
|
|
136
140
|
end
|
|
137
141
|
end
|
|
138
142
|
end
|
data/lib/rspec/core/pending.rb
CHANGED
|
@@ -24,7 +24,8 @@ module RSpec
|
|
|
24
24
|
example.example_group_instance.instance_eval { verify_mocks_for_rspec }
|
|
25
25
|
end
|
|
26
26
|
example.metadata[:pending] = false
|
|
27
|
-
rescue Exception
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
example.execution_result[:exception] = e
|
|
28
29
|
ensure
|
|
29
30
|
teardown_mocks_for_rspec
|
|
30
31
|
end
|