rspec 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/CHANGES +7 -12
  2. data/Rakefile +17 -12
  3. data/TUTORIAL +1 -1
  4. data/WHY_RSPEC +115 -0
  5. data/bin/spec +17 -4
  6. data/bin/test2rspec +35 -0
  7. data/examples/airport_spec.rb +35 -0
  8. data/examples/mocking_spec.rb +16 -0
  9. data/examples/spec_framework_spec.rb +28 -0
  10. data/examples/stack.rb +36 -0
  11. data/examples/stack_spec.rb +112 -0
  12. data/lib/spec.rb +5 -18
  13. data/lib/spec/api.rb +4 -0
  14. data/lib/spec/{exceptions.rb → api/exceptions.rb} +1 -1
  15. data/lib/spec/{expectations.rb → api/expectations.rb} +5 -4
  16. data/lib/spec/api/helper.rb +10 -0
  17. data/lib/spec/{have_helper.rb → api/helper/have_helper.rb} +1 -1
  18. data/lib/spec/{instance_helper.rb → api/helper/instance_helper.rb} +0 -0
  19. data/lib/spec/{instance_negator.rb → api/helper/instance_negator.rb} +0 -0
  20. data/lib/spec/{kind_helper.rb → api/helper/kind_helper.rb} +0 -0
  21. data/lib/spec/{kind_negator.rb → api/helper/kind_negator.rb} +0 -0
  22. data/lib/spec/{respond_helper.rb → api/helper/respond_helper.rb} +0 -0
  23. data/lib/spec/{respond_negator.rb → api/helper/respond_negator.rb} +0 -0
  24. data/lib/spec/{should_base.rb → api/helper/should_base.rb} +6 -4
  25. data/lib/spec/{should_helper.rb → api/helper/should_helper.rb} +12 -0
  26. data/lib/spec/{should_negator.rb → api/helper/should_negator.rb} +11 -0
  27. data/lib/spec/api/mock.rb +184 -0
  28. data/lib/spec/rake/spectask.rb +153 -0
  29. data/lib/spec/runner.rb +9 -0
  30. data/lib/spec/runner/backtrace_tweaker.rb +17 -0
  31. data/lib/spec/runner/context.rb +47 -0
  32. data/lib/spec/runner/context_runner.rb +52 -0
  33. data/lib/spec/runner/execution_context.rb +15 -0
  34. data/lib/spec/runner/instance_exec.rb +15 -0
  35. data/lib/spec/runner/kernel_ext.rb +6 -0
  36. data/lib/spec/runner/option_parser.rb +41 -0
  37. data/lib/spec/runner/rdoc_formatter.rb +17 -0
  38. data/lib/spec/runner/simple_text_reporter.rb +92 -0
  39. data/lib/spec/runner/specification.rb +42 -0
  40. data/lib/spec/tool/command_line.rb +39 -0
  41. data/lib/spec/tool/test_unit_translator.rb +112 -0
  42. data/lib/spec/version.rb +13 -0
  43. data/test/spec/api/helper/arbitrary_predicate_test.rb +121 -0
  44. data/test/spec/api/helper/containment_test.rb +117 -0
  45. data/test/spec/api/helper/equality_test.rb +46 -0
  46. data/test/spec/api/helper/identity_test.rb +68 -0
  47. data/test/spec/api/helper/raising_test.rb +50 -0
  48. data/test/spec/api/helper/regex_matching_test.rb +38 -0
  49. data/test/spec/api/helper/should_satisfy_test.rb +37 -0
  50. data/test/spec/api/helper/throwing_test.rb +56 -0
  51. data/test/spec/api/helper/true_false_special_case_test.rb +87 -0
  52. data/test/spec/api/helper/typing_test.rb +107 -0
  53. data/test/spec/api/mock_test.rb +161 -0
  54. data/test/spec/runner/backtrace_tweaker_test.rb +20 -0
  55. data/test/spec/runner/context_runner_test.rb +19 -0
  56. data/test/spec/runner/context_test.rb +29 -0
  57. data/test/spec/runner/execution_context_test.rb +13 -0
  58. data/test/spec/runner/option_parser_test.rb +50 -0
  59. data/test/spec/runner/rdoc_formatter_test.rb +23 -0
  60. data/test/spec/runner/simple_text_reporter_test.rb +128 -0
  61. data/test/spec/runner/specification_test.rb +70 -0
  62. data/test/spec/tool/command_line_test.rb +22 -0
  63. data/test/spec/tool/test_unit_api_spec.rb +61 -0
  64. data/test/spec/tool/test_unit_api_test.rb +61 -0
  65. data/test/spec/tool/test_unit_translator_test.rb +29 -0
  66. data/test/test_helper.rb +8 -0
  67. metadata +89 -67
  68. data/examples/add_specification_spec.rb +0 -15
  69. data/examples/craps.rb +0 -15
  70. data/examples/craps_spec.rb +0 -105
  71. data/examples/dsl_spec.rb +0 -8
  72. data/examples/movie.rb +0 -7
  73. data/examples/movie_list.rb +0 -19
  74. data/examples/movie_spec.rb +0 -37
  75. data/lib/spec/collector.rb +0 -17
  76. data/lib/spec/context.rb +0 -89
  77. data/lib/spec/dsl.rb +0 -23
  78. data/lib/spec/gui_runner.rb +0 -59
  79. data/lib/spec/mock.rb +0 -183
  80. data/lib/spec/text_runner.rb +0 -75
  81. data/test/collection_owner.rb +0 -48
  82. data/test/context_fixtures_test.rb +0 -71
  83. data/test/context_run_test.rb +0 -174
  84. data/test/dsl_test.rb +0 -48
  85. data/test/error_reporting_test.rb +0 -225
  86. data/test/expectations_for_should_have_test.rb +0 -144
  87. data/test/expectations_test.rb +0 -592
  88. data/test/get_classes.rb +0 -6
  89. data/test/gui_runner_test.rb +0 -162
  90. data/test/mock_test.rb +0 -157
  91. data/test/spec_collection_test.rb +0 -39
  92. data/test/specification_addition_test.rb +0 -29
  93. data/test/specification_identification_test.rb +0 -71
  94. data/test/text_runner_test.rb +0 -146
