rspec 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/CHANGES +9 -5
  2. data/Rakefile +35 -29
  3. data/bin/spec +0 -5
  4. data/doc/README +5 -0
  5. data/doc/config.yaml +2 -0
  6. data/doc/plugin/syntax.rb +38 -0
  7. data/doc/reference/rspec reference.page +0 -0
  8. data/doc/src/community.page +8 -0
  9. data/doc/src/default.css +198 -0
  10. data/doc/src/default.template +34 -0
  11. data/doc/src/documentation/api.page +251 -0
  12. data/doc/src/documentation/index.page +8 -0
  13. data/doc/src/documentation/mocks.page +207 -0
  14. data/doc/src/documentation/specs.page +20 -0
  15. data/doc/src/download.page +8 -0
  16. data/doc/src/examples.page +9 -0
  17. data/doc/src/images/ul.gif +0 -0
  18. data/doc/src/index.page +8 -0
  19. data/doc/src/tools/index.page +8 -0
  20. data/doc/src/tools/rails.page +8 -0
  21. data/doc/src/tools/rake.page +8 -0
  22. data/doc/src/tools/rcov.page +8 -0
  23. data/doc/src/tools/spec_runner.page +8 -0
  24. data/doc/src/tools/specdoc.page +8 -0
  25. data/doc/src/tools/test2rspec.page +8 -0
  26. data/doc/src/ul.gif +0 -0
  27. data/doc/src/why_rspec.page +8 -0
  28. data/examples/mocking_spec.rb +2 -2
  29. data/examples/spec_framework_spec.rb +4 -4
  30. data/lib/spec/api/helper/have_helper.rb +55 -55
  31. data/lib/spec/api/mock.rb +111 -38
  32. data/lib/spec/runner/backtrace_tweaker.rb +4 -4
  33. data/lib/spec/runner/context.rb +2 -1
  34. data/lib/spec/runner/context_runner.rb +3 -3
  35. data/lib/spec/runner/option_parser.rb +8 -4
  36. data/lib/spec/runner/simple_text_reporter.rb +29 -19
  37. data/lib/spec/runner/specification.rb +2 -1
  38. data/lib/spec/version.rb +1 -1
  39. data/test/rake/rcov_testtask.rb +45 -0
  40. data/test/spec/api/helper/arbitrary_predicate_test.rb +39 -24
  41. data/test/spec/api/helper/equality_test.rb +19 -0
  42. data/test/spec/api/helper/should_have_test.rb +183 -0
  43. data/test/spec/api/mock_arg_constraints_test.rb +90 -0
  44. data/test/spec/api/mock_test.rb +101 -21
  45. data/test/spec/runner/context_runner_test.rb +3 -3
  46. data/test/spec/runner/context_test.rb +2 -5
  47. data/test/spec/runner/execution_context_test.rb +1 -1
  48. data/test/spec/runner/option_parser_test.rb +16 -8
  49. data/test/spec/runner/simple_text_reporter_test.rb +57 -33
  50. data/test/spec/runner/specification_test.rb +7 -7
  51. data/test/spec/tool/command_line_test.rb +4 -4
  52. data/test/test_helper.rb +2 -2
  53. metadata +37 -8
  54. data/README +0 -38
  55. data/TODO +0 -9
  56. data/TUTORIAL +0 -259
  57. data/WHY_RSPEC +0 -115
