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,7 +1,7 @@
1
1
  module Spec
2
2
  module Expectations
3
3
  # This module adds syntactic sugar that allows usage of should_* instead of should.*
4
- module UnderscoreSugar
4
+ module UnderscoreSugar # :nodoc:
5
5
  def handle_underscores_for_rspec!
6
6
  original_method_missing = instance_method(:method_missing)
7
7
  class_eval do
@@ -14,7 +14,7 @@ module Spec
14
14
  return Spec::Expectations::Should::Should.new(self).__send__(__strip_should(sym), *args, &block)
15
15
  end
16
16
 
17
- def __strip_should sym
17
+ def __strip_should(sym) # :nodoc
18
18
  sym.to_s[7..-1]
19
19
  end
20
20
  end
@@ -2,3 +2,31 @@ require 'spec/expectations/sugar'
2
2
  require 'spec/expectations/errors'
3
3
  require 'spec/expectations/extensions'
4
4
  require 'spec/expectations/should'
5
+ require 'spec/expectations/message_builder'
6
+
7
+ module Spec
8
+ # See Spec::Expectations::ObjectExpectations for expectations that
9
+ # are available on all objects.
10
+ #
11
+ # See Spec::Expectations::ProcExpectations for expectations that
12
+ # are available on Proc objects.
13
+ #
14
+ # See Spec::Expectations::NumericExpectations for expectations that
15
+ # are available on Numeric objects.
16
+ module Expectations
17
+ class << self
18
+ # raises a Spec::Expectations::ExpecationNotMetError with message
19
+ def fail_with(message)
20
+ Kernel::raise(Spec::Expectations::ExpectationNotMetError.new(message))
21
+ end
22
+
23
+ def build_message(actual, expectation, expected)
24
+ message_builder.build_message(actual, expectation, expected)
25
+ end
26
+
27
+ def message_builder #:nodoc:
28
+ @message_builder ||= MessageBuilder.new
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,7 +3,7 @@ module Spec
3
3
  class ErrorGenerator
4
4
  attr_writer :opts
5
5
 
6
- def initialize target, name
6
+ def initialize(target, name)
7
7
  @target = target
8
8
  @name = name
9
9
  end
@@ -12,27 +12,34 @@ module Spec
12
12
  @opts ||= {}
13
13
  end
14
14
 
15
- def raise_unexpected_message_error sym, *args
15
+ def raise_unexpected_message_error(sym, *args)
16
16
  __raise "#{intro} received unexpected message :#{sym}#{arg_message(*args)}"
17
17
  end
18
18
 
19
- def raise_expectation_error sym, expected_received_count, actual_received_count, *args
19
+ def raise_unexpected_message_args_error(expectation, *args)
20
+ #this is either :no_args or an Array
21
+ expected_args = (expectation.expected_args == :no_args ? "(no args)" : format_args(*expectation.expected_args))
22
+ actual_args = args.empty? ? "(no args)" : format_args(*args)
23
+ __raise "#{intro} expected #{expectation.sym.inspect} with #{expected_args} but received it with #{actual_args}"
24
+ end
25
+
26
+ def raise_expectation_error(sym, expected_received_count, actual_received_count, *args)
20
27
  __raise "#{intro} expected :#{sym}#{arg_message(*args)} #{count_message(expected_received_count)}, but received it #{count_message(actual_received_count)}"
21
28
  end
22
29
 
23
- def raise_out_of_order_error sym
30
+ def raise_out_of_order_error(sym)
24
31
  __raise "#{intro} received :#{sym} out of order"
25
32
  end
26
33
 
27
- def raise_block_failed_error sym, detail
34
+ def raise_block_failed_error(sym, detail)
28
35
  __raise "#{intro} received :#{sym} but passed block failed with: #{detail}"
29
36
  end
30
37
 
31
- def raise_missing_block_error args_to_yield
38
+ def raise_missing_block_error(args_to_yield)
32
39
  __raise "#{intro} asked to yield |#{arg_list(*args_to_yield)}| but no block was passed"
33
40
  end
34
41
 