@@ -1,18 +1,5 @@
1
- require 'spec/context'
2
- require 'spec/should_base'
3
- require 'spec/have_helper'
4
- require 'spec/should_helper'
5
- require 'spec/kind_helper'
6
- require 'spec/instance_helper'
7
- require 'spec/respond_helper'
8
- require 'spec/should_negator'
9
- require 'spec/kind_negator'
10
- require 'spec/instance_negator'
11
- require 'spec/respond_negator'
12
- require 'spec/expectations'
13
- require 'spec/exceptions'
14
- require 'spec/text_runner'
15
- require 'spec/gui_runner'
16
- require 'spec/mock'
17
- require 'spec/collector'
18
- require 'spec/dsl'
1
+ $LOAD_PATH.push File.dirname(__FILE__) + '/../lib'
2
+
3
+ require 'spec/api'
4
+ require 'spec/runner'
5
+ require 'spec/runner/kernel_ext'
@@ -0,0 +1,4 @@
1
+ require 'spec/api/exceptions'
2
+ require 'spec/api/mock'
3
+ require 'spec/api/expectations'
4
+ require 'spec/api/helper'
@@ -1,5 +1,5 @@
1
1
  module Spec
2
- module Exceptions
2
+ module Api
3
3
  class ExpectationNotMetError < StandardError
4
4
  end
5
5
 
@@ -1,16 +1,17 @@
1
1
  module Spec
2
-
3
2
  module ObjectExpectations
4
-
5
3
  def should
6
4
  ShouldHelper.new self
7
5
  end
8
6
  end
9
-
10
7
  end
11
8
 
12
-
13
9
  class Object
14
10
  include Spec::ObjectExpectations
15
11
  end
16
12
 
13
+ class Numeric
14
+ def close?(other, precision)
15
+ (self - other).abs < precision
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec/api/helper/should_base'
2
+ require 'spec/api/helper/have_helper'
3
+ require 'spec/api/helper/instance_helper'
4
+ require 'spec/api/helper/instance_negator'
5
+ require 'spec/api/helper/kind_helper'
6
+ require 'spec/api/helper/kind_negator'
7
+ require 'spec/api/helper/respond_helper'
8
+ require 'spec/api/helper/respond_negator'
9
+ require 'spec/api/helper/should_helper'
10
+ require 'spec/api/helper/should_negator'
@@ -4,7 +4,7 @@ module Spec
4
4
 
5
5
  def initialize(target, expected=nil)
6
6
  @target = target
7
- @expected = expected
7
+ @expected = expected == :no ? 0 : expected
8
8
  @min = false
9
9
  @max = false
10
10
  end
@@ -21,14 +21,16 @@ module Spec
21
21
  elsif obj.kind_of? Proc
22
22
  "<Proc>"
23
23
  elsif (obj.kind_of? Array) || (obj.kind_of? String)
