rspec 1.2.9 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/History.rdoc +34 -1
  2. data/License.txt +1 -1
  3. data/Manifest.txt +11 -4
  4. data/README.rdoc +2 -3
  5. data/Rakefile +17 -13
  6. data/Upgrade.rdoc +63 -2
  7. data/features/formatters/nested_formatter.feature +32 -0
  8. data/features/interop/cucumber_stubs_dont_leak.feature +11 -0
  9. data/features/matchers/define_matcher_with_fluent_interface.feature +21 -0
  10. data/features/matchers/define_wrapped_matcher.feature +28 -1
  11. data/features/matchers/match_unless_raises.feature +60 -0
  12. data/features/matchers/match_unless_raises_unexpected_error.feature +39 -0
  13. data/features/mocks/block_local_expectations.feature +62 -0
  14. data/features/step_definitions/running_rspec_steps.rb +9 -0
  15. data/features/step_definitions/stubbing_steps.rb +16 -0
  16. data/features/support/env.rb +1 -0
  17. data/features/support/matchers/smart_match.rb +23 -4
  18. data/geminstaller.yml +28 -0
  19. data/lib/autotest/rspec.rb +14 -7
  20. data/lib/spec/dsl/main.rb +1 -1
  21. data/lib/spec/example/example_methods.rb +4 -0
  22. data/lib/spec/{matchers/extensions → extensions}/instance_exec.rb +0 -0
  23. data/lib/spec/interop/test.rb +1 -1
  24. data/lib/spec/matchers.rb +21 -2
  25. data/lib/spec/matchers/be.rb +167 -128
  26. data/lib/spec/matchers/has.rb +3 -3
  27. data/lib/spec/matchers/have.rb +1 -0
  28. data/lib/spec/matchers/matcher.rb +55 -10
  29. data/lib/spec/matchers/method_missing.rb +2 -2
  30. data/lib/spec/matchers/raise_exception.rb +131 -0
  31. data/lib/spec/matchers/throw_symbol.rb +16 -20
  32. data/lib/spec/mocks/message_expectation.rb +63 -48
  33. data/lib/spec/mocks/methods.rb +13 -8
  34. data/lib/spec/mocks/proxy.rb +43 -22
  35. data/lib/spec/runner/differs/default.rb +1 -1
  36. data/lib/spec/runner/drb_command_line.rb +8 -2
  37. data/lib/spec/runner/example_group_runner.rb +1 -2
  38. data/lib/spec/runner/formatter/nested_text_formatter.rb +6 -3
  39. data/lib/spec/runner/option_parser.rb +2 -0
  40. data/lib/spec/runner/options.rb +6 -1
  41. data/lib/spec/stubs/cucumber.rb +2 -2
  42. data/lib/spec/version.rb +2 -2
  43. data/spec/autotest/autotest_helper.rb +1 -1
  44. data/spec/autotest/discover_spec.rb +2 -2
  45. data/spec/autotest/failed_results_re_spec.rb +2 -2
  46. data/spec/autotest/rspec_spec.rb +21 -6
  47. data/spec/spec/example/example_group_methods_spec.rb +2 -1
  48. data/spec/spec/interop/test/unit/spec_spec.rb +7 -7
  49. data/spec/spec/interop/test/unit/testcase_spec.rb +7 -7
  50. data/spec/spec/interop/test/unit/testsuite_adapter_spec.rb +1 -1
  51. data/spec/spec/matchers/be_spec.rb +159 -10
  52. data/spec/spec/matchers/has_spec.rb +109 -0
  53. data/spec/spec/matchers/matcher_spec.rb +70 -9
  54. data/spec/spec/matchers/raise_exception_spec.rb +345 -0
  55. data/spec/spec/matchers/throw_symbol_spec.rb +83 -58
  56. data/spec/spec/mocks/and_yield_spec.rb +117 -0
  57. data/spec/spec/mocks/mock_spec.rb +2 -2
  58. data/spec/spec/runner/command_line_spec.rb +26 -5
  59. data/spec/spec/runner/drb_command_line_spec.rb +39 -0
  60. data/spec/spec/runner/formatter/nested_text_formatter_spec.rb +35 -11
  61. data/spec/spec/runner/option_parser_spec.rb +12 -6
  62. data/spec/spec/runner/options_spec.rb +7 -0
  63. data/spec/spec/runner/quiet_backtrace_tweaker_spec.rb +23 -5
  64. metadata +17 -10
  65. data/lib/spec/matchers/raise_error.rb +0 -129
  66. data/spec/spec/matchers/matcher_methods_spec.rb +0 -63
  67. data/spec/spec/matchers/raise_error_spec.rb +0 -333
