rspec 0.7.2 → 0.7.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/"
|