35
- def raise_wrong_arity_error args_to_yield, arity
42
+ def raise_wrong_arity_error(args_to_yield, arity)
36
43
  __raise "#{intro} yielded |#{arg_list(*args_to_yield)}| to block with arity of #{arity}"
37
44
  end
38
45
 
@@ -41,15 +48,19 @@ module Spec
41
48
  @name ? "Mock '#{@name}'" : @target.to_s
42
49
  end
43
50
 
44
- def __raise message
51
+ def __raise(message)
45
52
  message = opts[:message] unless opts[:message].nil?
46
53
  Kernel::raise(Spec::Mocks::MockExpectationError, message)
47
54
  end
48
55
 
49
- def arg_message *args
50
- return "" if [:any_args] == args
51
- return if args.empty?
52
- " with [" + arg_list(*args) + "]"
56
+ def arg_message(*args)
57
+ " with " + format_args(*args)
58
+ end
59
+
60
+ def format_args(*args)
61
+ return "(no args)" if args.empty? || args == :no_args || args == [:no_args]
62
+ return "(any args)" if [:any_args] == args
63
+ "(" + arg_list(*args) + ")"
53
64
  end
54
65
 
55
66
  def arg_list(*args)
@@ -22,6 +22,10 @@ module Spec
22
22
  @at_most = nil
23
23
  @args_to_yield = nil
24
24
  end
25
+
26
+ def expected_args
27
+ @args_expectation.args
28
+ end
25
29
 
26
30
  def and_return(*values, &return_block)
27
31
  Kernel::raise AmbiguousReturnError unless @method_block.nil?
@@ -41,6 +45,14 @@ module Spec
41
45
  @exception_to_raise = exception
42
46
  end
43
47
 
48
+ def and_throw(symbol)
49
+ @symbol_to_throw = symbol
50
+ end
51
+
52
+ def and_yield(*args)
53
+ @args_to_yield = args
54
+ end
55
+
44
56
  def matches(sym, args)
45
57
  @sym == sym and @args_expectation.check_args(args)
46
58
  end
@@ -83,7 +95,7 @@ module Spec
83
95
  if block.nil?
84
96
  @error_generator.raise_missing_block_error @args_to_yield
85
97
  end
86
- if @args_to_yield.length != block.arity
98
+ if block.arity > -1 && @args_to_yield.length != block.arity
87
99
  @error_generator.raise_wrong_arity_error @args_to_yield, block.arity
88
100
  end
89
101
  block.call(*@args_to_yield)
@@ -125,7 +137,6 @@ module Spec
125
137
  end
126
138
  end
127
139
 
128
-
129
140
  def with(*args)
130
141
  @args_expectation = ArgumentExpectation.new(args)
131
142
  self
@@ -146,7 +157,7 @@ module Spec
146
157
  self
147
158
  end
148
159
 
149
- def set_expected_received_count relativity, n
160
+ def set_expected_received_count(relativity, n)
150
161
  @at_least = (relativity == :at_least)
151
162
  @at_most = (relativity == :at_most)
152
163
  @expected_received_count = 1 if n == :once
@@ -179,38 +190,30 @@ module Spec
179
190
  self
180
191
  end
181
192
 
182
- def and_throw(symbol)
183
- @symbol_to_throw = symbol
184
- end
185
-
186
- def and_yield(*args)
187
- @args_to_yield = args
188
- end
189
-
190
193
  def ordered
191
194
  @order_group.register(self)
192
195
  @ordered = true
193
196
  self
194
197
  end
195
198
 
196
- def negative_expectation_for? sym
199
+ def negative_expectation_for?(sym)
197
200
  return false
198
201
  end
199
202
  end
200
203
 
201
204
  class NegativeMessageExpectation < MessageExpectation
202
205
  def initialize(message, expectation_ordering, expected_from, sym, method_block)
203
- super message, expectation_ordering, expected_from, sym, method_block, 0
206
+ super(message, expectation_ordering, expected_from, sym, method_block, 0)
204
207
  end
205
208
 
206
- def negative_expectation_for? sym
209
+ def negative_expectation_for?(sym)
207
210
  return @sym == sym
208
211
  end
209
212
  end
210
213
 