24
- "<#{obj.inspect}>"
25
- else
26
- "<#{obj.inspect}:#{obj.class}>"
24
+ "#{obj.inspect}"
25
+ elsif obj.inspect.include? "<"
26
+ "#{obj.class} #{obj.inspect}"
27
+ else
28
+ "#{obj.class} <#{obj.inspect}>"
27
29
  end
28
30
  end
29
31
 
30
32
  def fail_with_message(message)
31
- Kernel::raise(Spec::Exceptions::ExpectationNotMetError.new(message))
33
+ Kernel::raise(Spec::Api::ExpectationNotMetError.new(message))
32
34
  end
33
35
 
34
36
  end
@@ -25,6 +25,7 @@ module Spec
25
25
  def be(expected = :no_arg)
26
26
  return self if (expected == :no_arg)
27
27
  return if (expected == false and @target.nil?)
28
+ return if (expected == true and (!@target.nil?) and (@target != false))
28
29
  fail_with_message(default_message("should be", expected)) unless (@target.equal?(expected))
29
30
  end
30
31
 
@@ -68,6 +69,17 @@ module Spec
68
69
  fail_with_message(default_message("should raise", exception.inspect))
69
70
  end
70
71
  end
72
+
73
+ def throw(symbol)
74
+ begin
75
+ catch symbol do
76
+ @target.call
77
+ fail_with_message(default_message("should throw", symbol.inspect))
78
+ end
79
+ rescue NameError
80
+ fail_with_message(default_message("should throw", symbol.inspect))
81
+ end
82
+ end
71
83
 
72
84
  end
73
85
 
@@ -54,6 +54,17 @@ module Spec
54
54
  end
55
55
  end
56
56
 
57
+ def throw(symbol=:___this_is_a_symbol_that_will_never_occur___)
58
+ begin
59
+ catch symbol do
60
+ @target.call
61
+ return true
62
+ end
63
+ fail_with_message(default_message("should not throw", symbol.inspect))
64
+ rescue NameError
65
+ end
66
+ end
67
+
57
68
  def method_missing(sym, *args)
58
69
  return unless @target.send("#{sym}?", *args)
59
70
  fail_with_message(default_message("should not be #{sym}" + (args.empty? ? '' : (' ' + args.join(', ')))))