@@ -55,6 +55,19 @@ module Spec
55
55
  end
56
56
  end
57
57
 
58
+ # Record and otherwise ignore all messages that aren't specified,
59
+ # with +stub+, +stub!+, or +should_receive+.
60
+ #
61
+ # == Returns
62
+ # self
63
+ def as_null_object
64
+ __mock_proxy.as_null_object
65
+ end
66
+
67
+ def null_object?
68
+ __mock_proxy.null_object?
69
+ end
70
+
58
71
  def received_message?(sym, *args, &block) #:nodoc:
59
72
  __mock_proxy.received_message?(sym.to_sym, *args, &block)
60
73
  end
@@ -66,14 +79,6 @@ module Spec
66
79
  def rspec_reset #:nodoc:
67
80
  __mock_proxy.reset
68
81
  end
69
-
70
- def as_null_object
71
- __mock_proxy.as_null_object
72
- end
73
-
74
- def null_object?
75
- __mock_proxy.null_object?
76
- end
77
82
 
78
83
  private
79
84
 
@@ -40,13 +40,16 @@ module Spec
40
40
  def add_message_expectation(expected_from, sym, opts={}, &block)
41
41
  __add sym
42
42
  warn_if_nil_class sym
43
- if existing_stub = @stubs.detect {|s| s.sym == sym }
44
- expectation = existing_stub.build_child(expected_from, block_given?? block : nil, 1, opts)
43
+ @expectations << build_expectation(expected_from, sym, opts, &block)
44
+ @expectations.last
45
+ end
46
+
47
+ def build_expectation(expected_from, sym, opts, &block)
48
+ if stub = find_matching_method_stub(sym)
49
+ stub.build_child(expected_from, block_given?? block : nil, 1, opts)
45
50
  else
46
- expectation = MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
51
+ MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
47
52
  end
48
- @expectations << expectation
49
- @expectations.last
50
53
  end
51
54
 
52
55
  def add_negative_message_expectation(expected_from, sym, &block)
@@ -64,7 +67,6 @@ module Spec
64
67
 
65
68
  def remove_stub(message)
66
69
  message = message.to_sym
67
-
68
70
  if stub_to_remove = @stubs.detect { |s| s.matches_name?(message) }
69
71
  reset_proxied_method(message)
70
72
  @stubs.delete(stub_to_remove)
@@ -92,7 +94,7 @@ module Spec
92
94
  end
93
95
 
94
96
  def has_negative_expectation?(sym)
95
- @expectations.detect {|expectation| expectation.negative_expectation_for?(sym)}
97
+ @expectations.any? {|expectation| expectation.negative_expectation_for?(sym)}
96
98
  end
97
99
 
98
100
  def record_message_received(sym, args, block)
@@ -103,21 +105,39 @@ module Spec
103
105
  expectation = find_matching_expectation(sym, *args)
104
106
  stub = find_matching_method_stub(sym, *args)
105
107
 
106
- if (stub && expectation && expectation.called_max_times?) || (stub && !expectation)
107
- if expectation = find_almost_matching_expectation(sym, *args)
108
- expectation.advise(args, block) unless expectation.expected_messages_received?
109
- end
110
- stub.invoke(*args, &block)
108
+ if ok_to_invoke_stub?(stub, expectation)
109
+ record_stub(stub, sym, args, &block)
111
110
  elsif expectation
112
- expectation.invoke(*args, &block)
111
+ invoke_expectation(expectation, *args, &block)
113
112
  elsif expectation = find_almost_matching_expectation(sym, *args)
