rspec 0.5.2 → 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -2
- data/Rakefile +22 -30
- data/doc/src/default.css +11 -10
- data/doc/src/documentation/api.page +15 -82
- data/doc/src/documentation/mocks.page +12 -55
- data/doc/src/meta.info +4 -1
- data/examples/airport_spec.rb +0 -1
- data/examples/empty_stack_spec.rb +1 -0
- data/examples/stack_spec.rb +1 -0
- data/examples/team_spec.rb +30 -0
- data/lib/spec/api.rb +1 -0
- data/lib/spec/api/duck_type.rb +16 -0
- data/lib/spec/api/expectations.rb +4 -4
- data/lib/spec/api/mock.rb +1 -0
- data/lib/spec/runner/backtrace_tweaker.rb +1 -2
- data/lib/spec/runner/context.rb +2 -3
- data/lib/spec/runner/context_runner.rb +2 -2
- data/lib/spec/runner/execution_context.rb +4 -0
- data/lib/spec/runner/option_parser.rb +3 -2
- data/lib/spec/runner/simple_text_reporter.rb +11 -25
- data/lib/spec/runner/specification.rb +1 -2
- data/lib/spec/version.rb +1 -1
- data/test/{rake → rcov}/rcov_testtask.rb +4 -4
- data/test/rcov/rcov_verify.rb +28 -0
- data/test/spec/api/duck_type_test.rb +19 -0
- data/test/spec/api/mock_arg_constraints_test.rb +20 -0
- data/test/spec/runner/backtrace_tweaker_test.rb +16 -8
- data/test/spec/runner/context_runner_test.rb +3 -3
- data/test/spec/runner/context_test.rb +2 -2
- data/test/spec/runner/execution_context_test.rb +7 -0
- data/test/spec/runner/option_parser_test.rb +12 -2
- data/test/spec/runner/simple_text_reporter_test.rb +18 -47
- data/test/spec/runner/specification_test.rb +5 -5
- data/test/spec/tool/command_line_test.rb +0 -1
- data/test/test_helper.rb +1 -0
- metadata +9 -7
- data/doc/src/download.page +0 -7
data/CHANGES
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
= RSpec Changelog
|
2
2
|
|
3
|
+
== Version 0.5.3
|
4
|
+
The "hurry up, CoR is in two days" release.
|
5
|
+
|
6
|
+
* Don't run rcov by default [aslak_hellesoy]
|
7
|
+
* Make separate task for running tests with RCov [aslak_hellesoy]
|
8
|
+
* Added Rake task to fail build if coverage drops below a certain threshold [aslak_hellesoy]
|
9
|
+
* Even more failure output cleanup (simplification) [dchelimsky]
|
10
|
+
* Added duck_type constraint for mocks [dchelimsky]
|
11
|
+
|
3
12
|
== Version 0.5.2
|
4
13
|
This release has minor improvements to the commandline and fixes some gem warnings
|
5
14
|
|
@@ -18,8 +27,7 @@ This release is the first release of RSpec with a new website. It will look bett
|
|
18
27
|
* Various improvements to failure reporting [dchelimsky]
|
19
28
|
|
20
29
|
== Version 0.5.0
|
21
|
-
|
22
|
-
This release introduces a new API and obsoletes previous versions.
|
30
|
+
This release introduces a new API and obsolesces previous versions.
|
23
31
|
|
24
32
|
* Moved source code to separate subfolders
|
25
33
|
* Added new DSL runner based on instance_exec
|
data/Rakefile
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
$:.unshift('lib')
|
2
2
|
require 'rubygems'
|
3
|
-
require 'meta_project'
|
4
3
|
require 'rake/gempackagetask'
|
5
4
|
require 'rake/contrib/rubyforgepublisher'
|
6
|
-
require 'rake/contrib/xforge'
|
7
5
|
require 'rake/clean'
|
8
6
|
require 'rake/testtask'
|
9
7
|
require 'rake/rdoctask'
|
10
8
|
require 'lib/spec/version'
|
11
9
|
require 'lib/spec/rake/spectask'
|
12
|
-
require 'test/
|
10
|
+
require 'test/rcov/rcov_testtask'
|
11
|
+
require 'test/rcov/rcov_verify'
|
13
12
|
|
14
13
|
PKG_NAME = "rspec"
|
15
14
|
# Versioning scheme: MAJOR.MINOR.PATCH
|
@@ -36,13 +35,16 @@ Spec::Rake::SpecTask.new do |t|
|
|
36
35
|
end
|
37
36
|
|
38
37
|
Rake::TestTask.new do |t|
|
39
|
-
t.libs << "test"
|
40
38
|
t.test_files = FileList['test/**/*_test.rb']
|
41
39
|
t.verbose = true
|
42
40
|
end
|
43
41
|
|
44
|
-
|
45
|
-
|
42
|
+
RCov::TestTask.new do |t|
|
43
|
+
t.test_files = FileList['test/**/*_test.rb']
|
44
|
+
t.verbose = true
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'Generate HTML documentation'
|
46
48
|
task :doc do
|
47
49
|
sh %{pushd doc; webgen; popd }
|
48
50
|
end
|
@@ -52,19 +54,11 @@ rd = Rake::RDocTask.new("rdoc") do |rdoc|
|
|
52
54
|
rdoc.rdoc_dir = 'doc/output/rdoc'
|
53
55
|
rdoc.title = "RSpec"
|
54
56
|
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
55
|
-
rdoc.rdoc_files.include('CHANGES')
|
57
|
+
rdoc.rdoc_files.include('README', 'CHANGES')
|
56
58
|
rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc')
|
57
|
-
rdoc.rdoc_files.exclude('doc/**/*_attrs.rdoc')
|
58
59
|
end
|
59
60
|
|
60
|
-
# ====================================================================
|
61
|
-
# Create a task that will package the Rake software into distributable
|
62
|
-
# tar, zip and gem files.
|
63
|
-
|
64
61
|
spec = Gem::Specification.new do |s|
|
65
|
-
|
66
|
-
#### Basic information.
|
67
|
-
|
68
62
|
s.name = PKG_NAME
|
69
63
|
s.version = PKG_VERSION
|
70
64
|
s.summary = "Behaviour Specification Framework for Ruby"
|
@@ -78,8 +72,6 @@ spec = Gem::Specification.new do |s|
|
|
78
72
|
s.files = PKG_FILES.to_a
|
79
73
|
s.require_path = 'lib'
|
80
74
|
|
81
|
-
#### Documentation and testing.
|
82
|
-
|
83
75
|
s.has_rdoc = true
|
84
76
|
s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
|
85
77
|
s.rdoc_options <<
|
@@ -87,18 +79,12 @@ spec = Gem::Specification.new do |s|
|
|
87
79
|
'--main' << 'README' <<
|
88
80
|
'--line-numbers'
|
89
81
|
|
90
|
-
s.test_files = Dir.glob('test
|
91
|
-
|
92
|
-
#### Make executable
|
82
|
+
s.test_files = Dir.glob('test/*_test.rb')
|
93
83
|
s.require_path = 'lib'
|
94
84
|
s.autorequire = 'spec'
|
95
|
-
|
96
85
|
s.bindir = "bin"
|
97
86
|
s.executables = ["spec", "test2rspec"]
|
98
87
|
s.default_executable = "spec"
|
99
|
-
|
100
|
-
#### Author and project details.
|
101
|
-
|
102
88
|
s.author = "Steven Baker"
|
103
89
|
s.email = "srbaker@pobox.com"
|
104
90
|
s.homepage = "http://rspec.rubyforge.org"
|
@@ -110,8 +96,6 @@ Rake::GemPackageTask.new(spec) do |pkg|
|
|
110
96
|
pkg.need_tar = true
|
111
97
|
end
|
112
98
|
|
113
|
-
# Support Tasks ------------------------------------------------------
|
114
|
-
|
115
99
|
def egrep(pattern)
|
116
100
|
Dir['**/*.rb'].each do |fn|
|
117
101
|
count = 0
|
@@ -139,9 +123,14 @@ end
|
|
139
123
|
task :release => [:clobber, :verify_user, :verify_password, :test, :upload_releases, :publish_website, :publish_news]
|
140
124
|
|
141
125
|
desc "Build the website with rdoc and rcov, but do not publish it"
|
142
|
-
task :website => [:clobber, :
|
126
|
+
task :website => [:clobber, :copy_rcov_report, :doc, :rdoc]
|
127
|
+
|
128
|
+
RCov::VerifyTask.new do |t|
|
129
|
+
t.threshold = 99.1 # Don't make it lower unless you have a damn good reason.
|
130
|
+
t.index_html = 'coverage/index.html'
|
131
|
+
end
|
143
132
|
|
144
|
-
task :
|
133
|
+
task :copy_rcov_report => [:test_with_rcov, :rcov_verify] do
|
145
134
|
rm_rf 'doc/output/coverage'
|
146
135
|
mkdir 'doc/output' unless File.exists? 'doc/output'
|
147
136
|
mv 'coverage', 'doc/output'
|
@@ -166,9 +155,10 @@ task :publish_website => [:verify_user, :website] do
|
|
166
155
|
publisher.upload
|
167
156
|
end
|
168
157
|
|
169
|
-
desc "Release gem to RubyForge. You must make sure lib/version.rb is aligned with the CHANGELOG file"
|
158
|
+
desc "Release gem+tgz+zip to RubyForge. You must make sure lib/version.rb is aligned with the CHANGELOG file"
|
170
159
|
task :upload_releases => [:verify_user, :verify_password, :package] do
|
171
|
-
|
160
|
+
require 'meta_project'
|
161
|
+
require 'rake/contrib/xforge'
|
172
162
|
release_files = FileList[
|
173
163
|
"pkg/#{PKG_FILE_NAME}.gem",
|
174
164
|
"pkg/#{PKG_FILE_NAME}.tgz",
|
@@ -186,6 +176,8 @@ end
|
|
186
176
|
|
187
177
|
desc "Publish news on RubyForge"
|
188
178
|
task :publish_news => [:verify_user, :verify_password] do
|
179
|
+
require 'meta_project'
|
180
|
+
require 'rake/contrib/xforge'
|
189
181
|
Rake::XForge::NewsPublisher.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |news|
|
190
182
|
# Never hardcode user name and password in the Rakefile!
|
191
183
|
news.user_name = ENV['RUBYFORGE_USER']
|
data/doc/src/default.css
CHANGED
@@ -41,7 +41,6 @@ acronym {
|
|
41
41
|
#header h1 strong {
|
42
42
|
color:#c00;
|
43
43
|
}
|
44
|
-
|
45
44
|
#header h2 {
|
46
45
|
margin:140px 0 0 0;
|
47
46
|
font-size:1em;
|
@@ -65,7 +64,6 @@ acronym {
|
|
65
64
|
list-style:none;
|
66
65
|
display:inline;
|
67
66
|
}
|
68
|
-
|
69
67
|
#navigation li a {
|
70
68
|
padding:5px 5px 2px 5px;
|
71
69
|
margin:0 1px 0 1px;
|
@@ -74,7 +72,6 @@ acronym {
|
|
74
72
|
font-weight:bold;
|
75
73
|
border-bottom:1px solid #c00;
|
76
74
|
}
|
77
|
-
|
78
75
|
#navigation li a:hover {
|
79
76
|
color:#C00;
|
80
77
|
border-bottom:1px solid #ddd;
|
@@ -86,8 +83,7 @@ acronym {
|
|
86
83
|
#content p {
|
87
84
|
padding:2px 20px;
|
88
85
|
text-align:justify;
|
89
|
-
|
90
|
-
line-height:1.8em;
|
86
|
+
line-height:1.4em;
|
91
87
|
}
|
92
88
|
#content h1 {
|
93
89
|
display:block;
|
@@ -102,7 +98,7 @@ acronym {
|
|
102
98
|
}
|
103
99
|
#content h2 {
|
104
100
|
display:block;
|
105
|
-
margin:20px 0 0
|
101
|
+
margin:20px 0 0 0px;
|
106
102
|
padding:0;
|
107
103
|
font-family:"Trebuchet MS",arial,sans-serif;
|
108
104
|
font-size:1.1em;
|
@@ -140,12 +136,17 @@ acronym {
|
|
140
136
|
padding:0;
|
141
137
|
text-indent:0;
|
142
138
|
}
|
139
|
+
#content code {
|
140
|
+
font-family:"courier new";
|
141
|
+
color:#444;
|
142
|
+
font-weight:bold;
|
143
|
+
}
|
143
144
|
#content pre {
|
144
|
-
|
145
|
-
|
145
|
+
padding:10px;
|
146
|
+
margin:0 18px 0 18px;
|
146
147
|
color:#444;
|
147
|
-
border:1px solid #
|
148
|
-
background-color:#
|
148
|
+
border:1px solid #444;
|
149
|
+
background-color:#ddd;
|
149
150
|
}
|
150
151
|
#content ul {
|
151
152
|
margin-left:70px;
|
@@ -5,200 +5,147 @@ ordering: 5
|
|
5
5
|
---
|
6
6
|
h2. Core API
|
7
7
|
|
8
|
-
When RSpec executes specifications, it defines a method
|
9
|
-
This *should* method is your entry to the magic of RSpec.
|
8
|
+
When RSpec executes specifications, it defines a method <code>should</code> on every object in the system. This <code>should</code> method is your entry to the magic of RSpec.
|
10
9
|
|
11
|
-
Almost all expectation forms have a corresponding negated form. It is listed
|
12
|
-
when it is supported and, in general, is met when ever the non negated form would be
|
13
|
-
violated.
|
10
|
+
Almost all expectation forms have a corresponding negated form. It is listed when it is supported and, in general, is met when ever the non-negated form would be violated.
|
14
11
|
|
15
12
|
h3. General
|
16
13
|
|
17
14
|
h4. Arbitrary Block
|
18
15
|
|
19
16
|
<pre>
|
20
|
-
<code>
|
21
17
|
target.should.satisfy {|arg| ...}
|
22
18
|
target.should.not.satisfy {|arg| ...}
|
23
|
-
</code>
|
24
19
|
</pre>
|
25
20
|
|
26
|
-
The supplied block is evaluated, passing <code>target</code> as the sole argument. If the
|
27
|
-
block evaluates to <code>false</code> in the case of <code>should.satisfy</code>, or <code>true</code> in the case of
|
28
|
-
<code>should.not.satisfy</code>, <code>ExpectationNotMetError</code> is raised.
|
21
|
+
The supplied block is evaluated, passing <code>target</code> as the sole argument. If the block evaluates to <code>false</code> in the case of <code>should.satisfy</code>, or <code>true</code> in the case of <code>should.not.satisfy</code>, <code>ExpectationNotMetError</code> is raised.
|
29
22
|
|
30
23
|
<pre>
|
31
|
-
<code>
|
32
24
|
target.should.satisfy {|arg| arg > 0}
|
33
|
-
</code>
|
34
25
|
</pre>
|
35
26
|
|
36
27
|
h4. Equality
|
37
28
|
|
38
29
|
<pre>
|
39
|
-
<code>
|
40
30
|
target.should.equal <value>
|
41
31
|
target.should.not.equal <value>
|
42
|
-
</code>
|
43
32
|
</pre>
|
44
33
|
|
45
|
-
The target object is compared to <code>value</code> using ==. If the result is <code>false</code> (or
|
46
|
-
<code>true</code> for the negated form) <code>ExpectationNotMetError</code> is raised.
|
34
|
+
The target object is compared to <code>value</code> using ==. If the result is <code>false</code> (or <code>true</code> for the negated form) <code>ExpectationNotMetError</code> is raised.
|
47
35
|
|
48
36
|
h4. Floating Point Comparison
|
49
37
|
|
50
38
|
<pre>
|
51
|
-
<code>
|
52
39
|
target.should.be.close <value>, <tolerance>
|
53
40
|
target.should.not.be.close <value>, <tolerance>
|
54
|
-
</code>
|
55
41
|
</pre>
|
56
42
|
|
57
|
-
The target object is compared to <code>value</code>. In the former case, if they differ
|
58
|
-
by more that <code>tolerance</code> <code>ExpectationNotMetError</code> is raised. In the latter case,
|
59
|
-
it is raised if they differ by less than <code>tolerance</code>.
|
43
|
+
The target object is compared to <code>value</code>. In the former case, if they differ by more that <code>tolerance</code> <code>ExpectationNotMetError</code> is raised. In the latter case, it is raised if they differ by less than <code>tolerance</code>.
|
60
44
|
|
61
45
|
<pre>
|
62
|
-
<code>
|
63
46
|
target.should.be.close 27.35, 0.05
|
64
|
-
</code>
|
65
47
|
</pre>
|
66
48
|
|
67
49
|
h4. Identity
|
68
50
|
|
69
51
|
<pre>
|
70
|
-
<code>
|
71
52
|
target.should.be <value>
|
72
53
|
target.should.not.be <value>
|
73
|
-
</code>
|
74
54
|
</pre>
|
75
55
|
|
76
|
-
The target object is compared to <code>value</code> using <code>equal?</code>. If the result is <code>false</code>
|
77
|
-
(or <code>true</code> for the negated form) <code>ExpectationNotMetError</code> is raised.
|
56
|
+
The target object is compared to <code>value</code> using <code>equal?</code>. If the result is <code>false</code> (or <code>true</code> for the negated form) <code>ExpectationNotMetError</code> is raised.
|
78
57
|
|
79
58
|
h4. Arbitrary Predicate
|
80
59
|
|
81
60
|
|
82
61
|
<pre>
|
83
|
-
<code>
|
84
62
|
target.should.predicate [optional args]
|
85
63
|
target.should.be.predicate [optional args]
|
86
64
|
target.should.not.predicate [optional args]
|
87
65
|
target.should.not.be.predicate [optional args]
|
88
|
-
</code>
|
89
66
|
</pre>
|
90
67
|
|
91
|
-
The message <code>predicate?</code> is sent to <code>target</code> with any supplied arguments. If the
|
92
|
-
result is <code>false</code> (or <code>true</code> for the negated form) <code>ExpectationNotMetError</code> is
|
93
|
-
raised.
|
68
|
+
The message <code>predicate?</code> is sent to <code>target</code> with any supplied arguments. If the result is <code>false</code> (or <code>true</code> for the negated form) <code>ExpectationNotMetError</code> is raised.
|
94
69
|
|
95
70
|
<pre>
|
96
|
-
<code>
|
97
71
|
container.should.include 'a' => container.include? 'a'
|
98
72
|
container.should.be.empty => container.empty?
|
99
|
-
</code>
|
100
73
|
</pre>
|
101
74
|
|
102
75
|
h4. Pattern Matching
|
103
76
|
|
104
77
|
<pre>
|
105
|
-
<code>
|
106
78
|
target.should.match <regex>
|
107
79
|
target.should.not.match <regex>
|
108
|
-
</code>
|
109
80
|
</pre>
|
110
81
|
|
111
|
-
The <code>target</code> is matched against <code>regex</code>. An <code>ExpectationNotMetError</code> is raised if
|
112
|
-
the match fails or succeeds, respectively.
|
82
|
+
The <code>target</code> is matched against <code>regex</code>. An <code>ExpectationNotMetError</code> is raised if the match fails or succeeds, respectively.
|
113
83
|
|
114
84
|
h3. Class/Type
|
115
85
|
|
116
86
|
h4. Direct Instance
|
117
87
|
|
118
88
|
<pre>
|
119
|
-
<code>
|
120
89
|
target.should.be.an.instance.of <class>
|
121
90
|
target.should.not.be.an.instance.of <class>
|
122
|
-
</code>
|
123
91
|
</pre>
|
124
92
|
|
125
|
-
An <code>ExpectationNotMetError</code> is raised if <code>target</code> is not or is, respectively, an
|
126
|
-
direct instance of <code>class</code>. As expected this correlates to <code>target.instance_of?
|
127
|
-
class</code>.
|
93
|
+
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>.
|
128
94
|
|
129
95
|
h4. Ancestor Class
|
130
96
|
|
131
97
|
<pre>
|
132
|
-
<code>
|
133
98
|
target.should.be.a.kind.of <class>
|
134
99
|
target.should.not.be.a.kind.of <class>
|
135
|
-
</code>
|
136
100
|
</pre>
|
137
101
|
|
138
|
-
As above, but uses <code>target.kind_of? class</code>: checking whether <code>class</code> is the
|
139
|
-
direct class of <code>target</code>, or an ancestor of <code>target</code>'s class.
|
102
|
+
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 class.
|
140
103
|
|
141
104
|
h4. Type
|
142
105
|
|
143
106
|
<pre>
|
144
|
-
<code>
|
145
107
|
target.should.respond.to <symbol>
|
146
108
|
target.should.not.respond.to <symbol>
|
147
|
-
</code>
|
148
109
|
</pre>
|
149
110
|
|
150
|
-
Uses <code>target.respond_to? symbol?</code> to check whether <code>symbol</code> is the name of a
|
151
|
-
message that <code>target</code> understands.
|
111
|
+
Uses <code>target.respond_to? symbol?</code> to check whether <code>symbol</code> is the name of a message that <code>target</code> understands.
|
152
112
|
|
153
113
|
h3. Procs
|
154
114
|
|
155
115
|
h4. Raising
|
156
116
|
|
157
117
|
<pre>
|
158
|
-
<code>
|
159
118
|
proc.should.raise <exception>
|
160
119
|
proc.should.not.raise <exception>
|
161
|
-
</code>
|
162
120
|
</pre>
|
163
121
|
|
164
|
-
Checks that <code>proc</code> does or doesn't cause the named exception to be raised.
|
165
|
-
Typically the <code>proc</code> is created in place using <code>lambda</code>. For example:
|
122
|
+
Checks that <code>proc</code> does or doesn't cause the named exception to be raised. Typically the <code>proc</code> is created in place using <code>lambda</code>. For example:
|
166
123
|
|
167
124
|
<pre>
|
168
|
-
<code>
|
169
125
|
lambda { 3 / 0 }.should.raise ZeroDivisionError
|
170
|
-
</code>
|
171
126
|
</pre>
|
172
127
|
|
173
128
|
There is a more general form as well.
|
174
129
|
|
175
130
|
<pre>
|
176
|
-
<code>
|
177
131
|
proc.should.raise
|
178
132
|
proc.should.not.raise
|
179
|
-
</code>
|
180
133
|
</pre>
|
181
134
|
|
182
|
-
These forms don't worry about what exception is raised (or not). All they are
|
183
|
-
concern with is that some except was raised, or that no exception was raised.
|
135
|
+
These forms don't worry about what exception is raised (or not). All they are concern with is that some except was raised, or that no exception was raised.
|
184
136
|
|
185
137
|
h4. Throwing
|
186
138
|
|
187
139
|
<pre>
|
188
|
-
<code>
|
189
140
|
proc.should.throw <symbol>
|
190
141
|
proc.should.not.throw <symbol>
|
191
|
-
</code>
|
192
142
|
</pre>
|
193
143
|
|
194
|
-
Similar to the above, but checks that <code>symbol</code> is thrown from within <code>proc</code>, or
|
195
|
-
that it is not. The latter is actually one of two cases: some other symbol is
|
144
|
+
Similar to the above, but checks that <code>symbol</code> is thrown from within <code>proc</code>, or that it is not. The latter is actually one of two cases: some other symbol is
|
196
145
|
thrown, or no symbol is thrown.
|
197
146
|
|
198
147
|
<pre>
|
199
|
-
<code>
|
200
148
|
proc.should.not.throw
|
201
|
-
</code>
|
202
149
|
</pre>
|
203
150
|
|
204
151
|
This form is more specific. It checks that no symbol is thrown from within <code>proc</code>.
|
@@ -208,25 +155,15 @@ h3. Collections
|
|
208
155
|
h4. Containment
|
209
156
|
|
210
157
|
<pre>
|
211
|
-
<code>
|
212
158
|
target.should.include <object>
|
213
|
-
</code>
|
214
159
|
</pre>
|
215
160
|
|
216
|
-
This is simply a specific case of the arbitrary predicate form. It uses
|
217
|
-
<code>target.include? object</code> and raises an <code>ExpectationNotMetError</code> if that returns
|
218
|
-
false. The remaining collection forms are a little more involved. They rely on
|
219
|
-
two things: <code>target</code> responds to the message <code>things</code> by returning an object
|
220
|
-
that responds to either <code>length</code> or <code>size</code>, which return a number that is a
|
221
|
-
measure of size. Currently <code>length</code> is used if is appropriate, otherwise <code>size</code> is
|
222
|
-
attempted.
|
161
|
+
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. The remaining collection forms are a little more involved. They rely on two things: <code>target</code> responds to the message <code>things</code> by returning an object that responds to either <code>length</code> or <code>size</code>, which return a number that is a measure of size. Currently <code>length</code> is used if is appropriate, otherwise <code>size</code> is attempted.
|
223
162
|
|
224
163
|
h4. Exact Size
|
225
164
|
|
226
165
|
<pre>
|
227
|
-
<code>
|
228
166
|
target.should.have(<number>).<things>
|
229
|
-
</code>
|
230
167
|
</pre>
|
231
168
|
|
232
169
|
The <code>things</code> of <code>target</code> has a length/size of exactly <code>number</code>.
|
@@ -234,9 +171,7 @@ The <code>things</code> of <code>target</code> has a length/size of exactly <cod
|
|
234
171
|
h4. Lower Bound
|
235
172
|
|
236
173
|
<pre>
|
237
|
-
<code>
|
238
174
|
target.should.have.at.least(<number>).<things>
|
239
|
-
</code>
|
240
175
|
</pre>
|
241
176
|
|
242
177
|
The <code>things</code> of <code>target</code> has a length/size of no less than <code>number</code>.
|
@@ -244,9 +179,7 @@ The <code>things</code> of <code>target</code> has a length/size of no less than
|
|
244
179
|
h4. Upper Bound
|
245
180
|
|
246
181
|
<pre>
|
247
|
-
<code>
|
248
182
|
target.should.have.at.most(<number>).<things>
|
249
|
-
</code>
|
250
183
|
</pre>
|
251
184
|
|
252
185
|
The <code>things</code> of <code>target</code> has a length/size of no more than <code>number</code>.
|