@@ -0,0 +1,20 @@
1
+ ---
2
+ title: Writing Specifications
3
+ inMenu: true
4
+ ordering: 2
5
+ ---
6
+ h2. Writing Specifications
7
+
8
+ An RSpec specification is a Ruby file with a context and one or more specifications. Example:
9
+
10
+ context "Stack" do
11
+ specify "should return top when sent top" do
12
+ stack = Stack.new
13
+ stack.push 3
14
+ stack.top.should.be 3
15
+ end
16
+ end
17
+
18
+ A context represents a collection of specifications and must be defined with a name and a block (do-end).
19
+ A specification is defined with the *specify* keyword and a sentence describing what's being specified.
20
+ It is highly recommended to include
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Download
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Download
7
+
8
+ Bla
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Examples
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Examples
7
+
8
+ Here is an example of an RSpec spec:
9
+ {ruby_inline: {filename: ../examples/spec_framework_spec.rb}}
Binary file
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Overview
3
+ inMenu: true
4
+ ordering: 1
5
+ ---
6
+ h2. RSpec
7
+
8
+ bla bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Tools
3
+ inMenu: true
4
+ ordering: 1
5
+ ---
6
+ h2. Tools
7
+
8
+ Look at my tools
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Rails Integration
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Rails Integration
7
+
8
+ Bla bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Rake Integration
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Rake Integration
7
+
8
+ Bla bla bla Bla bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Code Coverage
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Code Coverage
7
+
8
+ RCove bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Running Specifications
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Running Specifications
7
+
8
+ Bla bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Specdoc
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Specdoc
7
+
8
+ Bla bla
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Test::Unit migration
3
+ inMenu: true
4
+ ordering: 5
5
+ ---
6
+ h2. Test::Unit migration
7
+
8
+ lalalala
Binary file
@@ -0,0 +1,8 @@
1
+ ---
2
+ title: Why RSpec
3
+ inMenu: true
4
+ ordering: 2
5
+ ---
6
+ h2. Why RSpec
7
+
8
+ Bla bla bla
@@ -4,13 +4,13 @@ context "Mocker" do
4
4
 
5
5
  specify "should be able to call mock()" do
6
6
  mock = mock("poke me")
7
- mock.should_receive(:poke)
7
+ mock.should.receive(:poke)
8
8
  mock.poke
9
9
  end
10
10
 
11
11
  specify "should fail when expected message not received" do
12
12
  mock = mock("poke me")
13
- mock.should_receive(:poke)
13
+ mock.should.receive(:poke)
14
14
  end
15
15
 
16
16
  end
@@ -15,14 +15,14 @@ context "Spec framework" do
15
15
  setup do
16
16
  @spec_framework = SpecFramework.new
17
17
  end
18
-
19
- specify "should be intuitive" do
20
- @spec_framework.should.be.intuitive
21
- end
22
18
 
23
19
  specify "should be adopted quickly" do
24
20
  #this will fail
25
21
  @spec_framework.should.be.adopted_quickly
26
22
  end
23
+
24
+ specify "should be intuitive" do
25
+ @spec_framework.should.be.intuitive
26
+ end
27
27
 
28
28
  end
@@ -1,56 +1,56 @@
1
- module Spec
2
-
3
- class HaveHelper < ShouldBase
4
-
5
- def initialize(target, expected=nil)
6
- @target = target
7
- @expected = expected == :no ? 0 : expected
8
- @min = false
9
- @max = false
10
- end
11
-
12
- def method_missing(sym, *args)
13
- fail_with_message(build_message(sym)) unless as_specified?(sym)
14
- end
15
-
16
- def collection(sym)
17
- @target.send(sym)
18
- end
19
-
20
- def actual_size(collection)
21
- return collection.length if collection.respond_to? :length
22
- return collection.size if collection.respond_to? :size
23
- end
24
-
25
- def build_message(sym)
26
- message = "<#{@target.class.to_s}> should have"
27
- message += " at least" if @min
28
- message += " at most" if @max
29
- message += " #{@expected} #{sym} (has #{actual_size(collection(sym))})"
30
- end
31
-
32
- def as_specified?(sym)
33
- return actual_size(collection(sym)) >= @expected if @min
34
- return actual_size(collection(sym)) <= @expected if @max
35
- return actual_size(collection(sym)) == @expected
36
- end
37
-
38
- def at
39
- self
40
- end
41
-
42
- def least(min)
43
- @expected = min
44
- @min = true
45
- self
46
- end
47
-
48
- def most(max)
49
- @expected = max
50
- @max = true
51
- self
52
- end
53
-
54
- end
55
-
1
+ module Spec
2
+
3
+ class HaveHelper < ShouldBase
4
+
5
+ def initialize(target, expected=nil)
6
+ @target = target
7
+ @expected = expected == :no ? 0 : expected
8
+ @min = false
9
+ @max = false
10
+ end
11
+
12
+ def method_missing(sym, *args)
13
+ fail_with_message(build_message(sym)) unless as_specified?(sym)
14
+ end
15
+
16
+ def collection(sym)
17
+ @target.send(sym)
18
+ end
19
+
20
+ def actual_size(collection)
21
+ return collection.length if collection.respond_to? :length
22
+ return collection.size if collection.respond_to? :size
23
+ end
24
+
25
+ def build_message(sym)
26
+ message = "<#{@target.class.to_s}> should have"
27
+ message += " at least" if @min
28
+ message += " at most" if @max
29
+ message += " #{@expected} #{sym} (has #{actual_size(collection(sym))})"
30
+ end
31
+
32
+ def as_specified?(sym)
33
+ return actual_size(collection(sym)) >= @expected if @min
34
+ return actual_size(collection(sym)) <= @expected if @max
35
+ return actual_size(collection(sym)) == @expected
36
+ end
37
+
38
+ def at
39
+ self
40
+ end
41
+
42
+ def least(min)
43
+ @expected = min
44
+ @min = true
45
+ self
46
+ end
47
+
48
+ def most(max)
49
+ @expected = max
50
+ @max = true
51
+ self
52
+ end
53
+
54
+ end
55
+
56
56
  end
