rspec 0.7.2 → 0.7.5.1
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/CHANGES +72 -1
- data/EXAMPLES.rd +6 -0
- data/README +27 -6
- data/Rakefile +32 -81
- data/bin/drbspec +3 -0
- data/bin/spec +2 -3
- data/examples/file_accessor_spec.rb +1 -1
- data/examples/greeter_spec.rb +30 -0
- data/examples/helper_method_example.rb +1 -1
- data/examples/io_processor_spec.rb +1 -1
- data/examples/mocking_example.rb +1 -1
- data/examples/partial_mock_example.rb +1 -1
- data/examples/predicate_example.rb +1 -1
- data/examples/setup_teardown_example.rb +34 -0
- data/examples/spec_helper.rb +1 -0
- data/examples/stack_spec.rb +1 -1
- data/examples/stubbing_example.rb +1 -1
- data/examples/test_case_spec.rb +1 -1
- data/lib/spec/callback/callback_container.rb +60 -0
- data/lib/spec/callback/extensions/module.rb +24 -0
- data/lib/spec/callback/extensions/object.rb +33 -0
- data/lib/spec/callback.rb +3 -0
- data/lib/spec/expectations/diff.rb +10 -14
- data/lib/spec/expectations/extensions/numeric.rb +17 -3
- data/lib/spec/expectations/extensions/object.rb +145 -0
- data/lib/spec/expectations/extensions/proc.rb +57 -0
- data/lib/spec/expectations/extensions/string.rb +22 -0
- data/lib/spec/expectations/extensions.rb +2 -2
- data/lib/spec/expectations/message_builder.rb +13 -0
- data/lib/spec/expectations/should/base.rb +29 -10
- data/lib/spec/expectations/should/change.rb +69 -0
- data/lib/spec/expectations/should/have.rb +94 -37
- data/lib/spec/expectations/should/not.rb +6 -2
- data/lib/spec/expectations/should/should.rb +9 -5
- data/lib/spec/expectations/should.rb +1 -0
- data/lib/spec/expectations/sugar.rb +2 -2
- data/lib/spec/expectations.rb +28 -0
- data/lib/spec/mocks/error_generator.rb +23 -12
- data/lib/spec/mocks/message_expectation.rb +18 -15
- data/lib/spec/mocks/mock_handler.rb +10 -9
- data/lib/spec/mocks/mock_methods.rb +1 -1
- data/lib/spec/rake/spectask.rb +8 -2
- data/lib/spec/runner/backtrace_tweaker.rb +34 -25
- data/lib/spec/runner/context.rb +56 -7
- data/lib/spec/runner/context_eval.rb +33 -3
- data/lib/spec/runner/context_runner.rb +24 -11
- data/lib/spec/runner/drb_command_line.rb +21 -0
- data/lib/spec/runner/execution_context.rb +1 -0
- data/lib/spec/runner/extensions/kernel.rb +2 -0
- data/lib/spec/runner/extensions/object.rb +26 -18
- data/lib/spec/runner/formatter/base_text_formatter.rb +1 -1
- data/lib/spec/runner/formatter/html_formatter.rb +94 -74
- data/lib/spec/runner/heckle_runner.rb +55 -0
- data/lib/spec/runner/option_parser.rb +15 -3
- data/lib/spec/runner/reporter.rb +13 -8
- data/lib/spec/runner/specification.rb +67 -42
- data/lib/spec/runner.rb +1 -1
- data/lib/spec/version.rb +6 -5
- data/lib/spec.rb +1 -0
- metadata +20 -19
- data/lib/spec/expectations/extensions/inspect_for_expectation_not_met_error.rb +0 -14
- data/lib/spec/expectations/extensions/symbol.rb +0 -5
- data/vendor/selenium/README.txt +0 -23
- data/vendor/selenium/find_rspecs_home_page.rb +0 -23
- data/vendor/selenium/rspec_selenium.rb +0 -33
- data/vendor/selenium/start_browser_once.patch +0 -65
- data/vendor/watir/README.txt +0 -32
- data/vendor/watir/find_rspecs_home_page.rb +0 -21
- data/vendor/watir/find_rspecs_home_page.txt +0 -15
- data/vendor/watir/rspec_watir.rb +0 -45
@@ -1,21 +1,29 @@
|
|
1
|
-
#
|
1
|
+
# Copyright (c) 2004 David Heinemeier Hansson
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
2
21
|
class Object
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
n += 1 while respond_to?(mname="__instance_exec#{n}")
|
10
|
-
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
11
|
-
ensure
|
12
|
-
Thread.critical = old_critical
|
13
|
-
end
|
14
|
-
begin
|
15
|
-
ret = send(mname, *args)
|
16
|
-
ensure
|
17
|
-
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
18
|
-
end
|
19
|
-
ret
|
22
|
+
# From active_support
|
23
|
+
def copy_instance_variables_from(object, exclude = [])
|
24
|
+
exclude += object.protected_instance_variables if object.respond_to? :protected_instance_variables
|
25
|
+
|
26
|
+
instance_variables = object.instance_variables - exclude.map { |name| name.to_s }
|
27
|
+
instance_variables.each { |name| instance_variable_set(name, object.instance_variable_get(name)) }
|
20
28
|
end
|
21
29
|
end
|
@@ -4,83 +4,98 @@ module Spec
|
|
4
4
|
class HtmlFormatter < BaseTextFormatter
|
5
5
|
def initialize(output, dry_run=false, colour=false)
|
6
6
|
super
|
7
|
-
@
|
8
|
-
@
|
7
|
+
@current_spec_number = 0
|
8
|
+
@current_context_number = 0
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def start(spec_count)
|
12
12
|
@spec_count = spec_count
|
13
|
-
|
14
|
-
@output.puts
|
13
|
+
|
14
|
+
@output.puts @@header
|
15
15
|
STDOUT.flush
|
16
16
|
end
|
17
17
|
|
18
18
|
def add_context(name, first)
|
19
|
+
@current_context_number += 1
|
19
20
|
unless first
|
20
|
-
@output.puts " </
|
21
|
+
@output.puts " </dl>"
|
21
22
|
@output.puts "</div>"
|
22
23
|
end
|
23
24
|
@output.puts "<div class=\"context\">"
|
24
|
-
@output.puts " <
|
25
|
-
@output.puts " <
|
25
|
+
@output.puts " <dl>"
|
26
|
+
@output.puts " <dt id=\"context_#{@current_context_number}\">#{name}</dt>"
|
26
27
|
STDOUT.flush
|
27
28
|
end
|
28
29
|
|
29
30
|
def start_dump
|
30
|
-
@output.puts " </
|
31
|
+
@output.puts " </dl>"
|
31
32
|
@output.puts "</div>"
|
32
33
|
STDOUT.flush
|
33
34
|
end
|
34
35
|
|
35
36
|
def spec_started(name)
|
36
37
|
@current_spec = name
|
37
|
-
@
|
38
|
+
@current_spec_number += 1
|
38
39
|
STDOUT.flush
|
39
40
|
end
|
40
41
|
|
41
42
|
def spec_passed(name)
|
42
43
|
move_progress
|
43
|
-
@output.puts " <
|
44
|
+
@output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{escape(@current_spec)}</span></dd>"
|
44
45
|
STDOUT.flush
|
45
46
|
end
|
46
47
|
|
47
48
|
def spec_failed(name, counter, failure)
|
48
|
-
@output.puts " <script type=\"text/javascript\">
|
49
|
+
@output.puts " <script type=\"text/javascript\">makeRed('header');</script>"
|
50
|
+
@output.puts " <script type=\"text/javascript\">makeRed('context_#{@current_context_number}');</script>"
|
49
51
|
move_progress
|
50
|
-
@output.puts " <
|
51
|
-
@output.puts " <
|
52
|
+
@output.puts " <dd class=\"spec failed\">"
|
53
|
+
@output.puts " <span class=\"failed_spec_name\">#{escape(@current_spec)}</span>"
|
52
54
|
@output.puts " <div class=\"failure\" id=\"failure_#{counter}\">"
|
53
55
|
@output.puts " <div class=\"message\"><pre>#{escape(failure.exception.message)}</pre></div>" unless failure.exception.nil?
|
54
56
|
@output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(failure.exception.backtrace)}</pre></div>" unless failure.exception.nil?
|
57
|
+
extra_failure_content
|
55
58
|
@output.puts " </div>"
|
56
|
-
@output.puts " </
|
59
|
+
@output.puts " </dd>"
|
57
60
|
STDOUT.flush
|
58
61
|
end
|
59
62
|
|
63
|
+
# Override this method if you wish to output extra HTML for a failed spec. For example, you
|
64
|
+
# could output links to images or other files produced during the specs. Example:
|
65
|
+
#
|
66
|
+
#
|
67
|
+
def extra_failure_content
|
68
|
+
end
|
69
|
+
|
60
70
|
def move_progress
|
61
|
-
percent_done = @spec_count == 0 ? 100.0 : (@
|
71
|
+
percent_done = @spec_count == 0 ? 100.0 : (@current_spec_number.to_f / @spec_count.to_f * 1000).to_i / 10.0
|
62
72
|
@output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
|
63
73
|
end
|
64
74
|
|
65
75
|
def escape(string)
|
66
76
|
string.gsub(/&/n, '&').gsub(/\"/n, '"').gsub(/>/n, '>').gsub(/</n, '<')
|
67
77
|
end
|
68
|
-
|
78
|
+
|
69
79
|
def dump_failure(counter, failure)
|
70
80
|
end
|
71
81
|
|
72
82
|
def dump_summary(duration, spec_count, failure_count)
|
83
|
+
if @dry_run
|
84
|
+
totals = "This was a dry-run"
|
85
|
+
else
|
86
|
+
totals = "#{spec_count} specification#{'s' unless spec_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
|
87
|
+
end
|
88
|
+
@output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
|
89
|
+
@output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
|
90
|
+
@output.puts "</div>"
|
73
91
|
@output.puts "</body>"
|
74
92
|
@output.puts "</html>"
|
75
93
|
STDOUT.flush
|
76
94
|
end
|
77
|
-
|
78
|
-
|
79
|
-
GREEN_BACKGROUND = '#659D32'
|
80
|
-
|
81
|
-
HEADER = <<-HEADER
|
95
|
+
|
96
|
+
@@header = <<-HEADER
|
82
97
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
83
|
-
<!DOCTYPE html
|
98
|
+
<!DOCTYPE html
|
84
99
|
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
85
100
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
86
101
|
|
@@ -91,98 +106,103 @@ module Spec
|
|
91
106
|
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
92
107
|
<script type="text/javascript">
|
93
108
|
function moveProgressBar(percentDone) {
|
94
|
-
document.getElementById("
|
109
|
+
document.getElementById("header").style.width = percentDone +"%";
|
95
110
|
}
|
96
|
-
function
|
97
|
-
document.getElementById(
|
111
|
+
function makeRed(element_id) {
|
112
|
+
document.getElementById(element_id).style.background = '#C40D0D';
|
98
113
|
}
|
99
114
|
</script>
|
100
115
|
<style type="text/css">
|
101
116
|
body {
|
102
|
-
|
103
|
-
|
104
|
-
width: 85%;
|
117
|
+
margin: 0; padding: 0;
|
118
|
+
background: #fff;
|
105
119
|
}
|
106
120
|
|
107
|
-
#
|
108
|
-
background
|
109
|
-
border-bottom: 1px solid gray;
|
110
|
-
border-right: 1px solid gray;
|
121
|
+
#header {
|
122
|
+
background: #65C400; color: #fff;
|
111
123
|
}
|
112
124
|
|
113
|
-
|
114
|
-
|
115
|
-
|
125
|
+
h1 {
|
126
|
+
margin: 0 0 10px;
|
127
|
+
padding: 10px;
|
128
|
+
font: bold 18px "Lucida Grande", Helvetica, sans-serif;
|
116
129
|
}
|
117
130
|
|
118
|
-
|
119
|
-
padding:
|
120
|
-
|
121
|
-
|
131
|
+
#summary {
|
132
|
+
margin: 0; padding: 5px 10px;
|
133
|
+
font: bold 10px "Lucida Grande", Helvetica, sans-serif;
|
134
|
+
text-align: right;
|
135
|
+
position: absolute;
|
136
|
+
top: 0px;
|
137
|
+
right: 0px;
|
122
138
|
}
|
123
139
|
|
124
|
-
|
125
|
-
|
140
|
+
#summary p {
|
141
|
+
margin: 0 0 2px;
|
126
142
|
}
|
127
143
|
|
128
|
-
|
129
|
-
|
130
|
-
margin: 0;
|
131
|
-
border: 1px solid #fff;
|
144
|
+
#summary #totals {
|
145
|
+
font-size: 14px;
|
132
146
|
}
|
133
147
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
color: #589CCF;
|
148
|
+
.context {
|
149
|
+
margin: 0 10px 5px;
|
150
|
+
background: #fff;
|
138
151
|
}
|
139
152
|
|
140
|
-
|
141
|
-
|
142
|
-
|
153
|
+
dl {
|
154
|
+
margin: 0; padding: 0 0 5px;
|
155
|
+
font: normal 11px "Lucida Grande", Helvetica, sans-serif;
|
143
156
|
}
|
144
157
|
|
145
|
-
|
158
|
+
dt {
|
159
|
+
padding: 3px;
|
160
|
+
background: #65C400;
|
161
|
+
color: #fff;
|
146
162
|
font-weight: bold;
|
147
|
-
color: #EEB4B4;
|
148
163
|
}
|
149
164
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
padding: 1px 4px;
|
165
|
+
dd {
|
166
|
+
margin: 5px 0 5px 5px;
|
167
|
+
padding: 3px 3px 3px 18px;
|
154
168
|
}
|
155
169
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
color: #
|
160
|
-
padding: 2px 4px;
|
170
|
+
dd.spec.passed {
|
171
|
+
border-left: 5px solid #65C400;
|
172
|
+
border-bottom: 1px solid #65C400;
|
173
|
+
background: #DBFFB4; color: #3D7700;
|
161
174
|
}
|
162
175
|
|
163
|
-
|
164
|
-
|
165
|
-
|
176
|
+
dd.spec.failed {
|
177
|
+
border-left: 5px solid #C20000;
|
178
|
+
border-bottom: 1px solid #C20000;
|
179
|
+
color: #C20000; background: #FFFBD3;
|
166
180
|
}
|
167
181
|
|
168
182
|
div.backtrace {
|
169
|
-
color: #
|
183
|
+
color: #000;
|
184
|
+
font-size: 12px;
|
170
185
|
}
|
171
186
|
|
172
|
-
|
173
|
-
color: #
|
187
|
+
a {
|
188
|
+
color: #BE5C00;
|
174
189
|
}
|
175
|
-
|
176
190
|
</style>
|
177
191
|
</head>
|
178
192
|
<body>
|
179
193
|
|
180
|
-
<div id="
|
181
|
-
<
|
194
|
+
<div id="header">
|
195
|
+
<h1>RSpec Results</h1>
|
196
|
+
|
197
|
+
<div id="summary">
|
198
|
+
<p id="duration"> </p>
|
199
|
+
<p id="totals"> </p>
|
200
|
+
</div>
|
182
201
|
</div>
|
183
202
|
|
203
|
+
<div id="results">
|
184
204
|
HEADER
|
185
205
|
end
|
186
206
|
end
|
187
207
|
end
|
188
|
-
end
|
208
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
begin
|
2
|
+
require 'rubygems'
|
3
|
+
require 'heckle'
|
4
|
+
rescue LoadError ; raise "You must gem install heckle to use --heckle" ; end
|
5
|
+
|
6
|
+
module Spec
|
7
|
+
module Runner
|
8
|
+
# Creates a new Heckler configured to heckle all methods in the classes
|
9
|
+
# whose name matches +filter+
|
10
|
+
class HeckleRunner
|
11
|
+
def initialize(filter, heckle_class=Heckler)
|
12
|
+
@filter = filter
|
13
|
+
@heckle_class = heckle_class
|
14
|
+
end
|
15
|
+
|
16
|
+
# Runs all the contexts held by +context_runner+ once for each of the
|
17
|
+
# methods in the matched classes.
|
18
|
+
def heckle_with(context_runner)
|
19
|
+
if @filter =~ /(.*)[#\.](.*)/
|
20
|
+
heckle = @heckle_class.new($1, $2, context_runner)
|
21
|
+
heckle.validate
|
22
|
+
else
|
23
|
+
heckle_module
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def heckle_module
|
28
|
+
filter = /^#{@filter}/
|
29
|
+
classes = []
|
30
|
+
ObjectSpace.each_object(Class) do |klass|
|
31
|
+
classes << klass if klass.name =~ filter
|
32
|
+
end
|
33
|
+
|
34
|
+
classes.each do |klass|
|
35
|
+
klass.instance_methods(false).each do |method_name|
|
36
|
+
heckle = @heckle_class.new(klass.name, method_name, context_runner)
|
37
|
+
heckle.validate
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Heckler < Heckle::Base
|
44
|
+
def initialize(klass_name, method_name, context_runner)
|
45
|
+
super(klass_name, method_name)
|
46
|
+
@context_runner = context_runner
|
47
|
+
end
|
48
|
+
|
49
|
+
def tests_pass?
|
50
|
+
failure_count = @context_runner.run(false)
|
51
|
+
failure_count == 0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -13,7 +13,7 @@ module Spec
|
|
13
13
|
options = parse(args, err, out, warn_if_no_files)
|
14
14
|
|
15
15
|
formatter = options.formatter_type.new(options.out, options.dry_run, options.colour)
|
16
|
-
reporter = Reporter.new(formatter, options.backtrace_tweaker)
|
16
|
+
options.reporter = Reporter.new(formatter, options.backtrace_tweaker)
|
17
17
|
|
18
18
|
# this doesn't really belong here.
|
19
19
|
# it should, but the way things are coupled, it doesn't
|
@@ -21,7 +21,7 @@ module Spec
|
|
21
21
|
Spec::Expectations::Should::Base.differ = options.differ_class.new(options.diff_format, options.context_lines, options.colour)
|
22
22
|
end
|
23
23
|
|
24
|
-
ContextRunner.new(
|
24
|
+
ContextRunner.new(options)
|
25
25
|
end
|
26
26
|
|
27
27
|
def parse(args, err, out, warn_if_no_files)
|
@@ -74,7 +74,7 @@ module Spec
|
|
74
74
|
opts.on("-s", "--spec SPECIFICATION_NAME", "Execute context or specification with matching name") do |spec_name|
|
75
75
|
options.spec_name = spec_name
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
opts.on("-l", "--line LINE_NUMBER", Integer, "Execute context or specification at given line") do |line_number|
|
79
79
|
options.line_number = line_number.to_i
|
80
80
|
end
|
@@ -110,11 +110,23 @@ module Spec
|
|
110
110
|
opts.on("-b", "--backtrace", "Output full backtrace") do
|
111
111
|
options.backtrace_tweaker = NoisyBacktraceTweaker.new
|
112
112
|
end
|
113
|
+
|
114
|
+
opts.on("-H", "--heckle CODE", "If all specs pass, this will run your specs many times, mutating",
|
115
|
+
"the specced code a little each time. The intent is that specs",
|
116
|
+
"*should* fail, and RSpec will tell you if they don't.",
|
117
|
+
"CODE should be either Some::Module, Some::Class or Some::Fabulous#method}") do |heckle|
|
118
|
+
require 'spec/runner/heckle_runner'
|
119
|
+
options.heckle_runner = HeckleRunner.new(heckle)
|
120
|
+
end
|
113
121
|
|
114
122
|
opts.on("-d", "--dry-run", "Don't execute specs") do
|
115
123
|
options.dry_run = true
|
116
124
|
end
|
117
125
|
|
126
|
+
opts.on("-o", "--out OUTPUT_FILE", "Path to output file (defaults to STDOUT)") do |outfile|
|
127
|
+
options.out = File.new(outfile, 'w')
|
128
|
+
end
|
129
|
+
|
118
130
|
opts.on("-v", "--version", "Show version") do
|
119
131
|
out.puts ::Spec::VERSION::DESCRIPTION
|
120
132
|
exit if out == $stdout
|
data/lib/spec/runner/reporter.rb
CHANGED
@@ -4,14 +4,10 @@ module Spec
|
|
4
4
|
|
5
5
|
def initialize(formatter, backtrace_tweaker)
|
6
6
|
@formatter = formatter
|
7
|
-
@context_names = []
|
8
|
-
@failures = []
|
9
|
-
@spec_names = []
|
10
7
|
@backtrace_tweaker = backtrace_tweaker
|
11
|
-
|
12
|
-
@end_time = nil
|
8
|
+
clear!
|
13
9
|
end
|
14
|
-
|
10
|
+
|
15
11
|
def add_context(name)
|
16
12
|
#TODO - @context_names.empty? tells the formatter whether this is the first context or not - that's a little slippery
|
17
13
|
@formatter.add_context(name, @context_names.empty?)
|
@@ -31,8 +27,9 @@ module Spec
|
|
31
27
|
spec_failed(name, Failure.new(@context_names.last, name, error))
|
32
28
|
end
|
33
29
|
end
|
34
|
-
|
30
|
+
|
35
31
|
def start(number_of_specs)
|
32
|
+
clear!
|
36
33
|
@start_time = Time.new
|
37
34
|
@formatter.start(number_of_specs)
|
38
35
|
end
|
@@ -51,6 +48,14 @@ module Spec
|
|
51
48
|
|
52
49
|
private
|
53
50
|
|
51
|
+
def clear!
|
52
|
+
@context_names = []
|
53
|
+
@failures = []
|
54
|
+
@spec_names = []
|
55
|
+
@start_time = nil
|
56
|
+
@end_time = nil
|
57
|
+
end
|
58
|
+
|
54
59
|
def dump_failures
|
55
60
|
return if @failures.empty?
|
56
61
|
@failures.inject(1) do |index, failure|
|
@@ -97,4 +102,4 @@ module Spec
|
|
97
102
|
end
|
98
103
|
end
|
99
104
|
end
|
100
|
-
end
|
105
|
+
end
|
@@ -1,70 +1,95 @@
|
|
1
1
|
module Spec
|
2
2
|
module Runner
|
3
3
|
class Specification
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
module ClassMethods
|
5
|
+
attr_accessor :current
|
6
|
+
protected :current=
|
7
|
+
|
8
|
+
callback_events :before_setup, :after_teardown
|
9
9
|
end
|
10
|
-
|
10
|
+
extend ClassMethods
|
11
|
+
|
12
|
+
attr_reader :command
|
13
|
+
callback_events :before_setup, :after_teardown
|
14
|
+
|
11
15
|
def initialize(name, opts={}, &block)
|
12
16
|
@from = caller(0)[3]
|
13
17
|
@name = name
|
14
18
|
@options = opts
|
15
|
-
@
|
16
|
-
@listeners = []
|
19
|
+
@command = block
|
17
20
|
end
|
18
21
|
|
19
|
-
def run(reporter
|
20
|
-
reporter.spec_started(@name)
|
22
|
+
def run(reporter, setup_block, teardown_block, dry_run, execution_context)
|
23
|
+
reporter.spec_started(@name) if reporter
|
21
24
|
return reporter.spec_finished(@name) if dry_run
|
22
|
-
@@current_spec = self
|
23
|
-
execution_context = execution_context || ::Spec::Runner::ExecutionContext.new(self)
|
24
|
-
errors = []
|
25
|
-
begin
|
26
|
-
execution_context.instance_exec(&setup_block) unless setup_block.nil?
|
27
|
-
setup_ok = true
|
28
|
-
execution_context.instance_exec(&@block)
|
29
|
-
spec_ok = true
|
30
|
-
rescue => e
|
31
|
-
errors << e
|
32
|
-
end
|
33
25
|
|
26
|
+
errors = []
|
34
27
|
begin
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
errors
|
28
|
+
set_current
|
29
|
+
setup_ok = setup_spec(execution_context, errors, &setup_block)
|
30
|
+
spec_ok = execute_spec(execution_context, errors) if setup_ok
|
31
|
+
teardown_ok = teardown_spec(execution_context, errors, &teardown_block)
|
39
32
|
ensure
|
40
|
-
|
41
|
-
@@current_spec = nil
|
33
|
+
clear_current
|
42
34
|
end
|
43
|
-
|
44
|
-
SpecShouldRaiseHandler.new(@from, @options).handle(errors)
|
45
35
|
|
46
|
-
|
36
|
+
SpecShouldRaiseHandler.new(@from, @options).handle(errors)
|
37
|
+
reporter.spec_finished(@name, errors.first, failure_location(setup_ok, spec_ok, teardown_ok)) if reporter
|
47
38
|
end
|
48
39
|
|
49
40
|
def matches_matcher?(matcher)
|
50
41
|
matcher.matches? @name
|
51
42
|
end
|
52
43
|
|
53
|
-
|
54
|
-
|
44
|
+
private
|
45
|
+
def setup_spec(execution_context, errors, &setup_block)
|
46
|
+
notify_before_setup(errors)
|
47
|
+
execution_context.instance_eval(&setup_block) if setup_block
|
48
|
+
return errors.empty?
|
49
|
+
rescue => e
|
50
|
+
errors << e
|
51
|
+
return false
|
55
52
|
end
|
56
53
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
54
|
+
def execute_spec(execution_context, errors)
|
55
|
+
execution_context.instance_eval(&command)
|
56
|
+
return true
|
57
|
+
rescue => e
|
58
|
+
errors << e
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
def teardown_spec(execution_context, errors, &teardown_block)
|
63
|
+
execution_context.instance_eval(&teardown_block) if teardown_block
|
64
|
+
notify_after_teardown(errors)
|
65
|
+
return errors.empty?
|
66
|
+
rescue => e
|
67
|
+
errors << e
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
def notify_before_setup(errors)
|
72
|
+
self.class.send(:notify_callbacks, :before_setup, self, &append_errors(errors))
|
73
|
+
notify_callbacks(:before_setup, self, &append_errors(errors))
|
74
|
+
end
|
75
|
+
|
76
|
+
def notify_after_teardown(errors)
|
77
|
+
notify_callbacks(:after_teardown, self, &append_errors(errors))
|
78
|
+
self.class.send(:notify_callbacks, :after_teardown, self, &append_errors(errors))
|
79
|
+
end
|
80
|
+
|
81
|
+
def append_errors(errors)
|
82
|
+
proc {|error| errors << error}
|
83
|
+
end
|
84
|
+
|
85
|
+
def set_current
|
86
|
+
self.class.send(:current=, self)
|
87
|
+
end
|
88
|
+
|
89
|
+
def clear_current
|
90
|
+
self.class.send(:current=, nil)
|
65
91
|
end
|
66
92
|
|
67
|
-
private
|
68
93
|
def failure_location(setup_ok, spec_ok, teardown_ok)
|
69
94
|
return 'setup' unless setup_ok
|
70
95
|
return @name unless spec_ok
|
@@ -72,4 +97,4 @@ module Spec
|
|
72
97
|
end
|
73
98
|
end
|
74
99
|
end
|
75
|
-
end
|
100
|
+
end
|
data/lib/spec/runner.rb
CHANGED
@@ -6,10 +6,10 @@ require 'spec/runner/execution_context'
|
|
6
6
|
require 'spec/runner/context_runner'
|
7
7
|
require 'spec/runner/option_parser'
|
8
8
|
require 'spec/runner/command_line'
|
9
|
+
require 'spec/runner/drb_command_line'
|
9
10
|
require 'spec/runner/backtrace_tweaker'
|
10
11
|
require 'spec/runner/reporter'
|
11
12
|
require 'spec/runner/spec_matcher'
|
12
13
|
require 'spec/runner/extensions/kernel'
|
13
|
-
require 'spec/runner/extensions/object'
|
14
14
|
require 'spec/runner/spec_should_raise_handler'
|
15
15
|
require 'spec/runner/spec_parser'
|
data/lib/spec/version.rb
CHANGED
@@ -3,13 +3,14 @@ module Spec
|
|
3
3
|
unless defined? MAJOR
|
4
4
|
MAJOR = 0
|
5
5
|
MINOR = 7
|
6
|
-
TINY =
|
7
|
-
|
8
|
-
|
6
|
+
TINY = 5
|
7
|
+
MINISCULE = 1
|
8
|
+
# RANDOM_TOKEN: 0.0543628986724853
|
9
|
+
REV = "$LastChangedRevision: 1395 $".match(/LastChangedRevision: (\d+)/)[1]
|
9
10
|
|
10
|
-
STRING = [MAJOR, MINOR, TINY].join('.')
|
11
|
+
STRING = [MAJOR, MINOR, TINY, MINISCULE].join('.')
|
11
12
|
FULL_VERSION = "#{STRING} (r#{REV})"
|
12
|
-
TAG = "REL_" + [MAJOR, MINOR, TINY].join('_')
|
13
|
+
TAG = "REL_" + [MAJOR, MINOR, TINY, MINISCULE].join('_')
|
13
14
|
|
14
15
|
NAME = "RSpec"
|
15
16
|
URL = "http://rspec.rubyforge.org/"
|