211
214
  class MethodStub < BaseExpectation
212
215
  def initialize(message, expectation_ordering, expected_from, sym, method_block)
213
- super message, expectation_ordering, expected_from, sym, method_block, 0
216
+ super(message, expectation_ordering, expected_from, sym, method_block, 0)
214
217
  @expected_received_count = :any
215
218
  end
216
219
  end
@@ -41,14 +41,11 @@ module Spec
41
41
  end
42
42
 
43
43
  def __add expected_from, sym, block
44
- Runner::Specification.add_listener(self) if @options[:auto_verify]
44
+ current_spec = Runner::Specification.current
45
+ current_spec.after_teardown {verify} if current_spec && @options[:auto_verify]
45
46
  define_expected_method(sym)
46
47
  end
47
48
 
48
- def spec_finished spec
49
- verify
50
- end
51
-
52
49
  def define_expected_method(sym)
53
50
  if @target.respond_to?(sym) && !@proxied_methods[sym]
54
51
  @proxied_methods[sym] = @target.method(sym)
@@ -106,7 +103,7 @@ module Spec
106
103
  @proxied_methods.clear
107
104
  end
108
105
 
109
- def metaclass_eval str
106
+ def metaclass_eval(str)
110
107
  (class << @target; self; end).class_eval str
111
108
  end
112
109
 
@@ -135,15 +132,19 @@ module Spec
135
132
  if expectation = find_matching_expectation(sym, *args)
136
133
  expectation.invoke(args, block)
137
134
  elsif stub = find_matching_method_stub(sym)
138
- stub.invoke([], nil)
135
+ stub.invoke([], block)
139
136
  elsif expectation = find_almost_matching_expectation(sym, *args)
140
- raise_unexpected_message_error(sym, *args) unless has_negative_expectation?(sym) unless null_object?
137
+ raise_unexpected_message_args_error(expectation, *args) unless has_negative_expectation?(sym) unless null_object?
141
138
  else
142
139
  @target.send :method_missing, sym, *args, &block
143
140
  end
144
141
  end
145
142
 
146
- def raise_unexpected_message_error sym, *args
143
+ def raise_unexpected_message_args_error(expectation, *args)
144
+ @error_generator.raise_unexpected_message_args_error expectation, *args
145
+ end
146
+
147
+ def raise_unexpected_message_error(sym, *args)
147
148
  @error_generator.raise_unexpected_message_error sym, *args
148
149
  end
149
150
 
@@ -10,7 +10,7 @@ module Spec
10
10
  end
11
11
 
12
12
  def stub!(sym)
13
- __mock_handler.add_stub caller(1)[0], sym
13
+ __mock_handler.add_stub(caller(1)[0], sym)
14
14
  end
15
15
 
16
16
  def received_message?(sym, *args, &block)
@@ -12,8 +12,9 @@ module Spec
12
12
  #
13
13
  # Example:
14
14
  #
15
- # Rake::SpecTask.new do |t|
15
+ # Spec::Rake::SpecTask.new do |t|
16
16
  # t.warning = true
17
+ # t.rcov = true
17
18
  # end
18
19
  #
19
20
  # This will create a task that can be run with:
@@ -63,6 +64,11 @@ module Spec
63
64
 
64
65
  # A message to print to stdout when there are failures.
65
66
  attr_accessor :failure_message
67
+
68
+ # Whether or not to run specs via DRb. Setting this to true may
69
+ # run specs faster, especially in a Rails environment.
70
+ # Defaults to false
71
+ attr_accessor :drb
66
72
 
67
73
  # Explicitly define the list of spec files to be included in a
68
74
  # spec. +list+ is expected to be an array of file names (a
@@ -93,7 +99,7 @@ module Spec
93
99
  end
94
100
 
95
101
  def define
96
- spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/spec')
102
+ spec_script = File.expand_path(File.dirname(__FILE__) + '/../../../bin/' + (drb ? 'drbspec' : 'spec'))
97
103
 
98
104
  lib_path = @libs.join(File::PATH_SEPARATOR)
99
105
  actual_name = Hash === name ? name.keys.first : name
