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.
Files changed (70) hide show
  1. data/CHANGES +72 -1
  2. data/EXAMPLES.rd +6 -0
  3. data/README +27 -6
  4. data/Rakefile +32 -81
  5. data/bin/drbspec +3 -0
  6. data/bin/spec +2 -3
  7. data/examples/file_accessor_spec.rb +1 -1
  8. data/examples/greeter_spec.rb +30 -0
  9. data/examples/helper_method_example.rb +1 -1
  10. data/examples/io_processor_spec.rb +1 -1
  11. data/examples/mocking_example.rb +1 -1
  12. data/examples/partial_mock_example.rb +1 -1
  13. data/examples/predicate_example.rb +1 -1
  14. data/examples/setup_teardown_example.rb +34 -0
  15. data/examples/spec_helper.rb +1 -0
  16. data/examples/stack_spec.rb +1 -1
  17. data/examples/stubbing_example.rb +1 -1
  18. data/examples/test_case_spec.rb +1 -1
  19. data/lib/spec/callback/callback_container.rb +60 -0
  20. data/lib/spec/callback/extensions/module.rb +24 -0
  21. data/lib/spec/callback/extensions/object.rb +33 -0
  22. data/lib/spec/callback.rb +3 -0
  23. data/lib/spec/expectations/diff.rb +10 -14
  24. data/lib/spec/expectations/extensions/numeric.rb +17 -3
  25. data/lib/spec/expectations/extensions/object.rb +145 -0
  26. data/lib/spec/expectations/extensions/proc.rb +57 -0
  27. data/lib/spec/expectations/extensions/string.rb +22 -0
  28. data/lib/spec/expectations/extensions.rb +2 -2
  29. data/lib/spec/expectations/message_builder.rb +13 -0
  30. data/lib/spec/expectations/should/base.rb +29 -10
  31. data/lib/spec/expectations/should/change.rb +69 -0
  32. data/lib/spec/expectations/should/have.rb +94 -37
  33. data/lib/spec/expectations/should/not.rb +6 -2
  34. data/lib/spec/expectations/should/should.rb +9 -5
  35. data/lib/spec/expectations/should.rb +1 -0
  36. data/lib/spec/expectations/sugar.rb +2 -2
  37. data/lib/spec/expectations.rb +28 -0
  38. data/lib/spec/mocks/error_generator.rb +23 -12
  39. data/lib/spec/mocks/message_expectation.rb +18 -15
  40. data/lib/spec/mocks/mock_handler.rb +10 -9
  41. data/lib/spec/mocks/mock_methods.rb +1 -1
  42. data/lib/spec/rake/spectask.rb +8 -2
  43. data/lib/spec/runner/backtrace_tweaker.rb +34 -25
  44. data/lib/spec/runner/context.rb +56 -7
  45. data/lib/spec/runner/context_eval.rb +33 -3
  46. data/lib/spec/runner/context_runner.rb +24 -11
  47. data/lib/spec/runner/drb_command_line.rb +21 -0
  48. data/lib/spec/runner/execution_context.rb +1 -0
  49. data/lib/spec/runner/extensions/kernel.rb +2 -0
  50. data/lib/spec/runner/extensions/object.rb +26 -18
  51. data/lib/spec/runner/formatter/base_text_formatter.rb +1 -1
  52. data/lib/spec/runner/formatter/html_formatter.rb +94 -74
  53. data/lib/spec/runner/heckle_runner.rb +55 -0
  54. data/lib/spec/runner/option_parser.rb +15 -3
  55. data/lib/spec/runner/reporter.rb +13 -8
  56. data/lib/spec/runner/specification.rb +67 -42
  57. data/lib/spec/runner.rb +1 -1
  58. data/lib/spec/version.rb +6 -5
  59. data/lib/spec.rb +1 -0
  60. metadata +20 -19
  61. data/lib/spec/expectations/extensions/inspect_for_expectation_not_met_error.rb +0 -14
  62. data/lib/spec/expectations/extensions/symbol.rb +0 -5
  63. data/vendor/selenium/README.txt +0 -23
  64. data/vendor/selenium/find_rspecs_home_page.rb +0 -23
  65. data/vendor/selenium/rspec_selenium.rb +0 -33
  66. data/vendor/selenium/start_browser_once.patch +0 -65
  67. data/vendor/watir/README.txt +0 -32
  68. data/vendor/watir/find_rspecs_home_page.rb +0 -21
  69. data/vendor/watir/find_rspecs_home_page.txt +0 -15
  70. data/vendor/watir/rspec_watir.rb +0 -45
@@ -1,21 +1,29 @@
1
- # http://eigenclass.org/hiki.rb?bounded+space+instance_exec
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
- module InstanceExecHelper; end
4
- include InstanceExecHelper
5
- def instance_exec(*args, &block)
6
- begin
7
- old_critical, Thread.critical = Thread.critical, true
8
- n = 0
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
@@ -92,7 +92,7 @@ module Spec
92
92
  protected
93
93
 
94
94
  def backtrace_line(line)
95
- line
95
+ line.sub(/\A([^:]+:\d+)$/, '\\1:')
96
96
  end
97
97
 
98
98
  def colour(text, colour_code)
@@ -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
- @current_count = 0
8
- @spec_count = 0
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 HEADER
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 " </ul>"
21
+ @output.puts " </dl>"
21
22
  @output.puts "</div>"
22
23
  end
23
24
  @output.puts "<div class=\"context\">"