114
- expectation.advise(args, block) if null_object? unless expectation.expected_messages_received?
115
- raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?)
113
+ record_almost_matching_expectation(expectation, sym, *args, &block)
116
114
  else
117
115
  @target.__send__ :method_missing, sym, *args, &block
118
116
  end
119
117
  end
120
118
 
119
+ def record_stub(stub, sym, args, &block)
120
+ almost_matching_expectation(sym, *args) do |e|
121
+ e.advise(args, block)
122
+ end
123
+ stub.invoke(*args, &block)
124
+ end
125
+
126
+ def invoke_expectation(expectation, *args, &block)
127
+ expectation.invoke(*args, &block)
128
+ end
129
+
130
+ def record_almost_matching_expectation(expectation, sym, *args, &block)
131
+ expectation.advise(args, block)
132
+ unless (null_object? or has_negative_expectation?(sym))
133
+ raise_unexpected_message_args_error(expectation, *args)
134
+ end
135
+ end
136
+
137
+ def ok_to_invoke_stub?(stub, expectation)
138
+ stub && (!expectation || expectation.called_max_times?)
139
+ end
140
+
121
141
  def raise_unexpected_message_args_error(expectation, *args)
122
142
  @error_generator.raise_unexpected_message_args_error expectation, *args
123
143
  end
@@ -201,15 +221,11 @@ module Spec
201
221
  end
202
222
 
203
223
  def verify_expectations
204
- @expectations.each do |expectation|
205
- expectation.verify_messages_received
206
- end
224
+ @expectations.map {|e| e.verify_messages_received}
207
225
  end
208
226
 
209
227
  def reset_proxied_methods
210
- @proxied_methods.each do |sym|
211
- reset_proxied_method(sym)
212
- end
228
+ @proxied_methods.map {|sym| reset_proxied_method(sym)}
213
229
  end
214
230
 
215
231
  def reset_proxied_method(sym)
@@ -236,10 +252,15 @@ module Spec
236
252
  @expectations.find {|expectation| expectation.matches(sym, args)}
237
253
  end
238
254
 
255
+ def almost_matching_expectation(sym, *args, &block)
256
+ if e = find_almost_matching_expectation(sym, *args)
257
+ yield e
258
+ end
259
+ end
260
+
239
261
  def find_almost_matching_expectation(sym, *args)
240
262
  @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)}
241
263
  end
242
-
243
264
  end
244
265
  end
245
266
  end
@@ -4,7 +4,7 @@ require 'pp'
4
4
  module Spec
5
5
  module Expectations
6
6
  module Differs
7
- unless defined?(Default)
7
+ unless defined?(Spec::Expectations::Differs::Default)
8
8
  class Default
9
9
  def initialize(options)
10
10
  @options = options
@@ -4,16 +4,21 @@ module Spec
4
4
  module Runner
5
5
  # Facade to run specs by connecting to a DRB server
6
6
  class DrbCommandLine
7
+
8
+ def self.port(options)
9
+ (options.drb_port || ENV["RSPEC_DRB"] || 8989).to_i
10
+ end
11
+
7
12
  # Runs specs on a DRB server. Note that this API is similar to that of
8
13
  # CommandLine - making it possible for clients to use both interchangeably.
9
14
  def self.run(options)
10
15
  begin
11
16
  begin; \
12
17
  DRb.start_service("druby://localhost:0"); \
13
- rescue SocketError; \
18
+ rescue SocketError, Errno::EADDRNOTAVAIL; \
14
19
  DRb.start_service("druby://:0"); \
15
20
  end
16
- spec_server = DRbObject.new_with_uri("druby://127.0.0.1:8989")
21
+ spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{port(options)}")
17
22
  spec_server.run(options.argv, options.error_stream, options.output_stream)
18
23
  true
19
24
  rescue DRb::DRbConnError
@@ -21,6 +26,7 @@ module Spec
21
26
  false
22
27
  end
23
28
  end
29
+
24
30
  end
25
31
  end
26
32
  end
@@ -22,9 +22,8 @@ module Spec
22
22
  example_groups.each do |example_group|
23
23
  success = success & example_group.run(@options)
24
24
  end
25
- return success
26
- ensure
27
25
  finish
26
+ success
28
27
  end