@@ -0,0 +1,184 @@
1
+ module Spec
2
+ module Api
3
+ class Mock
4
+
5
+ DEFAULT_OPTIONS = {
6
+ :null_object => false
7
+ }
8
+ # Creates a new mock with a +name+ (that will be used in error messages only)
9
+ # Options:
10
+ # * <tt>:null_object</tt> - if true, the mock object acts as a forgiving null object allowing any message to be sent to it.
11
+ def initialize(name, options={})
12
+ @name = name
13
+ @options = DEFAULT_OPTIONS.dup.merge(options)
14
+ @expectations = []
15
+ end
16
+
17
+ def should_receive(sym, &block)
18
+ expected_from = caller(1)[0]
19
+ expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
20
+ @expectations << expectation
21
+ expectation
22
+ end
23
+
24
+ def __verify
25
+ @expectations.each do |expectation|
26
+ expectation.verify_messages_received
27
+ end
28
+ end
29
+
30
+ def method_missing(sym, *args, &block)
31
+ # TODO: use find_expectation(sym, args) which will lookup based on sym, args and strict mode.
32
+ if expectation = find_matching_expectation(sym, *args)
33
+ expectation.verify_message(args, block)
34
+ else
35
+ begin
36
+ # act as null object if method is missing and we ignore them. return value too!
37
+ @options[:null_object] ? self : super(sym, *args, &block)
38
+ rescue NoMethodError
39
+ raise Spec::Api::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with " + (args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", "))
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def find_matching_expectation(sym, *args)
47
+ expectation = @expectations.find {|expectation| expectation.matches(sym, args)}
48
+ end
49
+
50
+ end
51
+
52
+ # Represents the expection of the reception of a message
53
+ class MessageExpectation
54
+
55
+ def initialize(mock_name, expected_from, sym, block)
56
+ @mock_name = mock_name
57
+ @expected_from = expected_from
58
+ @sym = sym
59
+ @method_block = block
60
+ @block = proc {}
61
+ @received_count = 0
62
+ @expected_received_count = 1
63
+ @expected_params = nil
64
+ @consecutive = false
65
+ end
66
+
67
+ def matches(sym, args)
68
+ @sym == sym and (@expected_params.nil? or @expected_params == args)
69
+ end
70
+
71
+ # This method is called at the end of a spec, after teardown.
72
+ def verify_messages_received
73
+ # TODO: this doesn't provide good enough error messages to fix the error.
74
+ # Error msg should tell exactly what went wrong. (AH).
75
+
76
+ return if @expected_received_count == -2
77
+ return if (@expected_received_count == -1) && (@received_count > 0)
78
+ return if @expected_received_count == @received_count
79
+
80
+ expected_signature = nil
81
+ if @expected_params.nil?
82
+ expected_signature = @sym
83
+ else
84
+ params = @expected_params.collect{|param| "<#{param}:#{param.class.name}>"}.join(", ")
85
+ expected_signature = "#{@sym}(#{params})"
86
+ end
87
+
88
+ count_message = "{@expected_received_count} times"
89
+ count_message = "at least once" if (@expected_received_count == -1)
90
+ count_message = "never" if (@expected_received_count == 0)
91
+ count_message = "once" if (@expected_received_count == 1)
92
+ count_message = "twice" if (@expected_received_count == 2)
93
+
94
+ message = "Mock '#{@mock_name}' expected #{expected_signature} #{count_message}, but received it #{@received_count} times"
95
+ begin
96
+ raise Spec::Api::MockExpectationError, message
97
+ rescue => error
98
+ error.backtrace.insert(0, @expected_from)
99
+ raise error
100
+ end
101
+ end
102
+
103
+ # This method is called when a method is invoked on a mock
104
+ def verify_message(args, block)
105
+ unless @method_block.nil?
106
+ begin
107
+ result = @method_block.call(*args)
108
+ rescue Spec::Api::ExpectationNotMetError => detail
109
+ raise Spec::Api::MockExpectationError, "Call expectation violated with: " + $!
110
+ end
111
+ @received_count += 1
112
+ return result
113
+ end
114
+
115
+ unless @expected_params.nil? or @expected_params == args
116
+ raise Spec::Api::MockExpectationError,
117
+ "#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{args}>"
118
+ end
119
+ args << block unless block.nil?
120
+ @received_count += 1
121
+ value = @block.call(*args)
122
+
123
+ return value unless @consecutive
124
+
125
+ value[[@received_count, value.size].min - 1]
126
+ end
127
+
128
+ def with(*args)
129
+ @expected_params = args
130
+ self
131
+ end
132
+
133
+ def with_no_args
134
+ @expected_params = []
135
+ self
136
+ end
137
+
138
+ def with_any_args
139
+ @expected_params = nil
140
+ self
141
+ end
142
+
143
+ def at_least_once
144
+ @expected_received_count = -1
145
+ self
146
+ end
147
+
148
+ def any_number_of_times
149
+ @expected_received_count = -2
150
+ self
151
+ end
152
+
153
+ def never
154
+ @expected_received_count = 0
155
+ self
156
+ end
157
+
158
+ def once
159
+ @expected_received_count = 1
160
+ self
161
+ end
162
+
163
+ def twice
164
+ @expected_received_count = 2
165
+ self
166
+ end
167
+
168
+ def returns(value=nil,&block)
169
+ @block = block_given? ? block : proc { value }
170
+ end
171
+
172
+ def returns_consecutively(value=[nil],&block)
173
+ @consecutive = true
174
+ @block = block_given? ? block : proc { value }
175
+ end
176
+
177
+ # this reads better in English IMHO: (AH)
178
+ # uri_specs.should_receive(:[]).with(:overview).and_return("http://some.host/look_here/\#{path}")
179
+ alias :and_return :returns
180
+ alias :and_return_consecutively :returns_consecutively
181
+
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Define a task library for running RSpec contexts.
4
+
5
+ require 'rake'
6
+ require 'rake/tasklib'
7
+ require File.dirname(__FILE__) + '/../../spec'
8
+
9
+ module Spec
10
+ module Rake
11
+
12
+ # Create a task that runs a set of RSpec contexts.
13
+ #
14
+ # Example:
15
+ #
16
+ # Rake::SpecTask.new do |t|
17
+ # t.libs << "spec"
18
+ # t.spec_files = FileList['spec/**/*_spec.rb']
19
+ # t.verbose = true
20
+ # end
21
+ #
22
+ # If rake is invoked with a "SPEC=filename" command line option,
23
+ # then the list of spec files will be overridden to include only the
24
+ # filename specified on the command line. This provides an easy way
25
+ # to run just one spec.
26
+ #
27
+ # If rake is invoked with a "SPECOPTS=options" command line option,
28
+ # then the given options are passed to the spec process after a
29
+ # '--'. This allows Test::Unit options to be passed to the spec
30
+ # suite.
31
+ #
32
+ # Examples:
33
+ #
34
+ # rake spec # run specs normally
35
+ # rake spec SPEC=just_one_file.rb # run just one spec file.
36
+ # rake spec SPECOPTS="-v" # run in verbose mode
37
+ # rake spec SPECOPTS="--runner=fox" # use the fox spec runner
38
+ #
39
+ class SpecTask < ::Rake::TaskLib
40
+
41
+ # Name of spec task. (default is :spec)
42
+ attr_accessor :name
43
+
44
+ # List of directories to added to $LOAD_PATH before running the
45
+ # specs. (default is 'lib')
46
+ attr_accessor :libs
47
+
48
+ # True if verbose spec output desired. (default is false)
49
+ attr_accessor :verbose
50
+
51
+ # Test options passed to the spec suite. An explicit
52
+ # SPECOPTS=opts on the command line will override this. (default
53
+ # is NONE)
54
+ attr_accessor :options
55
+
56
+ # Request that the specs be run with the warning flag set.
57
+ # E.g. warning=true implies "ruby -w" used to run the specs.
58
+ attr_accessor :warning
59
+
60
+ # Glob pattern to match spec files. (default is 'spec/spec*.rb')
61
+ attr_accessor :pattern
62
+
63
+ # Style of spec loader to use. Options are:
64
+ #
65
+ # * :rake -- Rake provided spec loading script (default).
66
+ # * :specrb -- Ruby provided spec loading script.
67
+ # * :direct -- Load specs using command line loader.
68
+ #
69
+ attr_accessor :loader
70
+
71
+ # Array of commandline options to pass to ruby when running spec loader.
72
+ attr_accessor :ruby_opts
73
+
74
+ # Explicitly define the list of spec files to be included in a
75
+ # spec. +list+ is expected to be an array of file names (a
76
+ # FileList is acceptable). If both +pattern+ and +spec_files+ are
77
+ # used, then the list of spec files is the union of the two.
78
+ def spec_files=(list)
79
+ @spec_files = list
80
+ end
81
+
82
+ # Create a specing task.
83
+ def initialize(name=:spec)
84
+ @name = name
85
+ @libs = ["lib"]
86
+ @pattern = nil
87
+ @options = nil
88
+ @spec_files = nil
89
+ @verbose = false
90
+ @warning = false
91
+ @loader = :rake
92
+ @ruby_opts = []
93
+ yield self if block_given?
94
+ @pattern = 'spec/**/*_spec.rb' if @pattern.nil? && @spec_files.nil?
95
+ define
96
+ end
97
+
98
+ # Create the tasks defined by this task lib.
99
+ def define
100
+ lib_path = @libs.join(File::PATH_SEPARATOR)
101
+ desc "Run specs" + (@name==:spec ? "" : " for #{@name}")
102
+ task @name do
103
+ run_code =
104
+ case @loader
105
+ when :direct
106
+ "-e 'ARGV.each{|f| load f}'"
107
+ when :rake
108
+ rake_loader
109
+ end
110
+
111
+ RakeFileUtils.verbose(@verbose) do
112
+ @ruby_opts.unshift( "-I#{lib_path}" )
113
+ @ruby_opts.unshift( "-w" ) if @warning
114
+ ruby @ruby_opts.join(" ") +
115
+ " \"#{run_code}\" " +
116
+ file_list.collect { |fn| "\"#{fn}\"" }.join(' ') +
117
+ " #{option_list}"
118
+ end
119
+ end
120
+ self
121
+ end
122
+
123
+ def option_list # :nodoc:
124
+ ENV['SPECOPTS'] || @options || ""
125
+ end
126
+
127
+ def file_list # :nodoc:
128
+ if ENV['SPEC']
129
+ FileList[ ENV['SPEC'] ]
130
+ else
131
+ result = []
132
+ result += @spec_files.to_a if @spec_files
133
+ result += FileList[ @pattern ].to_a if @pattern
134
+ FileList[result]
135
+ end
136
+ end
137
+
138
+ def rake_loader # :nodoc:
139
+ find_file('rake/rake_test_loader') or
140
+ fail "unable to find rake test loader"
141
+ end
142
+
143
+ def find_file(fn) # :nodoc:
144
+ $LOAD_PATH.each do |path|
145
+ file_path = File.join(path, "#{fn}.rb")
146
+ return file_path if File.exist? file_path
147
+ end
148
+ nil
149
+ end
150
+ end
151
+ end
152
+ end
153
+