rspec 0.5.7 → 0.5.8
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 -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.
|