@@ -13,8 +13,12 @@ module Spec
13
13
  @options = DEFAULT_OPTIONS.dup.merge(options)
14
14
  @expectations = []
15
15
  end
16
+
17
+ def should
18
+ self
19
+ end
16
20
 
17
- def should_receive(sym, &block)
21
+ def receive(sym, &block)
18
22
  expected_from = caller(1)[0]
19
23
  expectation = MessageExpectation.new(@name, expected_from, sym, block_given? ? block : nil)
20
24
  @expectations << expectation
@@ -36,7 +40,10 @@ module Spec
36
40
  # act as null object if method is missing and we ignore them. return value too!
37
41
  @options[:null_object] ? self : super(sym, *args, &block)
38
42
  rescue NoMethodError
39
- raise Spec::Api::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with " + (args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", "))
43
+
44
+ arg_message = args.collect{|arg| "<#{arg}:#{arg.class.name}>"}.join(", ")
45
+
46
+ Kernel::raise Spec::Api::MockExpectationError, "Mock '#{@name}' received unexpected message '#{sym.to_s}' with [#{arg_message}]"
40
47
  end
41
48
  end
42
49
  end
@@ -62,10 +69,39 @@ module Spec
62
69
  @expected_received_count = 1
63
70
  @expected_params = nil
64
71
  @consecutive = false
72
+ @exception_to_raise = nil
73
+ @symbol_to_throw = nil
74
+ @any_seen = false
75
+ @at_seen = false
76
+ @and_seen = false
65
77
  end
66
78
 
67
79
  def matches(sym, args)
68
- @sym == sym and (@expected_params.nil? or @expected_params == args)
80
+ @sym == sym and (@expected_params.nil? or @expected_params == args or constraints_match?(args))
81
+ end
82
+
83
+ def constraints_match?(args)
84
+ return false if args.length != @expected_params.length
85
+ for i in 0...@expected_params.length
86
+ next if @expected_params[i] == :anything
87
+ next if @expected_params[i] == :numeric and args[i].is_a?Numeric
88
+ next if @expected_params[i] == :boolean and args[i].is_a?TrueClass or args[i].is_a?FalseClass
89
+ next if @expected_params[i] == :string and args[i].is_a?String
90
+ return false unless args[i] == @expected_params[i]
91
+ end
92
+ return true
93
+ end
94
+
95
+ def make_count_message(count)
96
+ return "at least #{pretty_print(count.abs)}" if count < 0
97
+ return pretty_print(count) if count > 0
98
+ return "never"
99
+ end
100
+
101
+ def pretty_print(count)
102
+ return "once" if count == 1
103
+ return "twice" if count == 2
104
+ return "#{count} times"
69
105
  end
70
106
 
71
107
  # This method is called at the end of a spec, after teardown.
@@ -73,8 +109,8 @@ module Spec
73
109
  # TODO: this doesn't provide good enough error messages to fix the error.
74
110
  # Error msg should tell exactly what went wrong. (AH).
75
111
 
76
- return if @expected_received_count == -2
77
- return if (@expected_received_count == -1) && (@received_count > 0)
112
+ return if @expected_received_count == :any
113
+ return if (@expected_received_count < 0) && (@received_count >= @expected_received_count.abs)
78
114
  return if @expected_received_count == @received_count
79
115
 
80
116
  expected_signature = nil
@@ -85,18 +121,14 @@ module Spec
85
121
  expected_signature = "#{@sym}(#{params})"
86
122
  end
87
123
 
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)
124
+ count_message = make_count_message(@expected_received_count)
93
125
 
94
126
  message = "Mock '#{@mock_name}' expected #{expected_signature} #{count_message}, but received it #{@received_count} times"