@@ -1,42 +1,51 @@
1
1
  module Spec
2
2
  module Runner
3
- class NoisyBacktraceTweaker
4
- def tweak_instance_exec_line line, spec_name
5
- line = line.split(':in')[0] + ":in `#{spec_name}'" if line.include?('__instance_exec')
6
- line
3
+ class BacktraceTweaker
4
+ def clean_up_double_slashes(line)
5
+ line.gsub!('//','/')
7
6
  end
7
+ end
8
+
9
+ class NoisyBacktraceTweaker < BacktraceTweaker
8
10
  def tweak_backtrace(error, spec_name)
9
11
  return if error.backtrace.nil?
10
- error.backtrace.collect! do |line|
11
- tweak_instance_exec_line line, spec_name
12
+ error.backtrace.each do |line|
13
+ clean_up_double_slashes(line)
12
14
  end
13
- error.backtrace.compact!
14
15
  end
15
16
  end
16
17
 
17
18
  # Tweaks raised Exceptions to mask noisy (unneeded) parts of the backtrace
18
- class QuietBacktraceTweaker
19
- def tweak_instance_exec_line line, spec_name
20
- line = line.split(':in')[0] if line.include?('__instance_exec')
21
- line
19
+ class QuietBacktraceTweaker < BacktraceTweaker
20
+ unless defined?(IGNORE_PATTERNS)
21
+ root_dir = File.expand_path(File.join(__FILE__, '..', '..', '..', '..'))
22
+ spec_files = Dir["#{root_dir}/lib/spec/*"].map do |path|
23
+ subpath = path[root_dir.length..-1]
24
+ /#{subpath}/
25
+ end
26
+ IGNORE_PATTERNS = spec_files + [
27
+ /\/lib\/ruby\//,
28
+ /bin\/spec:/,
29
+ /bin\/rcov:/,
30
+ /lib\/rspec_on_rails/,
31
+ /vendor\/rails/,
32
+ # TextMate's Ruby and RSpec plugins
33
+ /Ruby\.tmbundle\/Support\/tmruby.rb:/,
34
+ /RSpec\.tmbundle\/Support\/lib/,
35
+ /temp_textmate\./
36
+ ]
22
37
  end
38
+
23
39
  def tweak_backtrace(error, spec_name)
24
40
  return if error.backtrace.nil?
25
41
  error.backtrace.collect! do |line|
26
- line = tweak_instance_exec_line line, spec_name
27
- line = nil if line =~ /\/lib\/ruby\//
28
- line = nil if line =~ /\/lib\/spec\/expectations\//
29
- line = nil if line =~ /\/lib\/spec\/mocks\//
30
- line = nil if line =~ /\/lib\/spec\/rake\//
31
- line = nil if line =~ /\/lib\/spec\/runner\//
32
- line = nil if line =~ /bin\/spec:/
33
- line = nil if line =~ /bin\/rcov:/
34
- line = nil if line =~ /lib\/rspec_on_rails/
35
- line = nil if line =~ /script\/rails_spec/
36
- # TextMate's Ruby and RSpec plugins
37
- line = nil if line =~ /Ruby\.tmbundle\/Support\/tmruby.rb:/
38
- line = nil if line =~ /RSpec\.tmbundle\/Support\/lib/
39
- line = nil if line =~ /temp_textmate\./
42
+ clean_up_double_slashes(line)
43
+ IGNORE_PATTERNS.each do |ignore|
44
+ if line =~ ignore
45
+ line = nil
46
+ break
47
+ end
48
+ end
40
49
  line
41
50
  end
42
51
  error.backtrace.compact!
@@ -20,11 +20,20 @@ module Spec
20
20
  def inherit(klass)
21
21
  @context_eval_module.inherit klass
22
22
  end
23
+ alias :inherit_context_eval_module_from :inherit
23
24
 
24
25
  def include(mod)
25
26
  @context_eval_module.include mod
26
27
  end
27
28
 
29
+ def context_setup(&block)
30
+ @context_eval_module.context_setup(&block)
31
+ end
32
+
33
+ def context_teardown(&block)
34
+ @context_eval_module.context_teardown(&block)
35
+ end
36
+
28
37
  def setup(&block)
