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.
- data/CHANGES +9 -5
- data/Rakefile +35 -29
- data/bin/spec +0 -5
- data/doc/README +5 -0
- data/doc/config.yaml +2 -0
- data/doc/plugin/syntax.rb +38 -0
- data/doc/reference/rspec reference.page +0 -0
- data/doc/src/community.page +8 -0
- data/doc/src/default.css +198 -0
- data/doc/src/default.template +34 -0
- data/doc/src/documentation/api.page +251 -0
- data/doc/src/documentation/index.page +8 -0
- data/doc/src/documentation/mocks.page +207 -0
- data/doc/src/documentation/specs.page +20 -0
- data/doc/src/download.page +8 -0
- data/doc/src/examples.page +9 -0
- data/doc/src/images/ul.gif +0 -0
- data/doc/src/index.page +8 -0
- data/doc/src/tools/index.page +8 -0
- data/doc/src/tools/rails.page +8 -0
- data/doc/src/tools/rake.page +8 -0
- data/doc/src/tools/rcov.page +8 -0
- data/doc/src/tools/spec_runner.page +8 -0
- data/doc/src/tools/specdoc.page +8 -0
- data/doc/src/tools/test2rspec.page +8 -0
- data/doc/src/ul.gif +0 -0
- data/doc/src/why_rspec.page +8 -0
- data/examples/mocking_spec.rb +2 -2
- data/examples/spec_framework_spec.rb +4 -4
- data/lib/spec/api/helper/have_helper.rb +55 -55
- data/lib/spec/api/mock.rb +111 -38
- data/lib/spec/runner/backtrace_tweaker.rb +4 -4
- data/lib/spec/runner/context.rb +2 -1
- data/lib/spec/runner/context_runner.rb +3 -3
- data/lib/spec/runner/option_parser.rb +8 -4
- data/lib/spec/runner/simple_text_reporter.rb +29 -19
- data/lib/spec/runner/specification.rb +2 -1
- data/lib/spec/version.rb +1 -1
- data/test/rake/rcov_testtask.rb +45 -0
- data/test/spec/api/helper/arbitrary_predicate_test.rb +39 -24
- data/test/spec/api/helper/equality_test.rb +19 -0
- data/test/spec/api/helper/should_have_test.rb +183 -0
- data/test/spec/api/mock_arg_constraints_test.rb +90 -0
- data/test/spec/api/mock_test.rb +101 -21
- data/test/spec/runner/context_runner_test.rb +3 -3
- data/test/spec/runner/context_test.rb +2 -5
- data/test/spec/runner/execution_context_test.rb +1 -1
- data/test/spec/runner/option_parser_test.rb +16 -8
- data/test/spec/runner/simple_text_reporter_test.rb +57 -33
- data/test/spec/runner/specification_test.rb +7 -7
- data/test/spec/tool/command_line_test.rb +4 -4
- data/test/test_helper.rb +2 -2
- metadata +37 -8
- data/README +0 -38
- data/TODO +0 -9
- data/TUTORIAL +0 -259
- 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
|
Binary file
|
data/doc/src/index.page
ADDED
data/doc/src/ul.gif
ADDED
Binary file
|
data/examples/mocking_spec.rb
CHANGED
@@ -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.
|
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.
|
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
|
data/lib/spec/api/mock.rb
CHANGED
@@ -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
|
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
|
-
|
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 ==
|
77
|
-
return if (@expected_received_count
|
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 =
|
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 =
|
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
|
134
|
-
@
|
172
|
+
|
173
|
+
def at
|
174
|
+
@at_seen = true
|
135
175
|
self
|
136
176
|
end
|
137
|
-
|
138
|
-
def
|
139
|
-
@
|
177
|
+
|
178
|
+
def exactly(n)
|
179
|
+
@expected_received_count = n
|
140
180
|
self
|
141
181
|
end
|
142
|
-
|
143
|
-
def
|
144
|
-
@
|
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
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
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
|
169
|
-
@
|
231
|
+
def and
|
232
|
+
@and_seen = true
|
233
|
+
self
|
170
234
|
end
|
171
235
|
|
172
|
-
def
|
173
|
-
|
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
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
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
|