rspec 1.2.9 → 1.3.0

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 (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