29
28
 
30
29
  protected
@@ -4,6 +4,9 @@ module Spec
4
4
  module Runner
5
5
  module Formatter
6
6
  class NestedTextFormatter < BaseTextFormatter
7
+
8
+ INDENT = ' '
9
+
7
10
  def initialize(options, where)
8
11
  super
9
12
  @last_nested_descriptions = []
@@ -13,8 +16,8 @@ module Spec
13
16
  super
14
17
 
15
18
  example_group.nested_descriptions.each_with_index do |nested_description, i|
16
- unless nested_description == @last_nested_descriptions[i]
17
- output.puts "#{' ' * i}#{nested_description}"
19
+ unless example_group.nested_descriptions[0..i] == @last_nested_descriptions[0..i]
20
+ output.puts "#{INDENT*i}#{nested_description}"
18
21
  end
19
22
  end
20
23
 
@@ -39,7 +42,7 @@ module Spec
39
42
  end
40
43
 
41
44
  def current_indentation
42
- ' ' * @last_nested_descriptions.length
45
+ INDENT*@last_nested_descriptions.length
43
46
  end
44
47
  end
45
48
  end
@@ -80,6 +80,7 @@ module Spec
80
80
  :runner => ["-U", "--runner RUNNER", "Use a custom Runner."],
81
81
  :debug => ["-u", "--debugger", "Enable ruby-debugging."],
82
82
  :drb => ["-X", "--drb", "Run examples via DRb. (For example against script/spec_server)"],
83
+ :drb_port => ["--port PORT", "Port for DRb server. (Ignored without --drb)"],
83
84
  :version => ["-v", "--version", "Show version"],
84
85
  :help => ["-h", "--help", "You're looking at it"]
85
86
  }
@@ -113,6 +114,7 @@ module Spec
113
114
  on(*OPTIONS[:runner]) {|runner| @options.user_input_for_runner = runner}
114
115
  on(*OPTIONS[:debug]) {@options.debug = true}
115
116
  on(*OPTIONS[:drb]) {}
117
+ on(*OPTIONS[:drb_port]) {|port| @options.drb_port = port}
116
118
  on(*OPTIONS[:version]) {parse_version}
117
119
  on("--autospec") {@options.autospec = true}
118
120
  on_tail(*OPTIONS[:help]) {parse_help}
@@ -50,7 +50,8 @@ module Spec
50
50
  :argv
51
51
  )
52
52
  attr_reader :colour, :differ_class, :files, :examples, :example_groups
53
-
53
+ attr_writer :drb_port
54
+
54
55
  def initialize(error_stream, output_stream)
55
56
  @error_stream = error_stream
56
57
  @output_stream = output_stream
@@ -289,6 +290,10 @@ module Spec
289
290
  @dry_run == true
290
291
  end
291
292
 
293
+ def drb_port
294
+ @drb_port.to_i if defined?(@drb_port)
295
+ end
296
+
292
297
  protected
293
298
 
294
299
  def define_predicate_matchers
@@ -1,5 +1,5 @@
1
1
  # This plugs RSpec's mocking/stubbing framework into cucumber
2
2
  require 'spec/mocks'
3
- Before {$rspec_stubs ||= Spec::Mocks::Space.new}
4
- After {$rspec_stubs.reset_all}
3
+ Before {$rspec_mocks ||= Spec::Mocks::Space.new}
4
+ After {$rspec_mocks.reset_all}
5
5
  World(Spec::Mocks::ExampleMethods)
@@ -2,8 +2,8 @@ module Spec # :nodoc:
2
2
  module VERSION # :nodoc:
3
3
  unless defined? MAJOR
4
4
  MAJOR = 1
5
- MINOR = 2
6
- TINY = 9
5
+ MINOR = 3
6
+ TINY = 0
7
7
  PRE = nil
8
8
 
9
9
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -5,4 +5,4 @@ rescue LoadError
5
5
  raise "You must install ZenTest to use autotest"
6
6
  end
7
7
  require 'autotest/rspec'
8
- require 'spec/autotest/autotest_matchers'
8
+ require 'autotest/autotest_matchers'
@@ -1,8 +1,8 @@
1
- require 'spec/autotest/autotest_helper'
1
+ require 'autotest/autotest_helper'
2
2
 