95
127
  begin
96
- raise Spec::Api::MockExpectationError, message
128
+ Kernel::raise Spec::Api::MockExpectationError, message
97
129
  rescue => error
98
130
  error.backtrace.insert(0, @expected_from)
99
- raise error
131
+ Kernel::raise error
100
132
  end
101
133
  end
102
134
 
@@ -106,18 +138,22 @@ module Spec
106
138
  begin
107
139
  result = @method_block.call(*args)
108
140
  rescue Spec::Api::ExpectationNotMetError => detail
109
- raise Spec::Api::MockExpectationError, "Call expectation violated with: " + $!
141
+ Kernel::raise Spec::Api::MockExpectationError, "Call expectation violated with: " + $!
110
142
  end
111
143
  @received_count += 1
112
144
  return result
113
145
  end
114
146
 
115
- unless @expected_params.nil? or @expected_params == args
116
- raise Spec::Api::MockExpectationError,
147
+ unless @expected_params.nil? or @expected_params == args or constraints_match?(args)
148
+ Kernel::raise Spec::Api::MockExpectationError,
117
149
  "#{@sym}: Parameter mismatch: Expected <#{@expected_params}>, got <#{args}>"
118
150
  end
119
151
  args << block unless block.nil?
120
152
  @received_count += 1
153
+
154
+ Kernel::raise @exception_to_raise.new unless @exception_to_raise.nil?
155
+ Kernel::throw @symbol_to_throw unless @symbol_to_throw.nil?
156
+
121
157
  value = @block.call(*args)
122
158
 
123
159
  return value unless @consecutive
@@ -126,29 +162,56 @@ module Spec
126
162
  end
127
163
 
128
164
  def with(*args)
129
- @expected_params = args
165
+ if args == [:anything] then @expected_params = nil
166
+ elsif args == [:nothing] then @expected_params = []
167
+ else @expected_params = args
168
+ end
169
+
130
170
  self
131
171
  end
132
-
133
- def with_no_args
134
- @expected_params = []
172
+
173
+ def at
174
+ @at_seen = true
135
175
  self
136
176
  end
137
-
138
- def with_any_args
139
- @expected_params = nil
177
+
178
+ def exactly(n)
179
+ @expected_received_count = n
140
180
  self
141
181
  end
142
-
143
- def at_least_once
144
- @expected_received_count = -1
182
+
183
+ def least(arg)
184
+ if @at_seen
185
+ @expected_received_count = -1 if arg == :once
186
+ @expected_received_count = -2 if arg == :twice
187
+ @expected_received_count = -arg if arg.kind_of? Numeric
188
+ end
189
+ @at_seen = false
145
190
  self
146
191
  end
147
192
 
148
- def any_number_of_times
149
- @expected_received_count = -2
150
- self
151
- end
193
+ def any
194
+ @any_seen = true
195
+ self
196
+ end
197
+
198
+ def number
199
+ @number_seen = @any_seen
200
+ @any_seen = false
201
+ self
202
+ end
203
+
204
+ def of
205
+ @of_seen = @number_seen
206
+ @number_seen = false
207
+ self
208
+ end
209
+
210
+ def times
211
+ @expected_received_count = :any if @of_seen
212
+ @of_seen = false
213
+ self
214
+ end
152
215
 
153
216
  def never
154
217
  @expected_received_count = 0
@@ -165,19 +228,29 @@ module Spec
165
228
  self
166
229
  end
167
230
 
168
- def returns(value=nil,&block)
169
- @block = block_given? ? block : proc { value }
231
+ def and
232
+ @and_seen = true
233
+ self
170
234
  end
171
235
 
172
- def returns_consecutively(value=[nil],&block)
173
- @consecutive = true
236
+ def return(value=nil,&block)
237
+ return self unless @and_seen
238
+ @and_seen = false
239
+ @consecutive = value.instance_of? Array
174
240
  @block = block_given? ? block : proc { value }
175
241
  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
242
+
243
+ def raise(exception=Exception)
244
+ return self unless @and_seen
245
+ @and_seen = false
246
+ @exception_to_raise = exception
247
+ end
248
+
249
+ def throw(symbol)
250
+ return self unless @and_seen
251
+ @and_seen = false
252
+ @symbol_to_throw = symbol
253
+ end
181
254
 
182
255
  end
183
256
  end