24
- @output.puts " <ul>"
25
- @output.puts " <li class=\"context_name\">#{name}</li>"
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 " </ul>"
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
- @current_count += 1
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 " <li class=\"spec passed\"><div class=\"passed_spec_name\">#{escape(@current_spec)}</div></li>"
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\">makeProgressbarRed();</script>"
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 " <li class=\"spec failed\">"
51
- @output.puts " <div class=\"failed_spec_name\">#{escape(@current_spec)}</div>"
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 " </li>"
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 : (@current_count.to_f / @spec_count.to_f * 1000).to_i / 10.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, '&amp;').gsub(/\"/n, '&quot;').gsub(/>/n, '&gt;').gsub(/</n, '&lt;')
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
- RED_BACKGROUND = '#CD0000'
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("progress-bar").style.width = percentDone +"%";
109
+ document.getElementById("header").style.width = percentDone +"%";
95
110
  }
96
- function makeProgressbarRed() {
97
- document.getElementById('progress-bar').style.background = '#{RED_BACKGROUND}';
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
- font-size: 9pt;
103
- font-family: verdana, arial, helvetica;
104
- width: 85%;
117
+ margin: 0; padding: 0;
118
+ background: #fff;
105
119
  }
106
120
 
107
- #progress-bar-bg {
108
- background-color: #C9C9C9;
109
- border-bottom: 1px solid gray;
110
- border-right: 1px solid gray;
121
+ #header {
122
+ background: #65C400; color: #fff;
111
123
  }
112
124
 
113
- #progress-bar {
114
- background-color: #{GREEN_BACKGROUND};
115
- width: 0px;
125
+ h1 {
126
+ margin: 0 0 10px;
127
+ padding: 10px;
128
+ font: bold 18px "Lucida Grande", Helvetica, sans-serif;
116
129
  }
117
130
 
118
- div.context {
119
- padding: 0px;
120
- background: #fff;
121
- margin-top: 0px;
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
- ul {
125
- padding-left: 0px;
140
+ #summary p {
141
+ margin: 0 0 2px;
126
142
  }
127
143
 
128
- li {
129
- list-style-type: none;
130
- margin: 0;
131
- border: 1px solid #fff;
144
+ #summary #totals {
145
+ font-size: 14px;
132
146
  }
133
147
 
134
- li.context_name {
135
- font-size: 1.3em;
136
- font-weight: bold;
137
- color: #589CCF;
148
+ .context {
149
+ margin: 0 10px 5px;
150
+ background: #fff;
138
151
  }
139
152
 
140
- div.passed_spec_name {
141
- font-weight: bold;
142
- color: #324F17;
153
+ dl {
154
+ margin: 0; padding: 0 0 5px;
155
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
143
156
  }
144
157
 
145
- div.failed_spec_name {
158
+ dt {
159
+ padding: 3px;
160
+ background: #65C400;
161
+ color: #fff;
146
162
  font-weight: bold;
147
- color: #EEB4B4;
148
163
  }
149
164
 
150
- li.passed {
151
- display: block;
152
- background: #659D32;
153
- padding: 1px 4px;
165
+ dd {
166
+ margin: 5px 0 5px 5px;
167
+ padding: 3px 3px 3px 18px;
154
168
  }
155
169
 
156
- li.failed {
157
- display: block;
158
- background: #CD0000;
159
- color: #000;
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
- li.failed .failure {
164
- font-weight: normal;
165
- font-size: 9pt;
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: #fff;
183
+ color: #000;
184
+ font-size: 12px;
170
185
  }
171
186
 
172
- div.backtrace a {
173
- color: #fff;
187
+ a {
188
+ color: #BE5C00;
174
189
  }
175
-
176
190
  </style>
177
191
  </head>
178
192
  <body>
179
193
 
180
- <div id="progress-bar-bg">
181
- <div id="progress-bar">&nbsp;</div>
194
+ <div id="header">
195
+ <h1>RSpec Results</h1>
196
+
197
+ <div id="summary">
198
+ <p id="duration">&nbsp;</p>
199
+ <p id="totals">&nbsp;</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(reporter, options.dry_run, options.spec_name)
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
@@ -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
- @start_time = nil
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
- @@current_spec = nil
6
-
7
- def self.add_listener listener
8
- @@current_spec.add_listener listener unless @@current_spec.nil?
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
- @block = block
16
- @listeners = []
19
+ @command = block
17
20
  end
18
21
 
19
- def run(reporter=nil, setup_block=nil, teardown_block=nil, dry_run=false, execution_context=nil)
20
- reporter.spec_started(@name) unless reporter.nil?
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
- execution_context.instance_exec(&teardown_block) unless teardown_block.nil?
36
- teardown_ok = true
37
- rescue => e
38
- errors << e
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
- notify_after_teardown errors
41
- @@current_spec = nil
33
+ clear_current
42
34
  end
43
-
44
- SpecShouldRaiseHandler.new(@from, @options).handle(errors)
45
35
 
46
- reporter.spec_finished(@name, errors.first, failure_location(setup_ok, spec_ok, teardown_ok)) unless reporter.nil?
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
- def add_listener listener
54
- @listeners << listener
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 notify_after_teardown errors
58
- @listeners.each do |listener|
59
- begin
60
- listener.spec_finished(self) if listener.respond_to?(:spec_finished)
61
- rescue => e
62
- errors << e
63
- end
64
- end
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 = 2
7
- # RANDOM_TOKEN: 0.868668446220024
8
- REV = "$LastChangedRevision: 1095 $".match(/LastChangedRevision: (\d+)/)[1]
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/"
data/lib/spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'spec/version'
2
+ require 'spec/callback'
2
3
  require 'spec/expectations'
3
4
  require 'spec/mocks'
4
5
  require 'spec/runner'