3
3
  describe Autotest::Rspec, "discovery" do
4
4
  it "adds the rspec autotest plugin" do
5
5
  Autotest.should_receive(:add_discovery)
6
- load File.expand_path(File.dirname(__FILE__) + "/../../lib/autotest/discover.rb")
6
+ load File.expand_path("../../../lib/autotest/discover.rb", __FILE__)
7
7
  end
8
8
  end
@@ -1,4 +1,4 @@
1
- require 'spec/autotest/autotest_helper'
1
+ require 'autotest/autotest_helper'
2
2
 
3
3
  describe "failed_results_re" do
4
4
  it "should match a failure" do
@@ -28,4 +28,4 @@ describe "failed_results_re" do
28
28
  $1.should == "this example"
29
29
  $2.should == "reason\n/path.rb:37:"
30
30
  end
31
- end
31
+ end
@@ -1,4 +1,4 @@
1
- require 'spec/autotest/autotest_helper'
1
+ require 'autotest/autotest_helper'
2
2
 
3
3
  describe Autotest::Rspec do
4
4
  describe "adding spec.opts --options" do
@@ -26,17 +26,21 @@ describe Autotest::Rspec do
26
26
  @ruby = @rspec_autotest.ruby
27
27
  @spec_cmd = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'spec'))
28
28
  @options = @rspec_autotest.add_options_if_present
29
+ files = %w[file_one file_two]
29
30
  @files_to_test = {
30
- :spec => ["file_one", "file_two"]
31
+ files[0] => [],
32
+ files[1] => []
31
33
  }
32
34
  # this is not the inner representation of Autotest!
33
- @rspec_autotest.stub!(:files_to_test).and_return @files_to_test
34
- @files_to_test.stub!(:keys).and_return @files_to_test[:spec]
35
- @to_test = @files_to_test.keys.flatten.join ' '
35
+ @rspec_autotest.files_to_test = @files_to_test
36
+ @to_test = files.map { |f| File.expand_path(f) }.join ' '
36
37
  end
37
38
 
38
39
  it "should make the appropriate test command" do
