rspec 0.5.0 → 0.5.1

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