rspec 0.5.7 → 0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +9 -0
- data/Rakefile +7 -10
- data/bin/spec +1 -1
- data/bin/test2spec +93 -0
- data/doc/src/default.template +1 -1
- data/doc/src/documentation/index.page +37 -37
- data/doc/src/documentation/mocks.page +88 -60
- data/doc/src/tools/index.page +2 -2
- data/doc/src/tools/meta.info +1 -1
- data/doc/src/tools/test2spec.page +73 -0
- data/doc/src/tutorials/notes.txt +1 -1
- data/doc/src/tutorials/stack_01.page +4 -4
- data/doc/src/tutorials/stack_02.page +6 -6
- data/doc/src/tutorials/stack_03.page +8 -8
- data/doc/src/tutorials/stack_04.page +2 -2
- data/doc/src/tutorials/stack_05.page +1 -1
- data/lib/spec/api/sugar.rb +3 -3
- data/lib/spec/runner/base_text_formatter.rb +11 -5
- data/lib/spec/runner/option_parser.rb +1 -1
- data/lib/spec/runner/progress_bar_formatter.rb +1 -1
- data/lib/spec/runner/rdoc_formatter.rb +1 -1
- data/lib/spec/runner/reporter.rb +6 -3
- data/lib/spec/runner/specdoc_formatter.rb +1 -1
- data/lib/spec/runner/specification.rb +1 -0
- data/lib/spec/tool/ruby2ruby.rb +485 -0
- data/lib/spec/tool/test_unit_translator.rb +114 -83
- data/lib/spec/tool/translation_test_runner.rb +118 -0
- data/lib/spec/version.rb +1 -1
- data/test/spec/runner/context_test.rb +4 -0
- data/test/spec/runner/progress_bar_formatter_test.rb +1 -1
- data/test/spec/runner/rdoc_formatter_test.rb +1 -1
- data/test/spec/runner/reporter_test.rb +24 -7
- data/test/spec/runner/specdoc_formatter_test.rb +1 -1
- data/test/spec/runner/specification_test.rb +8 -0
- data/test/spec/tool/ruby_to_ruby_test.rb +79 -0
- data/test/spec/tool/test_unit_api_spec.rb +45 -31
- data/test/spec/tool/test_unit_api_test.rb +13 -6
- data/test/spec/tool/test_unit_translator_test.rb +6 -1
- metadata +11 -10
- data/bin/test2rspec +0 -35
- data/doc/src/tools/test2rspec.page +0 -13
- data/lib/spec/tool/command_line.rb +0 -39
- data/test/spec/tool/command_line_test.rb +0 -21
data/CHANGES
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
= RSpec Changelog
|
2
2
|
|
3
|
+
== Version 0.5.8
|
4
|
+
This release features a new Test::Unit to RSpec translation tool.
|
5
|
+
Also note that the RubyGem of the previous release (0.5.7) was corrupt.
|
6
|
+
We're close to being able to translate all of RSpec's own Test::Unit
|
7
|
+
tests and have them run successfully!
|
8
|
+
|
9
|
+
* Updated test2spec documentation.
|
10
|
+
* Replaced old test2rspec with a new test2spec, which is based on ParseTree and RubyInline.
|
11
|
+
|
3
12
|
== Version 0.5.7
|
4
13
|
This release changes examples and documentation to recommend underscores rather than dots,
|
5
14
|
and addresses some bugfixes and changes to the spec commandline.
|
data/Rakefile
CHANGED
@@ -25,7 +25,7 @@ PKG_FILES = FileList[
|
|
25
25
|
'test/**/*.rb',
|
26
26
|
'examples/**/*.rb',
|
27
27
|
'doc/**/*'
|
28
|
-
]
|
28
|
+
]
|
29
29
|
|
30
30
|
task :default => [:test]
|
31
31
|
|
@@ -51,12 +51,12 @@ task :doc do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
desc 'Generate RDoc'
|
54
|
-
rd = Rake::RDocTask.new
|
54
|
+
rd = Rake::RDocTask.new do |rdoc|
|
55
55
|
rdoc.rdoc_dir = 'doc/output/rdoc'
|
56
|
-
rdoc.title
|
57
|
-
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
56
|
+
rdoc.options << '--title' << 'RSpec' << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
58
57
|
rdoc.rdoc_files.include('README', 'CHANGES', 'EXAMPLES.rd', 'lib/**/*.rb')
|
59
58
|
end
|
59
|
+
task :rdoc => :examples_specdoc # We generate EXAMPLES.rd
|
60
60
|
|
61
61
|
spec = Gem::Specification.new do |s|
|
62
62
|
s.name = PKG_NAME
|
@@ -73,17 +73,14 @@ spec = Gem::Specification.new do |s|
|
|
73
73
|
s.require_path = 'lib'
|
74
74
|
|
75
75
|
s.has_rdoc = true
|
76
|
-
s.
|
77
|
-
s.
|
78
|
-
'--title' << 'RSpec' <<
|
79
|
-
'--main' << 'README' <<
|
80
|
-
'--line-numbers'
|
76
|
+
s.rdoc_options = rd.options
|
77
|
+
s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$|^EXAMPLES.rd$/ }.to_a
|
81
78
|
|
82
79
|
s.test_files = Dir.glob('test/*_test.rb')
|
83
80
|
s.require_path = 'lib'
|
84
81
|
s.autorequire = 'spec'
|
85
82
|
s.bindir = "bin"
|
86
|
-
s.executables = ["spec", "
|
83
|
+
s.executables = ["spec", "test2spec"]
|
87
84
|
s.default_executable = "spec"
|
88
85
|
s.author = "Steven Baker, Aslak Hellesoy, Dave Astels, David Chelimsky"
|
89
86
|
s.email = "rspec-devel@rubyforge.org"
|
data/bin/spec
CHANGED
@@ -5,7 +5,7 @@ $context_runner = ::Spec::Runner::OptionParser.create_context_runner(ARGV, false
|
|
5
5
|
|
6
6
|
# If ARGV is a glob, it will actually each over each one of the matching files.
|
7
7
|
ARGV.each do |file_or_dir|
|
8
|
-
if File.
|
8
|
+
if File.directory?(file_or_dir)
|
9
9
|
Dir["#{file_or_dir}/**/*.rb"].each do |file|
|
10
10
|
require "#{file}"
|
11
11
|
end
|
data/bin/test2spec
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'test/unit/ui/console/testrunner'
|
5
|
+
require 'test/unit/ui/testrunnerutilities'
|
6
|
+
require 'test/unit/ui/testrunnermediator'
|
7
|
+
require 'test/unit/autorunner'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
$LOAD_PATH.push File.dirname(__FILE__) + '/../lib'
|
11
|
+
|
12
|
+
require 'rubygems'
|
13
|
+
require 'spec/tool/translation_test_runner'
|
14
|
+
require 'spec/version'
|
15
|
+
|
16
|
+
$test2spec_options = {
|
17
|
+
:collision => :ask
|
18
|
+
}
|
19
|
+
|
20
|
+
opts = OptionParser.new do |opts|
|
21
|
+
opts.banner = "Usage: test2spec [options] (FILE|DIRECTORY|GLOB)+"
|
22
|
+
opts.separator ""
|
23
|
+
|
24
|
+
opts.on("-s", "--specdir DIRECTORY", "Directory where specs will be written") do |dir|
|
25
|
+
$test2spec_options[:specdir] = dir
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-c", "--chmod MODIFIERS", Integer, "Change file modifiers on written files (POSIX only)") do |mods|
|
29
|
+
$test2spec_options[:chmod] = mods
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("--svn", "Add written files to subversion") do
|
33
|
+
$test2spec_options[:svn] = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-f", "--force", "Forcefully overwrite existing specs") do
|
37
|
+
$test2spec_options[:collision] = :force
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-v", "--version", "Show version") do
|
41
|
+
puts "test2spec #{Spec::VERSION::DESCRIPTION}"
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-d", "--dry-run", "Don't write anything - just verify that translation works") do
|
46
|
+
options.dry_run = true
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on_tail("-h", "--help", "You're looking at it") do
|
50
|
+
puts opts
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.parse! ARGV
|
56
|
+
|
57
|
+
if($test2spec_options[:specdir].nil?)
|
58
|
+
STDERR.puts "ERROR: --specdir must be specified"
|
59
|
+
puts opts
|
60
|
+
exit 1
|
61
|
+
end
|
62
|
+
|
63
|
+
if(ARGV.empty?)
|
64
|
+
STDERR.puts "ERROR: At least one directory, file or glob must be specified"
|
65
|
+
puts opts
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
module Test
|
70
|
+
module Unit
|
71
|
+
class AutoRunner
|
72
|
+
def initialize(standalone)
|
73
|
+
@standalone = standalone
|
74
|
+
@runner = proc { |r| Spec::Tool::TranslationTestRunner }
|
75
|
+
@collector = COLLECTORS[(standalone ? :dir : :objectspace)]
|
76
|
+
@filters = []
|
77
|
+
@to_run = []
|
78
|
+
yield(self) if(block_given?)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# If ARGV is a glob, it will actually each over each one of the matching files.
|
85
|
+
ARGV.each do |arg|
|
86
|
+
if File.directory?(arg)
|
87
|
+
Dir["#{arg}/**/*.rb"].each do |file|
|
88
|
+
require "#{file}"
|
89
|
+
end
|
90
|
+
else
|
91
|
+
require arg
|
92
|
+
end
|
93
|
+
end
|
data/doc/src/default.template
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{lang:}">
|
4
4
|
<head>
|
5
5
|
<title>{title: }</title>
|
6
|
-
<link href="{relocatable: default.css}" rel="stylesheet" />
|
6
|
+
<link href="{relocatable: default.css}" rel="stylesheet" type="text/css" media="screen"/>
|
7
7
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
8
8
|
</head>
|
9
9
|
<body>
|
@@ -14,21 +14,21 @@ h3. General
|
|
14
14
|
h4. Arbitrary Block
|
15
15
|
|
16
16
|
<ruby>
|
17
|
-
target.
|
18
|
-
target.
|
17
|
+
target.should_satisfy {|arg| ...}
|
18
|
+
target.should_not_satisfy {|arg| ...}
|
19
19
|
</ruby>
|
20
20
|
|
21
21
|
The supplied block is evaluated, passing <code>target</code> as the sole argument. If the block evaluates to <code>false</code>, <code>ExpectationNotMetError</code> is raised.
|
22
22
|
|
23
23
|
<ruby>
|
24
|
-
target.
|
24
|
+
target.should_satisfy {|arg| arg > 0}
|
25
25
|
</ruby>
|
26
26
|
|
27
27
|
h4. Equality
|
28
28
|
|
29
29
|
<ruby>
|
30
|
-
target.
|
31
|
-
target.
|
30
|
+
target.should_equal <value>
|
31
|
+
target.should_not_equal <value>
|
32
32
|
</ruby>
|
33
33
|
|
34
34
|
The target object is compared to <code>value</code> using ==. If the result is <code>false</code>, <code>ExpectationNotMetError</code> is raised.
|
@@ -36,21 +36,21 @@ The target object is compared to <code>value</code> using ==. If the result is <
|
|
36
36
|
h4. Floating Point Comparison
|
37
37
|
|
38
38
|
<ruby>
|
39
|
-
target.
|
40
|
-
target.
|
39
|
+
target.should_be_close <value>, <tolerance>
|
40
|
+
target.should_not_be_close <value>, <tolerance>
|
41
41
|
</ruby>
|
42
42
|
|
43
43
|
The target object is compared to <code>value</code>. If they differ by more that <code>tolerance</code>, <code>ExpectationNotMetError</code> is raised. In the negated case, <code>ExpectationNotMetError</code> is raised if they differ by less than <code>tolerance</code>.
|
44
44
|
|
45
45
|
<ruby>
|
46
|
-
target.
|
46
|
+
target.should_be_close 27.35, 0.05
|
47
47
|
</ruby>
|
48
48
|
|
49
49
|
h4. Identity
|
50
50
|
|
51
51
|
<ruby>
|
52
|
-
target.
|
53
|
-
target.
|
52
|
+
target.should_be <value>
|
53
|
+
target.should_not_be <value>
|
54
54
|
</ruby>
|
55
55
|
|
56
56
|
The target object is compared to <code>value</code> using <code>equal?</code>. If the result is <code>false</code>, <code>ExpectationNotMetError</code> is raised.
|
@@ -58,10 +58,10 @@ The target object is compared to <code>value</code> using <code>equal?</code>. I
|
|
58
58
|
h4. Arbitrary Predicate
|
59
59
|
|
60
60
|
<ruby>
|
61
|
-
target.
|
62
|
-
target.
|
63
|
-
target.
|
64
|
-
target.
|
61
|
+
target.should_predicate [optional args]
|
62
|
+
target.should_be_predicate [optional args]
|
63
|
+
target.should_not_predicate [optional args]
|
64
|
+
target.should_not_be_predicate [optional args]
|
65
65
|
</ruby>
|
66
66
|
|
67
67
|
The message <code>predicate?</code> is sent to <code>target</code> with any supplied arguments. If the result is <code>false</code>, <code>ExpectationNotMetError</code> is raised.
|
@@ -69,15 +69,15 @@ The message <code>predicate?</code> is sent to <code>target</code> with any supp
|
|
69
69
|
For example:
|
70
70
|
|
71
71
|
<ruby>
|
72
|
-
container.
|
73
|
-
container.
|
72
|
+
container.should_include('a') => container.include?('a')
|
73
|
+
container.should_be_empty => container.empty?
|
74
74
|
</ruby>
|
75
75
|
|
76
76
|
h4. Pattern Matching
|
77
77
|
|
78
78
|
<ruby>
|
79
|
-
target.
|
80
|
-
target.
|
79
|
+
target.should_match <regex>
|
80
|
+
target.should_not_match <regex>
|
81
81
|
</ruby>
|
82
82
|
|
83
83
|
The <code>target</code> is matched against <code>regex</code>. An <code>ExpectationNotMetError</code> is raised if the match fails.
|
@@ -87,8 +87,8 @@ h3. Class/Type
|
|
87
87
|
h4. Direct Instance
|
88
88
|
|
89
89
|
<ruby>
|
90
|
-
target.
|
91
|
-
target.
|
90
|
+
target.should_be_an_instance_of <class>
|
91
|
+
target.should_not_be_an_instance_of <class>
|
92
92
|
</ruby>
|
93
93
|
|
94
94
|
An <code>ExpectationNotMetError</code> is raised if <code>target</code> is not or is, respectively, an direct instance of <code>class</code>. As expected this correlates to <code>target.instance_of? class</code>.
|
@@ -96,8 +96,8 @@ An <code>ExpectationNotMetError</code> is raised if <code>target</code> is not o
|
|
96
96
|
h4. Ancestor Class
|
97
97
|
|
98
98
|
<ruby>
|
99
|
-
target.
|
100
|
-
target.
|
99
|
+
target.should_be_a_kind_of <class>
|
100
|
+
target.should_not_be_a_kind_of <class>
|
101
101
|
</ruby>
|
102
102
|
|
103
103
|
As above, but uses <code>target.kind_of? class</code>: checking whether <code>class</code> is the direct class of <code>target</code>, or an ancestor of <code>target</code>'s direct class.
|
@@ -105,8 +105,8 @@ As above, but uses <code>target.kind_of? class</code>: checking whether <code>cl
|
|
105
105
|
h4. Type
|
106
106
|
|
107
107
|
<ruby>
|
108
|
-
target.
|
109
|
-
target.
|
108
|
+
target.should_respond_to <symbol>
|
109
|
+
target.should_not_respond_to <symbol>
|
110
110
|
</ruby>
|
111
111
|
|
112
112
|
Uses <code>target.respond_to?(symbol)</code> to check whether <code>symbol</code> is the name of a message that <code>target</code> understands.
|
@@ -116,21 +116,21 @@ h3. Procs
|
|
116
116
|
h4. Raising
|
117
117
|
|
118
118
|
<ruby>
|
119
|
-
proc.
|
120
|
-
proc.
|
119
|
+
proc.should_raise <exception>
|
120
|
+
proc.should_not_raise <exception>
|
121
121
|
</ruby>
|
122
122
|
|
123
123
|
Checks that <code>proc</code> causes the named exception to be raised or not. The latter is actually one of two cases: some other exception is raised, or no exception is raised. Typically the <code>proc</code> is created in place using <code>lambda</code>. For example:
|
124
124
|
|
125
125
|
<ruby>
|
126
|
-
lambda { 3 / 0 }.
|
126
|
+
lambda { 3 / 0 }.should_raise ZeroDivisionError
|
127
127
|
</ruby>
|
128
128
|
|
129
129
|
There is a more general form as well.
|
130
130
|
|
131
131
|
<ruby>
|
132
|
-
proc.
|
133
|
-
proc.
|
132
|
+
proc.should_raise
|
133
|
+
proc.should_not_raise
|
134
134
|
</ruby>
|
135
135
|
|
136
136
|
These forms don't worry about what exception is raised (or not). All they are concerned with is that some except was raised, or that no exception was.
|
@@ -138,14 +138,14 @@ These forms don't worry about what exception is raised (or not). All they are co
|
|
138
138
|
h4. Throwing
|
139
139
|
|
140
140
|
<ruby>
|
141
|
-
proc.
|
142
|
-
proc.
|
141
|
+
proc.should_throw <symbol>
|
142
|
+
proc.should_not_throw <symbol>
|
143
143
|
</ruby>
|
144
144
|
|
145
145
|
Similar to the above, but checks that <code>symbol</code> is thrown from within <code>proc</code>, or not. The latter is actually one of two cases: some other symbol is thrown, or no symbol is thrown.
|
146
146
|
|
147
147
|
<ruby>
|
148
|
-
proc.
|
148
|
+
proc.should_not_throw
|
149
149
|
</ruby>
|
150
150
|
|
151
151
|
This form is more specific. It checks that no symbol is thrown from within <code>proc</code>.
|
@@ -155,8 +155,8 @@ h3. Collections
|
|
155
155
|
h4. Containment
|
156
156
|
|
157
157
|
<ruby>
|
158
|
-
target.
|
159
|
-
target.
|
158
|
+
target.should_include <object>
|
159
|
+
target.should_not_include <object>
|
160
160
|
</ruby>
|
161
161
|
|
162
162
|
This is simply a specific case of the arbitrary predicate form. It uses <code>target.include?(object)</code> and raises an <code>ExpectationNotMetError</code> if that returns false.
|
@@ -166,7 +166,7 @@ The remaining collection forms are a little more involved. They rely on two thin
|
|
166
166
|
h4. Exact Size
|
167
167
|
|
168
168
|
<ruby>
|
169
|
-
target.
|
169
|
+
target.should_have(<number>).things
|
170
170
|
</ruby>
|
171
171
|
|
172
172
|
The <code>things</code> of <code>target</code> has a length/size of exactly <code>number</code>.
|
@@ -174,7 +174,7 @@ The <code>things</code> of <code>target</code> has a length/size of exactly <cod
|
|
174
174
|
h4. Lower Bound
|
175
175
|
|
176
176
|
<ruby>
|
177
|
-
target.
|
177
|
+
target.should_have_at_least(<number>).things
|
178
178
|
</ruby>
|
179
179
|
|
180
180
|
The <code>things</code> of <code>target</code> has a length/size of no less than <code>number</code>.
|
@@ -182,7 +182,7 @@ The <code>things</code> of <code>target</code> has a length/size of no less than
|
|
182
182
|
h4. Upper Bound
|
183
183
|
|
184
184
|
<ruby>
|
185
|
-
target.
|
185
|
+
target.should_have_at_most(<number>).things
|
186
186
|
</ruby>
|
187
187
|
|
188
188
|
The <code>things</code> of <code>target</code> has a length/size of no more than <code>number</code>.
|
@@ -4,7 +4,7 @@ inMenu: true
|
|
4
4
|
---
|
5
5
|
h2. Mock API
|
6
6
|
|
7
|
-
RSpec contains a
|
7
|
+
RSpec contains a tightly integrated, powerful Mock Object framework.
|
8
8
|
|
9
9
|
h3. Creating a mock
|
10
10
|
|
@@ -12,13 +12,17 @@ h3. Creating a mock
|
|
12
12
|
my_mock = mock(<name>)
|
13
13
|
</ruby>
|
14
14
|
|
15
|
-
This creates a new mock with the given <code>name</code> (a string) and registers it.
|
15
|
+
This creates a new mock with the given <code>name</code> (a string) and registers it.
|
16
|
+
When the specification finishes, all registered mocks are verified.
|
16
17
|
|
17
18
|
<ruby>
|
18
19
|
my_mock = mock(<name>, <options>)
|
19
20
|
</ruby>
|
20
21
|
|
21
|
-
As above, but allows you to specific options to tweak the mock's behaviour. The
|
22
|
+
As above, but allows you to specific options to tweak the mock's behaviour. The
|
23
|
+
<code>options</code> argument is a hash. Currently the only supported option is
|
24
|
+
<code>:null_object</code>. Setting this to true instructs the mock to ignore
|
25
|
+
(quietly consume) any messages it hasn't been told to expect - and return itself. I.e.:
|
22
26
|
|
23
27
|
<ruby>
|
24
28
|
my_mock = mock("blah", :null_object => true)
|
@@ -27,59 +31,52 @@ my_mock = mock("blah", :null_object => true)
|
|
27
31
|
h3. Expecting Messages
|
28
32
|
|
29
33
|
<ruby>
|
30
|
-
my_mock.
|
34
|
+
my_mock.should_receive(<message>)
|
31
35
|
</ruby>
|
32
36
|
|
33
|
-
The <code>message</code> argument is a symbol that is the name of a message
|
34
|
-
|
35
|
-
h3. Arbitrary Handling of Received Messages
|
36
|
-
|
37
|
-
You can supply a block to a message expectation. When the message is received
|
38
|
-
by the mock, the block is evaluated, and passed any arguments. The result is
|
39
|
-
the return value of the message. For example:
|
40
|
-
|
41
|
-
<ruby>
|
42
|
-
my_mock.should_receivereceive(:random_call) {| a | a.should_receivebe true}
|
43
|
-
</ruby>
|
44
|
-
|
45
|
-
This allows arbitrary argument validation and result computation. It's handy and kind of cool to be able to do this, but I advise against it. Mocks should not be functional. they should be completely declarative. That said, it's sometimes useful to give them some minimal behaviour.
|
37
|
+
The <code>message</code> argument is a symbol that is the name of a message
|
38
|
+
that you want the mock to expect.
|
46
39
|
|
47
40
|
h3. Expecting Arguments
|
48
41
|
|
49
42
|
<ruby>
|
50
|
-
my_mock.
|
43
|
+
my_mock.should_receive(:msg).with(<args>)
|
51
44
|
</ruby>
|
52
45
|
|
53
46
|
for example:
|
54
47
|
|
55
48
|
<ruby>
|
56
|
-
my_mock.
|
49
|
+
my_mock.should_receive(:msg).with(1, 2, 3)
|
57
50
|
</ruby>
|
58
51
|
|
59
|
-
The <code>args</code> argument is a series of arguments (e.g. 1, 2, 3) that are
|
52
|
+
The <code>args</code> argument is a series of arguments (e.g. 1, 2, 3) that are
|
53
|
+
expected to be passed as arguments to the associated message.
|
60
54
|
|
61
55
|
<ruby>
|
62
|
-
my_mock.
|
56
|
+
my_mock.should_receive(:msg).with(:no_args)
|
63
57
|
</ruby>
|
64
58
|
|
65
59
|
The message (<code>msg</code>) is expected to be passed no arguments.
|
66
60
|
|
67
61
|
<ruby>
|
68
|
-
my_mock.
|
62
|
+
my_mock.should_receive(:msg).with(:any_args)
|
69
63
|
</ruby>
|
70
64
|
|
71
|
-
Any arguments (and any number of arguments) are to be accepted. This includes
|
65
|
+
Any arguments (and any number of arguments) are to be accepted. This includes
|
66
|
+
cases where no arguments are provided. *This is the default when no <code>with()</code>
|
67
|
+
clause is specified.* Even so, sometimes you want to be explicit about it.
|
72
68
|
|
73
69
|
h3. Argument Constraints
|
74
70
|
|
75
|
-
Constraints can be placed on individual arguments which are looser than value
|
71
|
+
Constraints can be placed on individual arguments which are looser than value
|
72
|
+
equivalence (as above).
|
76
73
|
|
77
74
|
h4. :anything
|
78
75
|
|
79
76
|
accepts any value for this argument, e.g.:
|
80
77
|
|
81
78
|
<ruby>
|
82
|
-
my_mock.
|
79
|
+
my_mock.should_receive(:msg).with(1, :anything, "A")
|
83
80
|
</ruby>
|
84
81
|
|
85
82
|
h4. :numeric
|
@@ -87,7 +84,7 @@ h4. :numeric
|
|
87
84
|
accepts any numeric value for this argument, e.g.:
|
88
85
|
|
89
86
|
<ruby>
|
90
|
-
my_mock.
|
87
|
+
my_mock.should_receive(:msg).with(a, :numeric, "b")
|
91
88
|
</ruby>
|
92
89
|
|
93
90
|
h4. :boolean
|
@@ -95,7 +92,7 @@ h4. :boolean
|
|
95
92
|
accepts a boolean value for this argument, e.g.:
|
96
93
|
|
97
94
|
<ruby>
|
98
|
-
my_mock.
|
95
|
+
my_mock.should_receive(:msg).with(a, :boolean, "b")
|
99
96
|
</ruby>
|
100
97
|
|
101
98
|
h4. :string
|
@@ -103,7 +100,7 @@ h4. :string
|
|
103
100
|
accepts any string for this argument, e.g.:
|
104
101
|
|
105
102
|
<ruby>
|
106
|
-
my_mock.
|
103
|
+
my_mock.should_receive(:msg).with(a, :string, "b")
|
107
104
|
</ruby>
|
108
105
|
|
109
106
|
h4. duck_type(message(s))
|
@@ -112,55 +109,57 @@ accepts any object that responds to the prescribed message(s), e.g.:
|
|
112
109
|
|
113
110
|
<ruby>
|
114
111
|
#accepts a Fixnum for the second arg
|
115
|
-
my_mock.
|
112
|
+
my_mock.should_receive(:msg).with(a, duck_type(:abs, :div), "b")
|
116
113
|
</ruby>
|
117
114
|
|
118
115
|
h3. Receive Counts
|
119
116
|
|
120
117
|
<ruby>
|
121
|
-
my_mock.
|
118
|
+
my_mock.should_receive(:msg).never
|
122
119
|
</ruby>
|
123
120
|
|
124
121
|
An exception is raised if the message is ever received.
|
122
|
+
This is equivalent to not specifying the reception of :msg,
|
123
|
+
but it's more declarative and useful for humans.
|
125
124
|
|
126
125
|
<ruby>
|
127
|
-
my_mock.
|
126
|
+
my_mock.should_receive(:msg).any_number_of_times
|
128
127
|
</ruby>
|
129
128
|
|
130
129
|
The message can be received 0 or more times.
|
131
130
|
|
132
131
|
<ruby>
|
133
|
-
my_mock.
|
132
|
+
my_mock.should_receive(:msg).once
|
134
133
|
</ruby>
|
135
134
|
|
136
135
|
An exception is raised if the message is never received, or it is received more than once.
|
137
136
|
|
138
137
|
<ruby>
|
139
|
-
my_mock.
|
138
|
+
my_mock.should_receive(:msg).twice
|
140
139
|
</ruby>
|
141
140
|
|
142
141
|
An exception is raised if the message is received anything but two times.
|
143
142
|
|
144
143
|
<ruby>
|
145
|
-
my_mock.
|
144
|
+
my_mock.should_receive(:msg).exactly(n).times
|
146
145
|
</ruby>
|
147
146
|
|
148
147
|
An exception is raised if the message is received anything but <code>n</code> times.
|
149
148
|
|
150
149
|
<ruby>
|
151
|
-
my_mock.
|
150
|
+
my_mock.should_receive(:msg).at_least(:once)
|
152
151
|
</ruby>
|
153
152
|
|
154
153
|
An exception is raised if the message is never received.
|
155
154
|
|
156
155
|
<ruby>
|
157
|
-
my_mock.
|
156
|
+
my_mock.should_receive(:msg).at_least(:twice)
|
158
157
|
</ruby>
|
159
158
|
|
160
159
|
An exception is raised if the message is never received or is received only once.
|
161
160
|
|
162
161
|
<ruby>
|
163
|
-
my_mock.
|
162
|
+
my_mock.should_receive(:msg).at_least(n).times
|
164
163
|
</ruby>
|
165
164
|
|
166
165
|
An exception is raised if the message is received fewer than <code>n</code> times.
|
@@ -170,7 +169,7 @@ h3. Return Values
|
|
170
169
|
h4. Single return value
|
171
170
|
|
172
171
|
<ruby>
|
173
|
-
my_mock.
|
172
|
+
my_mock.should_receive(:msg).once_and_return(<value>)
|
174
173
|
</ruby>
|
175
174
|
|
176
175
|
Each time the expected message is received, <code>value</code> will be returned as the result.
|
@@ -178,45 +177,51 @@ Each time the expected message is received, <code>value</code> will be returned
|
|
178
177
|
h4. Consequtive return values
|
179
178
|
|
180
179
|
<ruby>
|
181
|
-
|
180
|
+
and_return([<value-1>, <value-2>, ..., <value-n>])
|
182
181
|
</ruby>
|
183
182
|
|
184
|
-
When the expected message is received, <code>value-i</code> will be returned as the result
|
183
|
+
When the expected message is received, <code>value-i</code> will be returned as the result
|
184
|
+
for the ith reception of the message. After the message has been received <code>i</code> times,
|
185
|
+
<code>value-n</code> is returned for all
|
185
186
|
subsequent receives.
|
186
187
|
|
187
|
-
*Note:* if you wish to have a single return value that is an array, you must use this form, with
|
188
|
+
*Note:* if you wish to have a single return value that is an array, you must use this form, with
|
189
|
+
one item that is the array to return. Otherwise your array will be interpreted as a series of return values.
|
190
|
+
For example:
|
188
191
|
|
189
192
|
<ruby>
|
190
|
-
|
193
|
+
and_return([[1, 2, 3]])
|
191
194
|
</ruby>
|
192
195
|
|
193
196
|
h4. Computed return value
|
194
197
|
|
195
198
|
<ruby>
|
196
|
-
my_mock.
|
199
|
+
my_mock.should_receive(:msg).once_and_return {...}
|
197
200
|
</ruby>
|
198
201
|
|
199
202
|
When the expected message is received, the result of evaluating the supplied
|
200
203
|
block will be returned as the result. The block is passed any arguments passed
|
201
|
-
as arguments of the message. This capability can be used to compute return
|
204
|
+
as arguments of the message. This capability can be used to compute return
|
205
|
+
values based on the arguments. For example:
|
202
206
|
|
203
207
|
<ruby>
|
204
|
-
my_mock.
|
208
|
+
my_mock.should_receive(:msg).with(:numeric, :numeric) once_and_return {|a, b| a + b}
|
205
209
|
</ruby>
|
206
210
|
|
207
211
|
h3. Raising and Throwing
|
208
212
|
|
209
213
|
<ruby>
|
210
|
-
my_mock.
|
211
|
-
my_mock.
|
214
|
+
my_mock.should_receive(:msg).once_and_raise(<exception>)
|
215
|
+
my_mock.should_receive(:msg).once_and_throw(<symbol>)
|
212
216
|
</ruby>
|
213
217
|
|
214
|
-
These instruct the mock to raise an exception or throw a symbol, respectively,
|
218
|
+
These instruct the mock to raise an exception or throw a symbol, respectively,
|
219
|
+
instead of returning a value.
|
215
220
|
|
216
221
|
h3. Yielding
|
217
222
|
|
218
223
|
<ruby>
|
219
|
-
my_mock.
|
224
|
+
my_mock.should_receive(:msg).once_and_yield([<value-1>, <value-2>, ..., <value-n>])
|
220
225
|
</ruby>
|
221
226
|
|
222
227
|
When the expected message is received, the mock will yield the values to the passed block.
|
@@ -229,8 +234,8 @@ It shouldn't be the case very often, but it can be handy at times.
|
|
229
234
|
Labeling expectations as being ordered is done by the <code>ordered</code> call:
|
230
235
|
|
231
236
|
<ruby>
|
232
|
-
my_mock.
|
233
|
-
my_mock.
|
237
|
+
my_mock.should_receive(:flip).once.ordered
|
238
|
+
my_mock.should_receive(:flop).once.ordered
|
234
239
|
</ruby>
|
235
240
|
|
236
241
|
If the send of <code>flop</code> is seen before <code>flip</code> the specification will fail.
|
@@ -238,22 +243,45 @@ If the send of <code>flop</code> is seen before <code>flip</code> the specificat
|
|
238
243
|
Of course, chains of ordered expectations can be set up:
|
239
244
|
|
240
245
|
<ruby>
|
241
|
-
my_mock.
|
242
|
-
my_mock.
|
243
|
-
my_mock.
|
246
|
+
my_mock.should_receive(:one).ordered
|
247
|
+
my_mock.should_receive(:two).ordered
|
248
|
+
my_mock.should_receive(:three).ordered
|
244
249
|
</ruby>
|
245
250
|
|
246
251
|
The expected order is the order in which the expectations are declared.
|
247
252
|
|
248
|
-
Order-
|
253
|
+
Order-independent expectations can be set anywhere in the expectation sequence, in any order.
|
254
|
+
Only the order of expectations tagged with the <code>ordered</code> call is significant.
|
255
|
+
Likewise, calls to order-independent methods can be made in any order, even interspersed with
|
256
|
+
calls to order-dependent methods. For example:
|
249
257
|
|
250
258
|
<ruby>
|
251
|
-
my_mock.
|
252
|
-
my_mock.
|
253
|
-
my_mock.
|
254
|
-
my_mock.
|
259
|
+
my_mock.should_receive(:zero)
|
260
|
+
my_mock.should_receive(:one).ordered
|
261
|
+
my_mock.should_receive(:two).ordered
|
262
|
+
my_mock.should_receive(:one_and_a_half)
|
263
|
+
|
264
|
+
# This will pass:
|
255
265
|
my_mock.one
|
256
266
|
my_mock.one_and_a_half
|
257
267
|
my_mock.zero
|
258
268
|
my_mock.two
|
259
|
-
</ruby>
|
269
|
+
</ruby>
|
270
|
+
|
271
|
+
h3. Arbitrary Handling of Received Messages
|
272
|
+
|
273
|
+
You can supply a block to a message expectation. When the message is received
|
274
|
+
by the mock, the block is passed any arguments and evaluated. The result is
|
275
|
+
the return value of the block. For example:
|
276
|
+
|
277
|
+
<ruby>
|
278
|
+
my_mock.should_receive(:msg) { |a, b|
|
279
|
+
a.should_be true
|
280
|
+
b.should_not_contain('mice')
|
281
|
+
"Chunky bacon!"
|
282
|
+
}
|
283
|
+
</ruby>
|
284
|
+
|
285
|
+
This allows arbitrary argument validation and result computation. It's handy and kind of cool to be able to
|
286
|
+
do this, but it is advised to not use this form in most situations. Mocks should not be functional.
|
287
|
+
They should be completely declarative. That said, it's sometimes useful to give them some minimal behaviour.
|