rspec 0.4.0 → 0.5.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 (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
+