29
38
  @context_eval_module.setup(&block)
30
39
  end
@@ -39,15 +48,16 @@ module Spec
39
48
 
40
49
  def run(reporter, dry_run=false)
41
50
  reporter.add_context(@name)
42
-
43
51
  prepare_execution_context_class
52
+ errors = run_context_setup(reporter, dry_run)
53
+
44
54
  specifications.each do |specification|
45
- specification.run(reporter, setup_block, teardown_block, dry_run, execution_context(specification))
46
- end
47
- end
48
-
49
- def execution_context specification
50
- execution_context_class.new(specification)
55
+ specification_execution_context = execution_context(specification)
56
+ specification_execution_context.copy_instance_variables_from(@once_only_execution_context_instance, [:@spec]) unless context_setup_block.nil?
57
+ specification.run(reporter, setup_block, teardown_block, dry_run, specification_execution_context)
58
+ end unless errors.length > 0
59
+
60
+ run_context_teardown(reporter, dry_run)
51
61
  end
52
62
 
53
63
  def number_of_specs
@@ -82,6 +92,14 @@ module Spec
82
92
  @context_eval_module.method_missing(*args)
83
93
  end
84
94
 
95
+ def context_setup_block
96
+ @context_eval_module.send :context_setup_block
97
+ end
98
+
99
+ def context_teardown_block
100
+ @context_eval_module.send :context_teardown_block
101
+ end
102
+
85
103
  def specifications
86
104
  @context_eval_module.send :specifications
87
105
  end
@@ -118,6 +136,37 @@ module Spec
118
136
  @context_eval_module.send :execution_context_class
119
137
  end
120
138
 
139
+ def execution_context specification
140
+ execution_context_class.new(specification)
141
+ end
142
+
143
+ def run_context_setup(reporter, dry_run)
144
+ errors = []
145
+ unless dry_run
146
+ begin
147
+ @once_only_execution_context_instance = execution_context(nil)
148
+ @once_only_execution_context_instance.instance_eval(&context_setup_block)
149
+ rescue => e
150
+ errors << e
151
+ location = "context_setup"
152
+ reporter.spec_finished(location, e, location) if reporter
153
+ end
154
+ end
155
+ errors
156
+ end
157
+
158
+ def run_context_teardown(reporter, dry_run)
159
+ unless dry_run
160
+ begin
161
+ @once_only_execution_context_instance ||= execution_context(nil)
162
+ @once_only_execution_context_instance.instance_eval(&context_teardown_block)
163
+ rescue => e
164
+ location = "context_teardown"
165
+ reporter.spec_finished(location, e, location) if reporter
166
+ end
167
+ end
168
+ end
169
+
121
170
  end
122
171
  include InstanceMethods
123
172
  end
@@ -11,6 +11,14 @@ module Spec
11
11
  context_modules << mod
12
12
  end
13
13
 
14
+ def context_setup(&block)
15
+ context_setup_parts << block
16
+ end
17
+
18
+ def context_teardown(&block)
19
+ context_teardown_parts << block
20
+ end
21
+
14
22
  def setup(&block)
15
23
  setup_parts << block
16
24
  end
@@ -28,7 +36,8 @@ module Spec
28
36
  my_methods |= context_superclass.methods
29
37
  my_methods
30
38
  end
31
- protected
39
+
40
+ protected
32
41
 
33
42
  def method_missing(method_name, *args)
34
43
  if context_superclass.respond_to?(method_name)
@@ -37,7 +46,20 @@ module Spec
37
46
  super
38
47
  end
39
48
 
40
- private
49
+ private
50
+
51
+ def context_setup_block
52
+ parts = context_setup_parts.dup
53
+ add_context_superclass_method(:context_setup, parts)
54
+ create_block_from_parts(parts)
55
+ end
56
+
57
+ def context_teardown_block
58
+ parts = context_teardown_parts.dup
59
+ add_context_superclass_method(:context_teardown, parts)
60
+ create_block_from_parts(parts)
61
+ end
62
+
41
63
  def setup_block
42
64
  parts = setup_parts.dup
