rspec-core 2.0.0.beta.20 → 2.0.0.beta.22
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/.rspec +1 -1
- data/Gemfile +7 -6
- data/History.md +30 -0
- data/Rakefile +3 -43
- data/bin/rspec +2 -1
- data/features/configuration/{options_file.feature → read_options_from_file.feature} +29 -25
- data/features/example_groups/shared_example_group.feature +10 -6
- data/features/hooks/before_and_after_hooks.feature +38 -0
- data/lib/autotest/rspec2.rb +10 -2
- data/lib/rspec/core.rb +8 -0
- data/lib/rspec/core/configuration.rb +16 -10
- data/lib/rspec/core/configuration_options.rb +7 -3
- data/lib/rspec/core/example.rb +7 -0
- data/lib/rspec/core/example_group.rb +15 -2
- data/lib/rspec/core/extensions/module_eval_with_args.rb +9 -29
- data/lib/rspec/core/extensions/object.rb +0 -2
- data/lib/rspec/core/formatters/base_formatter.rb +8 -6
- data/lib/rspec/core/formatters/base_text_formatter.rb +18 -10
- data/lib/rspec/core/formatters/documentation_formatter.rb +9 -9
- data/lib/rspec/core/option_parser.rb +0 -4
- data/lib/rspec/core/rake_task.rb +85 -39
- data/lib/rspec/core/reporter.rb +18 -5
- data/lib/rspec/core/runner.rb +8 -18
- data/lib/rspec/core/shared_example_group.rb +2 -1
- data/lib/rspec/core/version.rb +1 -1
- data/rspec-core.gemspec +33 -233
- data/spec/autotest/failed_results_re_spec.rb +1 -2
- data/spec/autotest/rspec_spec.rb +62 -42
- data/spec/rspec/core/configuration_options_spec.rb +12 -29
- data/spec/rspec/core/configuration_spec.rb +8 -8
- data/spec/rspec/core/example_group_spec.rb +38 -7
- data/spec/rspec/core/example_spec.rb +16 -1
- data/spec/rspec/core/formatters/base_formatter_spec.rb +6 -0
- data/spec/rspec/core/formatters/base_text_formatter_spec.rb +125 -10
- data/spec/rspec/core/formatters/documentation_formatter_spec.rb +36 -0
- data/spec/rspec/core/formatters/html_formatted-1.8.7-jruby.html +282 -0
- data/spec/rspec/core/formatters/html_formatted-1.9.1.html +22 -2
- data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-jruby.html +280 -0
- data/spec/rspec/core/formatters/text_mate_formatted-1.9.1.html +280 -0
- data/spec/rspec/core/rake_task_spec.rb +128 -0
- data/spec/rspec/core/reporter_spec.rb +36 -0
- data/spec/rspec/core/runner_spec.rb +0 -18
- data/spec/rspec/core/shared_example_group_spec.rb +22 -2
- data/spec/rspec/core/world_spec.rb +13 -15
- data/spec/spec_helper.rb +2 -1
- metadata +110 -13
- data/VERSION +0 -1
- data/lib/rspec/autorun.rb +0 -2
@@ -11,42 +11,22 @@ module RSpec
|
|
11
11
|
# If there are no args and the block doesn't expect any, there's no
|
12
12
|
# need to fake module_exec with our hack below.
|
13
13
|
# Notes:
|
14
|
-
# * lambda {
|
15
|
-
# * lambda { ||
|
16
|
-
# * lambda { |*a| }.arity # -1
|
14
|
+
# * lambda { }.arity # => -1
|
15
|
+
# * lambda { || }.arity # => 0
|
16
|
+
# * lambda { |*a| }.arity # => -1
|
17
17
|
return module_eval(&block) if block.arity < 1 && args.size.zero?
|
18
18
|
|
19
|
+
orig_singleton_methods = singleton_methods
|
19
20
|
instance_eval_with_args(*args, &block)
|
20
21
|
|
21
22
|
# The only difference between instance_eval and module_eval is static method defs.
|
22
23
|
# * `def foo` in instance_eval defines a singleton method on the instance
|
23
24
|
# * `def foo` in class/module_eval defines an instance method for the class/module
|
24
|
-
# Here we deal with this difference by defining instance
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
singleton_class.send(:remove_method, m_name)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def extract_static_instance_method_defs_from(block)
|
36
|
-
klass = Class.new do
|
37
|
-
# swallow any missing class method errors;
|
38
|
-
# we only care to capture the raw method definitions here.
|
39
|
-
def self.method_missing(*a); end
|
40
|
-
|
41
|
-
# skip any dynamic method definitions
|
42
|
-
def self.define_method(*a); end
|
43
|
-
|
44
|
-
# run the block so our instance methods get defined
|
45
|
-
class_eval(&block)
|
46
|
-
end
|
47
|
-
|
48
|
-
instance = klass.new
|
49
|
-
klass.instance_methods(false).inject({}) { |h, m| h[m] = instance.method(m); h }
|
25
|
+
# Here we deal with this difference by defining an instance method for
|
26
|
+
# each new singleton method.
|
27
|
+
# This has the side effect of duplicating methods (all new class methods will
|
28
|
+
# become instance methods and vice versa), but I don't see a way around it...
|
29
|
+
(singleton_methods - orig_singleton_methods).each { |m| define_method(m, &method(m)) }
|
50
30
|
end
|
51
31
|
end
|
52
32
|
end
|
@@ -38,6 +38,11 @@ module RSpec
|
|
38
38
|
@example_group = example_group
|
39
39
|
end
|
40
40
|
|
41
|
+
# This method is invoked at the end of the execution of each example group.
|
42
|
+
# +example_group+ is the example_group.
|
43
|
+
def example_group_finished(example_group)
|
44
|
+
end
|
45
|
+
|
41
46
|
def add_example_group(example_group)
|
42
47
|
RSpec.deprecate("add_example_group", "example_group_started")
|
43
48
|
example_group_started(example_group)
|
@@ -93,10 +98,7 @@ module RSpec
|
|
93
98
|
def format_backtrace(backtrace, example)
|
94
99
|
return "" unless backtrace
|
95
100
|
return backtrace if example.metadata[:full_backtrace] == true
|
96
|
-
|
97
|
-
cleansed = backtrace.select { |line| backtrace_line(line) }
|
98
|
-
# Kick the describe stack info off the list, just keep the line the problem happened on from that file
|
99
|
-
# cleansed = [cleansed.detect { |line| line.split(':').first == example.metadata[:caller].split(':').first }] if cleansed.size > 1
|
101
|
+
cleansed = backtrace.map { |line| backtrace_line(line) }.compact
|
100
102
|
cleansed.empty? ? backtrace : cleansed
|
101
103
|
end
|
102
104
|
|
@@ -108,8 +110,8 @@ module RSpec
|
|
108
110
|
|
109
111
|
def backtrace_line(line)
|
110
112
|
return nil if configuration.cleaned_from_backtrace?(line)
|
111
|
-
line.sub
|
112
|
-
line.sub
|
113
|
+
line = line.sub(File.expand_path("."), ".")
|
114
|
+
line = line.sub(/\A([^:]+:\d+)$/, '\\1')
|
113
115
|
return nil if line == '-e:1'
|
114
116
|
line
|
115
117
|
end
|
@@ -22,10 +22,18 @@ module RSpec
|
|
22
22
|
output.puts "#{padding}Expected pending '#{example.metadata[:execution_result][:pending_message]}' to fail. No Error was raised."
|
23
23
|
else
|
24
24
|
output.puts "#{short_padding}#{index.next}) #{example.full_description}"
|
25
|
-
output.puts "#{padding}Failure/Error: #{read_failed_line(exception, example).strip}"
|
25
|
+
output.puts "#{padding}#{red("Failure/Error:")} #{red(read_failed_line(exception, example).strip)}"
|
26
26
|
exception.message.split("\n").each do |line|
|
27
27
|
output.puts "#{padding}#{red(line)}"
|
28
28
|
end
|
29
|
+
|
30
|
+
example.example_group.ancestors.push(example.example_group).each do |group|
|
31
|
+
if group.metadata[:shared_group_name]
|
32
|
+
output.puts "#{padding}Shared Example Group: \"#{group.metadata[:shared_group_name]}\" called from " +
|
33
|
+
"#{backtrace_line(group.metadata[:example_group][:location])}"
|
34
|
+
break
|
35
|
+
end
|
36
|
+
end
|
29
37
|
end
|
30
38
|
|
31
39
|
format_backtrace(exception.backtrace, example).each do |backtrace_info|
|
@@ -48,18 +56,18 @@ module RSpec
|
|
48
56
|
|
49
57
|
def dump_summary(duration, example_count, failure_count, pending_count)
|
50
58
|
super(duration, example_count, failure_count, pending_count)
|
59
|
+
# Don't print out profiled info if there are failures, it just clutters the output
|
60
|
+
dump_profile if profile_examples? && failure_count == 0
|
51
61
|
output.puts "\nFinished in #{format_seconds(duration)} seconds\n"
|
52
|
-
|
53
62
|
output.puts colorise_summary(summary_line(example_count, failure_count, pending_count))
|
63
|
+
end
|
54
64
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
output.puts grey(" # #{format_caller(example.metadata[:location])}")
|
62
|
-
end
|
65
|
+
def dump_profile
|
66
|
+
sorted_examples = examples.sort_by { |example| example.execution_result[:run_time] }.reverse.first(10)
|
67
|
+
output.puts "\nTop #{sorted_examples.size} slowest examples:\n"
|
68
|
+
sorted_examples.each do |example|
|
69
|
+
output.puts " #{example.full_description}"
|
70
|
+
output.puts grey(" #{red(format_seconds(example.execution_result[:run_time]))} #{red("seconds")} #{format_caller(example.metadata[:location])}")
|
63
71
|
end
|
64
72
|
end
|
65
73
|
|
@@ -6,20 +6,20 @@ module RSpec
|
|
6
6
|
|
7
7
|
def initialize(output)
|
8
8
|
super(output)
|
9
|
-
@
|
9
|
+
@group_level = 0
|
10
10
|
end
|
11
11
|
|
12
12
|
def example_group_started(example_group)
|
13
13
|
super(example_group)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
output.puts if i == 0
|
18
|
-
output.puts "#{' ' * i}#{nested_example_group.description}"
|
19
|
-
end
|
20
|
-
end
|
15
|
+
output.puts if @group_level == 0
|
16
|
+
output.puts "#{' ' * @group_level}#{example_group.description}"
|
21
17
|
|
22
|
-
@
|
18
|
+
@group_level += 1
|
19
|
+
end
|
20
|
+
|
21
|
+
def example_group_finished(example_group)
|
22
|
+
@group_level -= 1
|
23
23
|
end
|
24
24
|
|
25
25
|
def example_passed(example)
|
@@ -55,7 +55,7 @@ module RSpec
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def current_indentation
|
58
|
-
' ' * @
|
58
|
+
' ' * @group_level
|
59
59
|
end
|
60
60
|
|
61
61
|
def example_group_chain
|
@@ -64,10 +64,6 @@ module RSpec::Core
|
|
64
64
|
options[:line_number] = o
|
65
65
|
end
|
66
66
|
|
67
|
-
parser.on('-o', '--options PATH', 'Read configuration options from a file path. (Defaults to .rspec)') do |o|
|
68
|
-
options[:options_file] = o || local_options_file
|
69
|
-
end
|
70
|
-
|
71
67
|
parser.on('-p', '--profile', 'Enable profiling of examples with output of the top 10 slowest examples') do |o|
|
72
68
|
options[:profile_examples] = o
|
73
69
|
end
|
data/lib/rspec/core/rake_task.rb
CHANGED
@@ -8,57 +8,94 @@ module RSpec
|
|
8
8
|
|
9
9
|
class RakeTask < ::Rake::TaskLib
|
10
10
|
|
11
|
-
# Name of task.
|
11
|
+
# Name of task.
|
12
|
+
#
|
13
|
+
# default:
|
14
|
+
# :spec
|
12
15
|
attr_accessor :name
|
13
16
|
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
|
18
|
-
# Glob pattern to match files. (default is 'spec/**/*_spec.rb')
|
17
|
+
# Glob pattern to match files.
|
18
|
+
#
|
19
|
+
# default:
|
20
|
+
# 'spec/**/*_spec.rb'
|
19
21
|
attr_accessor :pattern
|
20
22
|
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
#
|
25
|
-
|
23
|
+
# Deprecated. Use ruby_opts="-w" instead.
|
24
|
+
# When true, requests that the specs be run with the warning flag set.
|
25
|
+
# e.g. "ruby -w"
|
26
|
+
#
|
27
|
+
# default:
|
28
|
+
# false
|
29
|
+
attr_reader :warning
|
30
|
+
|
31
|
+
def warning=(true_or_false)
|
32
|
+
RSpec.deprecate("warning", 'ruby_opts="-w"')
|
33
|
+
@warning = true_or_false
|
34
|
+
end
|
26
35
|
|
27
36
|
# Whether or not to fail Rake when an error occurs (typically when examples fail).
|
28
|
-
#
|
37
|
+
#
|
38
|
+
# default:
|
39
|
+
# true
|
29
40
|
attr_accessor :fail_on_error
|
30
41
|
|
31
42
|
# A message to print to stderr when there are failures.
|
32
43
|
attr_accessor :failure_message
|
33
44
|
|
34
|
-
# Use verbose output. If this is set to true, the task will print
|
35
|
-
#
|
45
|
+
# Use verbose output. If this is set to true, the task will print the
|
46
|
+
# executed spec command to stdout.
|
47
|
+
#
|
48
|
+
# default:
|
49
|
+
# false
|
36
50
|
attr_accessor :verbose
|
37
51
|
|
38
|
-
# Use rcov for code coverage?
|
52
|
+
# Use rcov for code coverage?
|
53
|
+
#
|
54
|
+
# default:
|
55
|
+
# false
|
39
56
|
attr_accessor :rcov
|
40
57
|
|
41
|
-
# Path to rcov.
|
58
|
+
# Path to rcov.
|
59
|
+
#
|
60
|
+
# defaults:
|
61
|
+
# 'rcov'
|
42
62
|
attr_accessor :rcov_path
|
43
63
|
|
44
|
-
#
|
64
|
+
# Command line options to pass to rcov.
|
65
|
+
#
|
66
|
+
# default:
|
67
|
+
# nil
|
45
68
|
attr_accessor :rcov_opts
|
46
69
|
|
70
|
+
# Command line options to pass to ruby.
|
71
|
+
#
|
72
|
+
# default:
|
73
|
+
# nil
|
74
|
+
attr_accessor :ruby_opts
|
75
|
+
|
76
|
+
# Command line options to pass to rspec.
|
77
|
+
#
|
78
|
+
# default:
|
79
|
+
# nil
|
80
|
+
attr_accessor :rspec_opts
|
81
|
+
|
82
|
+
# Deprecated. Use rspec_opts instead.
|
83
|
+
def spec_opts=(opts)
|
84
|
+
RSpec.deprecate("spec_opts","rspec_opts")
|
85
|
+
@rspec_opts = opts
|
86
|
+
end
|
87
|
+
|
47
88
|
def initialize(*args)
|
48
89
|
@name = args.shift || :spec
|
49
|
-
@pattern, @rcov_path, @rcov_opts, @ruby_opts = nil, nil, nil, nil
|
90
|
+
@pattern, @rcov_path, @rcov_opts, @ruby_opts, @rspec_opts = nil, nil, nil, nil, nil
|
50
91
|
@warning, @rcov = false, false
|
51
92
|
@fail_on_error = true
|
52
|
-
@spec_opts = []
|
53
93
|
|
54
94
|
yield self if block_given?
|
95
|
+
|
55
96
|
@rcov_path ||= 'rcov'
|
56
97
|
@pattern ||= './spec/**/*_spec.rb'
|
57
|
-
define
|
58
|
-
end
|
59
98
|
|
60
|
-
def define # :nodoc:
|
61
|
-
actual_name = Hash === name ? name.keys.first : name
|
62
99
|
desc("Run RSpec code examples") unless ::Rake.application.last_comment
|
63
100
|
|
64
101
|
task name do
|
@@ -67,47 +104,56 @@ module RSpec
|
|
67
104
|
puts "No examples matching #{pattern} could be found"
|
68
105
|
else
|
69
106
|
puts spec_command.inspect if verbose
|
70
|
-
unless ruby(
|
107
|
+
unless ruby(spec_command)
|
71
108
|
STDERR.puts failure_message if failure_message
|
72
109
|
raise("#{spec_command} failed") if fail_on_error
|
73
110
|
end
|
74
111
|
end
|
75
112
|
end
|
76
113
|
end
|
77
|
-
|
78
|
-
self
|
79
114
|
end
|
80
115
|
|
81
116
|
def files_to_run # :nodoc:
|
82
|
-
FileList[ pattern ].
|
117
|
+
FileList[ pattern ].map { |f| %["#{f}"] }
|
83
118
|
end
|
84
119
|
|
85
120
|
private
|
86
121
|
|
87
122
|
def spec_command
|
88
123
|
@spec_command ||= begin
|
89
|
-
cmd_parts =
|
90
|
-
cmd_parts << "-w" if warning
|
91
|
-
cmd_parts
|
92
|
-
cmd_parts
|
93
|
-
cmd_parts
|
94
|
-
cmd_parts
|
95
|
-
cmd_parts <<
|
96
|
-
cmd_parts.join(" ")
|
124
|
+
cmd_parts = [ruby_opts]
|
125
|
+
cmd_parts << "-w" if warning?
|
126
|
+
cmd_parts << "-S"
|
127
|
+
cmd_parts << "bundle exec" if bundler?
|
128
|
+
cmd_parts << runner
|
129
|
+
cmd_parts << runner_options
|
130
|
+
cmd_parts << files_to_run
|
131
|
+
cmd_parts.flatten.compact.reject(&blank).join(" ")
|
97
132
|
end
|
98
133
|
end
|
99
134
|
|
135
|
+
private
|
136
|
+
|
100
137
|
def runner
|
101
|
-
rcov ? rcov_path :
|
138
|
+
rcov ? rcov_path : 'rspec'
|
102
139
|
end
|
103
140
|
|
104
141
|
def runner_options
|
105
|
-
rcov ? [rcov_opts] : [
|
142
|
+
rcov ? [rcov_opts] : [rspec_opts]
|
106
143
|
end
|
107
144
|
|
108
|
-
def bundler
|
109
|
-
File.exist?("./Gemfile")
|
145
|
+
def bundler?
|
146
|
+
File.exist?("./Gemfile")
|
110
147
|
end
|
148
|
+
|
149
|
+
def warning?
|
150
|
+
warning
|
151
|
+
end
|
152
|
+
|
153
|
+
def blank
|
154
|
+
lambda {|s| s == ""}
|
155
|
+
end
|
156
|
+
|
111
157
|
end
|
112
158
|
|
113
159
|
end
|
data/lib/rspec/core/reporter.rb
CHANGED
@@ -2,13 +2,20 @@ module RSpec::Core
|
|
2
2
|
class Reporter
|
3
3
|
def initialize(*formatters)
|
4
4
|
@formatters = formatters
|
5
|
-
@failure_count = @pending_count = 0
|
5
|
+
@example_count = @failure_count = @pending_count = 0
|
6
6
|
end
|
7
7
|
|
8
8
|
def report(count)
|
9
9
|
start(count)
|
10
10
|
begin
|
11
11
|
yield self
|
12
|
+
ensure
|
13
|
+
conclude
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def conclude
|
18
|
+
begin
|
12
19
|
stop
|
13
20
|
notify :start_dump
|
14
21
|
notify :dump_pending
|
@@ -19,10 +26,11 @@ module RSpec::Core
|
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
alias_method :abort, :conclude
|
30
|
+
|
31
|
+
def start(expected_example_count)
|
24
32
|
@start = Time.now
|
25
|
-
notify :start,
|
33
|
+
notify :start, expected_example_count
|
26
34
|
end
|
27
35
|
|
28
36
|
def message(message)
|
@@ -33,7 +41,12 @@ module RSpec::Core
|
|
33
41
|
notify :example_group_started, group
|
34
42
|
end
|
35
43
|
|
44
|
+
def example_group_finished(group)
|
45
|
+
notify :example_group_finished, group
|
46
|
+
end
|
47
|
+
|
36
48
|
def example_started(example)
|
49
|
+
@example_count += 1
|
37
50
|
notify :example_started, example
|
38
51
|
end
|
39
52
|
|
@@ -52,7 +65,7 @@ module RSpec::Core
|
|
52
65
|
end
|
53
66
|
|
54
67
|
def stop
|
55
|
-
@duration = Time.now - @start
|
68
|
+
@duration = Time.now - @start if @start
|
56
69
|
notify :stop
|
57
70
|
end
|
58
71
|
|
data/lib/rspec/core/runner.rb
CHANGED
@@ -4,30 +4,20 @@ module RSpec
|
|
4
4
|
module Core
|
5
5
|
class Runner
|
6
6
|
|
7
|
-
def self.autorun
|
8
|
-
return if autorun_disabled? || installed_at_exit? || running_in_drb?
|
9
|
-
@installed_at_exit = true
|
10
|
-
at_exit { run(ARGV, $stderr, $stdout) ? exit(0) : exit(1) }
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.autorun_disabled?
|
14
|
-
@autorun_disabled ||= false
|
15
|
-
end
|
16
|
-
|
17
7
|
def self.disable_autorun!
|
18
|
-
|
8
|
+
RSpec.deprecate("disable_autorun!")
|
19
9
|
end
|
20
10
|
|
21
|
-
def self.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
!!((DRb.current_server.uri) =~ /druby\:\/\/127.0.0.1\:/)
|
11
|
+
def self.trap_interrupt
|
12
|
+
trap('INT') do
|
13
|
+
exit!(1) if RSpec.wants_to_quit
|
14
|
+
RSpec.wants_to_quit = true
|
15
|
+
STDERR.puts "\nExiting... Interrupt again to exit immediately."
|
16
|
+
end
|
28
17
|
end
|
29
18
|
|
30
19
|
def self.run(args, err, out)
|
20
|
+
trap_interrupt
|
31
21
|
options = ConfigurationOptions.new(args)
|
32
22
|
options.parse_options
|
33
23
|
|