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.
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'