43
65
  add_context_superclass_method(:setup, parts)
@@ -73,6 +95,14 @@ module Spec
73
95
  @specifications ||= []
74
96
  end
75
97
 
98
+ def context_setup_parts
99
+ @context_setup_parts ||= []
100
+ end
101
+
102
+ def context_teardown_parts
103
+ @context_teardown_parts ||= []
104
+ end
105
+
76
106
  def setup_parts
77
107
  @setup_parts ||= []
78
108
  end
@@ -96,7 +126,7 @@ module Spec
96
126
  if part.is_a?(UnboundMethod)
97
127
  part.bind(self).call
98
128
  else
99
- instance_exec(&part)
129
+ instance_eval(&part)
100
130
  end
101
131
  end
102
132
  end
@@ -4,30 +4,43 @@ module Spec
4
4
  module Runner
5
5
  class ContextRunner
6
6
 
7
- def initialize(reporter, dry_run, single_spec=nil)
7
+ def initialize(options)
8
8
  @contexts = []
9
- @reporter = reporter
10
- @dry_run = dry_run
11
- @single_spec = single_spec
9
+ @options = options
12
10
  end
13
11
 
14
12
  def add_context(context)
15
- return if !@single_spec.nil? unless context.matches?(@single_spec)
16
- context.run_single_spec @single_spec if context.matches?(@single_spec)
13
+ return if !@options.spec_name.nil? unless context.matches?(@options.spec_name)
14
+ context.run_single_spec(@options.spec_name) if context.matches?(@options.spec_name)
17
15
  @contexts << context
18
16
  end
19
17
 
18
+ # Runs all contexts and returns the number of failures.
20
19
  def run(exit_when_done)
21
- @reporter.start(number_of_specs)
22
- @contexts.each do |context|
23
- context.run(@reporter, @dry_run)
20
+ @options.reporter.start(number_of_specs)
21
+ begin
22
+ @contexts.each do |context|
23
+ context.run(@options.reporter, @options.dry_run)
24
+ end
25
+ rescue Interrupt
26
+ ensure
27
+ @options.reporter.end
24
28
  end
25
- @reporter.end
26
- failure_count = @reporter.dump
29
+ failure_count = @options.reporter.dump
30
+
31
+ if(failure_count == 0 && !@options.heckle_runner.nil?)
32
+ heckle_runner = @options.heckle_runner
33
+ @options.heckle_runner = nil
34
+ context_runner = self.class.new(@options)
35
+ context_runner.instance_variable_set(:@contexts, @contexts)
36
+ heckle_runner.heckle_with(context_runner)
37
+ end
38
+
27
39
  if(exit_when_done)
28
40
  exit_code = (failure_count == 0) ? 0 : 1
29
41
  exit(exit_code)
30
42
  end
43
+ failure_count
31
44
  end
32
45
 
33
46
  def number_of_specs
@@ -0,0 +1,21 @@
1
+ require "drb/drb"
2
+
3
+ module Spec
4
+ module Runner
5
+ # Facade to run specs by connecting to a DRB server
6
+ class DrbCommandLine
7
+ # Runs specs on a DRB server. Note that this API is similar to that of
8
+ # CommandLine - making it possible for clients to use both interchangeably.
9
+ def self.run(argv, stderr, stdout, exit=false, warn_if_no_files=true)
10
+ begin
11
+ DRb.start_service
12
+ rails_spec_server = DRbObject.new_with_uri("druby://localhost:8989")
13
+ rails_spec_server.run(argv, stderr, stdout)
14
+ rescue DRb::DRbConnError
15
+ stderr.puts "No server is running"
16
+ exit 1 if exit
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -17,6 +17,7 @@ module Spec
17
17
  def violated(message="")
18
18
  raise Spec::Expectations::ExpectationNotMetError.new(message)
19
19
  end
20
+
20
21
  end
21
22
  include InstanceMethods
22
23
  end
@@ -1,3 +1,5 @@
1
+ require 'spec/runner/extensions/object'
2
+
1
3
  module Kernel
2
4
  def context(name, &block)
3
5
  context = Spec::Runner::Context.new(name, &block)