39
- @rspec_autotest.make_test_cmd(@files_to_test).should == "#{@ruby} #{@spec_cmd} --autospec #{@to_test} #{@options}"
40
+ cmd = @rspec_autotest.make_test_cmd(@files_to_test)
41
+ (cmd =~ /#{@ruby} #{@spec_cmd} --autospec (.*) #{@options}/).should be_true
42
+ $1.should =~ /#{File.expand_path('file_one')}/
43
+ $1.should =~ /#{File.expand_path('file_two')}/
40
44
  end
41
45
 
42
46
  it "should return a blank command for no files" do
@@ -108,4 +112,15 @@ describe Autotest::Rspec do
108
112
  @rspec_autotest.consolidate_failures(failures).keys.should_not include(subject_file)
109
113
  end
110
114
  end
115
+
116
+ describe "normalizing file names" do
117
+ it "should ensure that a single file appears in files_to_test only once" do
118
+ @rspec_autotest = Autotest::Rspec.new
119
+ @files_to_test = {}
120
+ ['filename.rb', './filename.rb', File.expand_path('filename.rb')].each do |file|
121
+ @files_to_test[file] = []
122
+ end
123
+ @rspec_autotest.normalize(@files_to_test).should have(1).file
124
+ end
125
+ end
111
126
  end
@@ -732,7 +732,7 @@ module Spec
732
732
  end
733
733
  end
734
734
 
735
- describe "#define" do
735
+ describe "#let" do
736
736
  let(:counter) do
737
737
  Class.new do
738
738
  def initialize
@@ -743,6 +743,7 @@ module Spec
743
743
  end
744
744
  end.new
745
745
  end
746
+
746
747
  it "generates an instance method" do
747
748
  counter.count.should == 1
748
749
  end
@@ -5,43 +5,43 @@ describe "ExampleGroup with test/unit/interop" do
5
5
 
6
6
  describe "with passing examples" do
7
7
  it "should output 0 failures" do
8
- output = ruby("#{resources}/spec_that_passes.rb")
8
+ output = ruby("'#{resources}/spec_that_passes.rb'")
9
9
  output.should include("1 example, 0 failures")
10
10
  end
11
11
 
12
12
  it "should return an exit code of 0" do
13
- ruby("#{resources}/spec_that_passes.rb")
13
+ ruby("'#{resources}/spec_that_passes.rb'")
14
14
  $?.should == 0
15
15
  end
16
16
  end
17
17
 
18
18
  describe "with failing examples" do
19
19
  it "should output 1 failure" do
20
- output = ruby("#{resources}/spec_that_fails.rb")
20
+ output = ruby("'#{resources}/spec_that_fails.rb'")
21
21
  output.should include("1 example, 1 failure")
22
22
  end
23
23
 
24
24
  it "should return an exit code of 256" do
25
- ruby("#{resources}/spec_that_fails.rb")
25
+ ruby("'#{resources}/spec_that_fails.rb'")
26
26
  $?.should == 256
27
27
  end
28
28
  end
29
29
 
30
30
  describe "with example that raises an error" do
31
31
  it "should output 1 failure" do
32
- output = ruby("#{resources}/spec_with_errors.rb")
32
+ output = ruby("'#{resources}/spec_with_errors.rb'")
33
33
  output.should include("1 example, 1 failure")
34
34
  end
35
35
 
36
36
  it "should return an exit code of 256" do
37
- ruby("#{resources}/spec_with_errors.rb")
37
+ ruby("'#{resources}/spec_with_errors.rb'")
38
38
  $?.should == 256
39
39
  end
40
40
  end
41
41
 
42
42
  describe "options hash" do
43
43
  it "should be exposed" do
44
- output = ruby("#{resources}/spec_with_options_hash.rb")
44
+ output = ruby("'#{resources}/spec_with_options_hash.rb'")
45
45
  output.should include("1 example, 0 failures")
46
46
  end
47
47
  end
@@ -9,42 +9,42 @@ describe "Test::Unit::TestCase" do
9
9
 
10
10
  describe "with passing test case" do
11
11
  it "should output 0 failures" do
12
- output = ruby("#{@dir}/test_case_that_passes.rb")
12
+ output = ruby("'#{@dir}/test_case_that_passes.rb'")
13
13
  output.should include("1 example, 0 failures")
14
14
  end
15
15
 
16
16
  it "should return an exit code of 0" do
17
- ruby("#{@dir}/test_case_that_passes.rb")
17
+ ruby("'#{@dir}/test_case_that_passes.rb'")
18
18
  $?.should == 0
19
19
  end
20
20
  end
21
21
 
22
22
  describe "with failing test case" do
23
23
  it "should output 1 failure" do
24
- output = ruby("#{@dir}/test_case_that_fails.rb")
24
+ output = ruby("'#{@dir}/test_case_that_fails.rb'")
25
25
  output.should include("1 example, 1 failure")
26
26
  end
27
27
 
28
28
  it "should return an exit code of 256" do
29
- ruby("#{@dir}/test_case_that_fails.rb")
29
+ ruby("'#{@dir}/test_case_that_fails.rb'")
30
30
  $?.should == 256
31
31
  end
32
32
  end
33
33
 
34
34
  describe "with test case that raises an error" do
35
35
  it "should output 1 failure" do
36
- output = ruby("#{@dir}/test_case_with_errors.rb")
36
+ output = ruby("'#{@dir}/test_case_with_errors.rb'")
37
37
  output.should include("1 example, 1 failure")
38
38
  end
39
39
 
40
40
  it "should return an exit code of 256" do
41
- ruby("#{@dir}/test_case_with_errors.rb")
41
+ ruby("'#{@dir}/test_case_with_errors.rb'")
42
42
  $?.should == 256
43
43
  end
44
44
  end
45
45
 
46
46
  it "should find all Test::Unit test methods" do
47
- output = ruby("#{@dir}/test_case_with_various_names.rb")
47
+ output = ruby("'#{@dir}/test_case_with_various_names.rb'")
48
48
  output.should include("4 examples, 0 failures")
49
49
  end
50
50
  end