ae 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,100 @@
1
+ = Subjunctives
2
+
3
+ Okay. I can hear the BDDers rumbling, "where's the *should?*"
4
+ AE has nothing against "should", but there are different
5
+ approaches for utilizing should nomenclature in specifications,
6
+ and AE wants to be open to these techniques. One of which
7
+ is how Shoulda (http://shoulda.rubyforge.org) utilizes
8
+ +should+ in a way analogous to RSpec's use of +it+.
9
+
10
+ Even so, AE provides a an optional mixin called +Subjunctive+ which
11
+ can be used to create assertor methods with English subjunctive
12
+ terms, such as +should+, or +must+, +shall+ and +will+.
13
+ To load this library use:
14
+
15
+ require 'ae/subjunctive'
16
+
17
+ Then all that is required it to define a subjunctive method for all
18
+ objects. For example:
19
+
20
+ def will(*args, &block)
21
+ Assertor.new(self, :backtrace=>caller).be(*args,&block)
22
+ end
23
+
24
+ It's that easy. Because of their commonality AE provides two such terms,
25
+ +should+ and +must+ as optional add-ons out-of-the-box.
26
+
27
+ require 'ae/subjunctive/should'
28
+ require 'ae/subjunctive/must'
29
+
30
+ We will use these two methods interchangeable for the rest of this
31
+ demonstration, but to be clear they both work exactly the same way,
32
+ and almost exactly like +assert+.
33
+
34
+ Keep in mind, AE "conical" functionality does not entail the subjunctive
35
+ forms. These are simply options you can load via your <tt>test_helper.rb</tt>,
36
+ or similar script, if you prefer these nomenclatures.
37
+
38
+
39
+ == Fluent Notation and Antonyms
40
+
41
+ Like +assert+, +should+ and +must+ can be used as higher order functions.
42
+
43
+ 4.should == 4
44
+ 4.must == 4
45
+
46
+ Antonyms provided for +should+ as <tt>should!</tt> (read "should not") and +shouldnt+.
47
+ For +must+ +must+, they are <tt>must!</tt> and +wont+.
48
+
49
+ 4.should! == 5
50
+ 4.shouldnt == 5
51
+
52
+ 4.must! == 5
53
+ 4.wont == 5
54
+
55
+
56
+ == To Be
57
+
58
+ On occasions where the English readability of a specification is hindered,
59
+ +be+ can be used.
60
+
61
+ StandardError.must.be.raised? do
62
+ unknown_method
63
+ end
64
+
65
+ The +be+ method is the same as +assert+ with the single exception
66
+ that it will compare a lone argument to the receiver using +equate?+,
67
+ unlike +assert+ which simply checks to see that the argument evaluates
68
+ as true.
69
+
70
+ 10.should.be 10
71
+ 10.should.be 10.0
72
+ 10.should.be Numeric
73
+
74
+ Assertion.assert.raised? do
75
+ 10.should.be "40"
76
+ end
77
+
78
+
79
+ == Indefinite Articles
80
+
81
+ Additional English forms are +a+ and +an+, equivalent to +be+ except
82
+ that they use <tt>case?</tt> (same as <tt>#===</tt>) instead of
83
+ <tt>equate?</tt> when acting on a single argument.
84
+
85
+ "hi".must.be.a String
86
+
87
+ Assertion.assert.raised? do
88
+ /x/.must.be.a /x/
89
+ end
90
+
91
+ Otherwise they are interchangeable.
92
+
93
+ "hi".must.be.an.instance_of?(String)
94
+
95
+ The indefinite articles work well when a noun follows as an arguments.
96
+
97
+ palindrome = lambda{ |x| x == x.reverse }
98
+
99
+ "abracarba".must.be.a palindrome
100
+
@@ -0,0 +1,84 @@
1
+ = Expect Method
2
+
3
+ Expect is another optional assertion nomenclature available
4
+ for use in your tests or specifications. Inspired by Jay Fields'
5
+ Expectations library, it provides convenient syntax for creating
6
+ exception and case equality assertions.
7
+
8
+ require 'ae/expect'
9
+
10
+ == Underlying Comparison
11
+
12
+ Expect uses #=== for comparison. So providing an argument and a block to
13
+ #expect we can test for a somewhat broader range of compassion than #assert.
14
+ For example we can test for a subclass.
15
+
16
+ expect Numeric do
17
+ 3
18
+ end
19
+
20
+ Assertion.assert.raised? do
21
+ expect Numeric do
22
+ "3"
23
+ end
24
+ end
25
+
26
+
27
+ == Exception Expectation
28
+
29
+ If the comparator is an Exception class or a instance of an Exception class,
30
+ then #expect will check to see if the block raises that kind of exception.
31
+
32
+ expect StandardError do
33
+ some_undefined_method
34
+ end
35
+
36
+ expect Assertion do
37
+ expect(nil)
38
+ end
39
+
40
+ This is an important distinction to note because it means #expect can not be used
41
+ if verify instances of Exception classes.
42
+
43
+ Assertion.assert.raised? do
44
+ expect Exception do
45
+ Exception.new
46
+ end
47
+ end
48
+
49
+
50
+ == Regex Expectations
51
+
52
+ That #expect entails #=== also means we can check for Regexp matches.
53
+
54
+ expect /x/ do
55
+ "oooxooo"
56
+ end
57
+
58
+
59
+ == Expected Method
60
+
61
+ We can use #expected to make the receiver the object of expectation.
62
+
63
+ x = "dummy"
64
+
65
+ /x/.expected do
66
+ "x"
67
+ end
68
+
69
+
70
+ == Function without Block
71
+
72
+ Without a block, the receiver is compared to the argument.
73
+
74
+ x.expect String
75
+
76
+
77
+ == Functor, or Higher Order Function
78
+
79
+ Like #assert, #expect can be used used as a *fluid* notation.
80
+
81
+ 10.expect == 10
82
+
83
+ In which case it works just like #assert.
84
+
@@ -0,0 +1,25 @@
1
+ = Assertion Counts
2
+
3
+ AE tracks the number of assertions made and the number that failed to pass.
4
+ We can reset the count using the +recount+ class method.
5
+
6
+ Assertion.recount
7
+
8
+ For example if we one assertion fails and another fails:
9
+
10
+ assert(true)
11
+ assert(false)
12
+
13
+ We will see that AE counted two assertions and one failure.
14
+
15
+ Assertion.count.assert == 2
16
+ Assertion.fails.assert == 1
17
+
18
+ The above calls simply access the actual global variables.
19
+
20
+ $assertions.assert == 4
21
+ $failures.assert == 1
22
+
23
+ Notice there are now two additional assertions.
24
+
25
+
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 2
8
- - 2
9
- version: 1.2.2
8
+ - 3
9
+ version: 1.2.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Thomas Sawyer
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-06 00:00:00 -04:00
17
+ date: 2010-06-08 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -50,8 +50,12 @@ extensions: []
50
50
  extra_rdoc_files:
51
51
  - README.rdoc
52
52
  files:
53
- - doc/qedoc/index.html
54
- - doc/qedoc/jquery.js
53
+ - qed/01_overview.rdoc
54
+ - qed/02_assertion.rdoc
55
+ - qed/03_assert.rdoc
56
+ - qed/04_subjunctive.rdoc
57
+ - qed/05_expect.rdoc
58
+ - qed/06_counts.rdoc
55
59
  - lib/ae/assert.rb
56
60
  - lib/ae/assertion.rb
57
61
  - lib/ae/assertor.rb
@@ -63,10 +67,14 @@ files:
63
67
  - lib/ae/subjunctive/must.rb
64
68
  - lib/ae/subjunctive/should.rb
65
69
  - lib/ae/subjunctive.rb
70
+ - lib/ae/version.yml
66
71
  - lib/ae.rb
72
+ - PROFILE
73
+ - LICENSE
67
74
  - README.rdoc
68
75
  - HISTORY
69
- - Syckfile
76
+ - REQUIRE
77
+ - VERSION
70
78
  has_rdoc: true
71
79
  homepage: http://proutils.github.com/ae
72
80
  licenses: []
data/Syckfile DELETED
@@ -1,77 +0,0 @@
1
- ---
2
- box:
3
- service: Box
4
- types : [gem]
5
- active : true
6
-
7
- dnote:
8
- service : DNote
9
- loadpath : ~
10
- labels : ~
11
- output : ~
12
- format : ~
13
- active : true
14
-
15
- stats:
16
- service : Stats
17
- title : ~
18
- loadpath : ~
19
- exclude : ~
20
- output : ~
21
- active : true
22
-
23
- vclog:
24
- service : VClog
25
- format : html # xml, txt
26
- layout : rel # gnu
27
- typed : false
28
- output : ~
29
- active : false
30
-
31
- rdoc:
32
- service: rdoc
33
- exclude: [Syckfile]
34
-
35
- ridoc:
36
- service: RIDoc
37
- include: ~
38
- exclude: ~
39
- active : true
40
-
41
- syntax:
42
- service : Syntax
43
- loadpath : ~
44
- exclude : ~
45
- active : false
46
-
47
- testrb:
48
- service : testrb
49
- tests : ~
50
- exclude : ~
51
- loadpath : ~
52
- requires : ~
53
- live : false
54
- active : false
55
-
56
- grancher:
57
- service: Grancher
58
- sitemap:
59
- - site
60
- - [doc/rdoc, rdoc]
61
- - [doc/qedoc, qedoc]
62
- active: true
63
-
64
- email:
65
- service : Email
66
- file : ~
67
- subject : ~
68
- mailto : ruby-talk@ruby-lang.org
69
- from : admin@tigerops.org
70
- server : <%= ENV['EMAIL_SERVER'] %>
71
- port : <%= ENV['EMAIL_PORT'] %>
72
- account : <%= ENV['EMAIL_ACCOUNT'] %>
73
- domain : <%= ENV['EMAIL_DOMAIN'] %>
74
- login : <%= ENV['EMAIL_LOGIN'] %>
75
- secure : <%= ENV['EMAIL_SECURE'] %>
76
- active : true
77
-
@@ -1,710 +0,0 @@
1
- <html>
2
- <head>
3
- <title>Assertive Expressive</title>
4
-
5
- <style>
6
- #container{ margin: 0 auto; width: 800px; }
7
-
8
- /* Debug borders */
9
- /* p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 { border: 1px solid red; } */
10
-
11
- body { font-size: 14px; line-height: 20px; margin: 1em 5% 1em 5%; font-family: Verdana, Arial, Helvetica, sans-serif; }
12
- a { color: #336; text-decoration: underline; }
13
- a:visited { color: #334; }
14
- em { font-style: italic; }
15
- strong { font-weight: bold; }
16
- tt { color: navy; }
17
-
18
- h1, h2, h3, h4, h5, h6 { color: #223; margin-top: 1.2em; margin-bottom: 0.5em; line-height: 1.3; }
19
- h1 { border-bottom: 2px solid silver; }
20
- h2 { border-bottom: 2px solid silver; padding-top: 0.5em; }
21
-
22
- hr { border: 1px solid silver; }
23
-
24
- p { color: #222; text-align: justify; margin-top: 0.5em; margin-bottom: 0.5em; line-height: 1.4em; }
25
-
26
- pre { padding: 10; margin: 0; font-family: monospace; font-size: 0.9em; }
27
- pre.pass { color: green; }
28
- pre.fail { color: red; }
29
- pre.error { color: red; font-weight: bold; }
30
-
31
- span#author { color: #527bbd; font-weight: bold; font-size: 1.1em; }
32
- span#email { }
33
- span#revision { }
34
-
35
- div#footer { font-size: small; border-top: 2px solid silver; padding-top: 0.5em; margin-top: 4.0em; }
36
- div#footer-text { float: left; padding-bottom: 0.5em; }
37
- div#footer-badges { float: right; padding-bottom: 0.5em; }
38
-
39
- /* Block element content. */
40
- div.content { padding: 0; }
41
-
42
- /* Block element titles. */
43
- h1.title { font-weight: bold; text-align: left; font-size: 3em; margin-top: 1.0em; margin-bottom: 0.5em; }
44
-
45
- /* Block element titles. */
46
- div.title, caption.title { font-weight: bold; text-align: left; margin-top: 1.0em; margin-bottom: 0.5em; }
47
- div.title + * { margin-top: 0; }
48
- td div.title:first-child { margin-top: 0.0em; }
49
- div.content div.title:first-child { margin-top: 0.0em; }
50
- div.content + div.title { margin-top: 0.0em; }
51
- div.sidebarblock > div.content { background: #ffffee; border: 1px solid silver; padding: 0.5em; }
52
-
53
- img { border-style: none; }
54
-
55
- dl { margin-top: 0.8em; margin-bottom: 0.8em; }
56
- dt { margin-top: 0.5em; margin-bottom: 0; font-style: italic; }
57
- dd > *:first-child { margin-top: 0; }
58
- ul, ol { list-style-position: outside; }
59
-
60
- thead { font-weight: bold; }
61
- tfoot { font-weight: bold; }
62
- </style>
63
-
64
- <!-- TODO: only include if these files exists -->
65
- <link href="../assets/styles/spec.css" type="text/css" rel="stylesheet">
66
- <!-- spec.css might be a problem with clobber -->
67
- <link href="spec.css" type="text/css" rel="stylesheet">
68
-
69
-
70
-
71
- <!-- JQuery is needed -->
72
- <script src="jquery.js" type="text/javascript" language="javascript"></script>
73
-
74
- </head>
75
-
76
- <body>
77
-
78
- <!-- Side Table of Contents -->
79
- <div id="sidebar" style="position: fixed; top: 10; right: 10; background: white;">
80
- <a href="javascript: toc_toggle();">
81
- <img src="img/icon/book.jpg" height="30px;" style="border: none;" alt="TOC" align="right"/>
82
- </a>
83
-
84
- <div id="toc_side" class="toc">
85
- </div>
86
- </div>
87
-
88
- <div id="container">
89
- <div id="header">
90
- <img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
91
-
92
- <h1 class="title">Assertive Expressive</h1>
93
-
94
- <h1>Table of Contents</h1>
95
-
96
- <div class="toc">
97
- </div>
98
- </div>
99
-
100
- <div id="content">
101
- <h1>Introduction</h1>
102
- <p>
103
- AE is an assertions framework for Ruby. It&#8217;s designed around the
104
- concept of an Assertor. The Assertor is an Assertion Functor, or
105
- Higher-Order Function, which reroutes method calls while monitoring them
106
- for failing conditions.
107
- </p>
108
- <h2>What&#8217;s Provided</h2>
109
- <p>
110
- Requiring the AE library.
111
- </p>
112
- <pre>
113
- require 'ae'
114
- </pre>
115
- <p>
116
- Loads two classes, <tt>Assertion</tt> and <tt>Assertor</tt>, the Kernel
117
- method <tt>assert</tt> and it&#8217;s ancillaries <tt>assert!</tt> and
118
- <tt>refute</tt> and a set of core extensions that make writing certain
119
- types of assertions easier.
120
- </p>
121
- <h2>Assertion and Assertor Classes</h2>
122
- <p>
123
- The <tt>Assertion</tt> class is at the heart of AE. All other AE methods
124
- depend on it. The <tt>Assertion</tt> class is a subclass of Exception. When
125
- an assertion is made and fails, it is an instance of Assertion that is
126
- raised.
127
- </p>
128
- <pre>
129
- Assertion.assert.raised? do
130
- msg = &quot;my failure message&quot;
131
- assert false, msg
132
- end
133
- </pre>
134
- <p>
135
- Like any raised exception, the last Assertion message is available via
136
- <tt>$!</tt>.
137
- </p>
138
- <p>
139
- (FYI, in Test::Unit the equivalent class was called
140
- <tt>AssertionFailedError</tt>.)
141
- </p>
142
- <p>
143
- Assertions themsevles are not generally used in creating tests or behavior
144
- specifications. Rather they are used to create additonal types of assertion
145
- methods.
146
- </p>
147
- <p>
148
- As mentioned above the <tt>Assertor</tt> class is a type of Higher-Order
149
- function, or Functor, which intercedes with a normal message invocation to
150
- monitor for failed conditions, upon which is raises Assertion exceptions.
151
- </p>
152
- <h2>Assertion Methods</h2>
153
- <p>
154
- The three methods, <tt>assert</tt>, <tt>assert!</tt> and <tt>refute</tt>
155
- all return an Assertor instance when used fluidly, i.e. magic-dot notation,
156
- higher-order notation, functor notation, whatever you prefer to call it.
157
- </p>
158
- <pre>
159
- assert(Assertor === assert)
160
- </pre>
161
- <p>
162
- Through the use of <tt>method_missing</tt>, the Assertor allows us to write
163
- statements like:
164
- </p>
165
- <pre>
166
- 1.assert == 1
167
- </pre>
168
- <p>
169
- If the operation evaluates to false or nil, then an Assertion error is
170
- raised.
171
- </p>
172
- <pre>
173
- Assertion.assert.raised? do
174
- 1.assert == 2
175
- end
176
- </pre>
177
- <p>
178
- The methods <tt>assert!</tt> and <tt>refute</tt> are just like
179
- <tt>assert</tt> expect they purport the negative condition. Patterned after
180
- Ruby&#8217;s own use of &quot;<tt>!</tt>&quot; as meaning <tt>not</tt>,
181
- <tt>assert!</tt> should be read &quot;assert not&quot;. While
182
- <tt>refute</tt> exists for the sake of those who find the use of a bang
183
- method for this purpose unsuited to them.
184
- </p>
185
- <h2>How It Works</h2>
186
- <p>
187
- An Assertor essentially sits in wait for a method call (via
188
- method_missing). When that happens it applies the method to the original
189
- receiver, but wrapped in a clause that raises an Assertion should the
190
- statement fail. If we wanted to be pedantic, we could write our assertions
191
- like:
192
- </p>
193
- <pre>
194
- raise Assertion.new(&quot;1 != 1&quot;) unless 1 == 1
195
- </pre>
196
- <p>
197
- Instead of
198
- </p>
199
- <pre>
200
- 1.assert == 1
201
- </pre>
202
- <p>
203
- Obviously using Assertor methods are whole lot more concise.
204
- </p>
205
-
206
-
207
- <h1>Assert Method</h1>
208
- <h2>Compatible with Test::Unit</h2>
209
- <p>
210
- The <tt>assert</tt> method is designed to be backward compatible with the
211
- same method in <tt>Test::Unit</tt>.
212
- </p>
213
- <p>
214
- Using an argument, <tt>assert</tt> will check that an argument evaluates to
215
- true. Optionally one can send along a meaningful message should the
216
- assertion fail.
217
- </p>
218
- <pre>
219
- assert(true, &quot;Not true!&quot;)
220
-
221
- Assertion.assert.raised? do
222
- assert(false, &quot;Not true!&quot;)
223
- end
224
- </pre>
225
- <h2>Assert with a Block</h2>
226
- <p>
227
- In addition <tt>assert</tt> has been extended to accept a block. Like the
228
- case of the argument, the block is expected to return something that
229
- evaluates as true.
230
- </p>
231
- <pre>
232
- assert do
233
- true
234
- end
235
-
236
- Assertion.assert.raised? do
237
- assert do
238
- false
239
- end
240
- end
241
- </pre>
242
- <p>
243
- We should also mention that, while probably not very useful, since the
244
- arity of a block can be checked, one can also pass the receiver into the
245
- block as a block argument.
246
- </p>
247
- <pre>
248
- &quot;hi&quot;.assert do |s|
249
- /h/ =~ s
250
- end
251
- </pre>
252
- <h2>Antonyms for Assert</h2>
253
- <p>
254
- We can state the opposite assertion using <tt>assert!</tt>.
255
- </p>
256
- <pre>
257
- 10.assert! == 9
258
- </pre>
259
- <p>
260
- Or, because some people do not like the use of a bang method,
261
- <tt>refute</tt>.
262
- </p>
263
- <pre>
264
- 10.refute == 9
265
- </pre>
266
- <p>
267
- These terms can be used just as <tt>assert</tt> is used in all examples,
268
- but with the opposite inference.
269
- </p>
270
- <p>
271
- Another way to get the opposite inference, is to use <tt>not</tt>.
272
- </p>
273
- <pre>
274
- 10.assert.not == 9
275
- </pre>
276
- <h2>Identity Assertions</h2>
277
- <p>
278
- Rather then the general form:
279
- </p>
280
- <pre>
281
- x = 10
282
- x.assert.object_id == x.object_id
283
- </pre>
284
- <p>
285
- We can use Ruby&#8217;s own <tt>equal?</tt> method.
286
- </p>
287
- <pre>
288
- x.assert.equal?(x)
289
- </pre>
290
- <p>
291
- AE provides <tt>identical?</tt> method as an alternative to make it a bit
292
- more clear.
293
- </p>
294
- <pre>
295
- x.assert.identical?(x)
296
- </pre>
297
- <h2>Equality Assertions</h2>
298
- <p>
299
- The most common assertion is that of value equality (<tt>==</tt>), as we
300
- have seen throughout this document. But other forms of equality can be
301
- verified as easily. We have already mentioned identity. In addition there
302
- is <em>type equality</em>.
303
- </p>
304
- <pre>
305
- 17.assert.eql? 17
306
-
307
- Assertion.assert.raised? do
308
- 17.assert.eql? 17.0
309
- end
310
- </pre>
311
- <p>
312
- And there is <em>case equality</em>.
313
- </p>
314
- <pre>
315
- Numeric.assert === 3
316
- </pre>
317
- <h2>Checking Equality with a Block</h2>
318
- <p>
319
- Because operators can not take blocks, and at times blocks can be
320
- convenient means of supplying a value to an assertion, AE has defined
321
- alternate renditions of the equality methods. For equal? and eql?, the
322
- method names are the same, they simply can take a block in place of an
323
- argument if need be.
324
- </p>
325
- <p>
326
- For <em>value equality</em> (<tt>==</tt>), the method is called
327
- <tt>eq?</tt>.
328
- </p>
329
- <pre>
330
- 10.assert.eq? do
331
- 10.0
332
- end
333
- </pre>
334
- <p>
335
- And should it fail&#8230;
336
- </p>
337
- <pre>
338
- Assertion.assert.raised? do
339
- 10.assert.eq? do
340
- 20
341
- end
342
- end
343
- </pre>
344
- <p>
345
- For <em>case equality</em> (<tt>===</tt>), it is <tt>case?</tt>.
346
- </p>
347
- <pre>
348
- Numeric.assert.case? do
349
- &quot;3&quot;.to_i
350
- end
351
-
352
- Assertion.assert.raised? do
353
- Numeric.assert.case? do
354
- &quot;3&quot;
355
- end
356
- end
357
- </pre>
358
- <h2>Exception Assertions</h2>
359
- <p>
360
- Validating errors is easy too, as has already been shown in the document to
361
- verify assertion failures.
362
- </p>
363
- <pre>
364
- StandardError.assert.raised? do
365
- unknown_method
366
- end
367
- </pre>
368
- <h2>Assertions on Object State</h2>
369
- <p>
370
- While testing or specifying the internal state of an object is generally
371
- considered poor form, there are times when it is necessay. Assert combined
372
- with <tt>instance_eval</tt> makes it easy too.
373
- </p>
374
- <pre>
375
- class X
376
- attr :a
377
- def initialize(a); @a = a; end
378
- end
379
-
380
- x = X.new(1)
381
-
382
- x.assert.instance_eval do
383
- @a == 1
384
- end
385
- </pre>
386
- <h2>Catch/Try Assertions</h2>
387
- <p>
388
- Catch/Try throws can be tested via <tt>Symbol#thrown?</tt>.
389
- </p>
390
- <pre>
391
- :hookme.assert.thrown? do
392
- throw :hookme
393
- end
394
- </pre>
395
- <p>
396
- Alternatively, a lambda containing the potential throw can be the receiver
397
- using <tt>throws?</tt>.
398
- </p>
399
- <pre>
400
- hook = lambda{ throw :hookme }
401
-
402
- hook.assert.throws?(:hookme)
403
- </pre>
404
- <h2>Assertions on Proc Changes</h2>
405
- <p>
406
- I have to admit I&#8217;m not sure how this is useful, but I found it in
407
- the Bacon API and ported it over just for sake of thoroughness.
408
- </p>
409
- <pre>
410
- a = 0
411
-
412
- l = lambda{ a }
413
-
414
- l.assert.change?{ a +=1 }
415
- </pre>
416
- <h2>Assertion on literal True, False and Nil</h2>
417
- <p>
418
- Ruby already provides the #nil? method.
419
- </p>
420
- <pre>
421
- nil.assert.nil?
422
- </pre>
423
- <p>
424
- AE adds <tt>true?</tt> and <tt>false?</tt> which acts accordingly.
425
- </p>
426
- <pre>
427
- true.assert.true?
428
- false.assert.false?
429
- </pre>
430
- <h2>Send Assertions</h2>
431
- <p>
432
- Assert that a method can be successfully called.
433
- </p>
434
- <pre>
435
- &quot;STRING&quot;.assert.send?(:upcase)
436
- </pre>
437
- <h2>Numeric Delta and Epsilon</h2>
438
- <p>
439
- You may wish to assert that a numeric value is with some range.
440
- </p>
441
- <pre>
442
- 3.in_delta?(1,5)
443
- </pre>
444
- <p>
445
- Or minimum range.
446
- </p>
447
- <pre>
448
- 3.in_epsilon?(3,5)
449
- </pre>
450
- <h2>Custom Lambda Assertions</h2>
451
- <p>
452
- Passing a lambda to the subjunctive method, will use it as if it were a
453
- block of the method. This allows for a simple way to quickly create
454
- reusable assertions.
455
- </p>
456
- <pre>
457
- palindrome = lambda{ |x| x == x.reverse }
458
-
459
- &quot;abracarba&quot;.assert palindrome
460
- </pre>
461
- <h2>Verifying Object State</h2>
462
- <p>
463
- NOTE: <em>This functionality is not currently supported, but is being
464
- considered for a future version.</em>
465
- </p>
466
- <p>
467
- If no block parameter is designated and the receiver differs from
468
- <tt>self</tt> in scope of the given block, then the block is evaluated in
469
- the scope of the receiver via <tt>instance_eval</tt>. This can be also be
470
- used to verify the state of an object.
471
- </p>
472
- <pre>
473
- class X
474
- attr :a
475
- def initialize(a); @a = a; end
476
- end
477
-
478
- x = X.new(4)
479
-
480
- x.must do
481
- 4 == @a
482
- end
483
- </pre>
484
- <p>
485
- And should it fail&#8230;
486
- </p>
487
- <pre>
488
- Assertion.assert.raised? do
489
- x.must do
490
- 5 == @a
491
- end
492
- end
493
- </pre>
494
- <p>
495
- For some this might be considered poor form, i.e. to test underlying
496
- implementation. You will get no argument here. It should be used
497
- thoughtfully, but I would not bet against there being occasions when such
498
- validations might be handy.
499
- </p>
500
-
501
- <h1>Subjunctives</h1>
502
- <p>
503
- Okay. I can hear the BDDers rumbling, &quot;where&#8217;s the should?&quot;
504
- AE has nothing against &quot;should&quot;, but there are different
505
- approaches for utilizing should nomenclature in specifications, and AE
506
- wants to be open to these techniques. One of which is how Shoulda
507
- (http://shoulda.rubyforge.org) utilizes <tt>should</tt> in a way analogous
508
- to RSpec&#8217;s use of <tt>it</tt>.
509
- </p>
510
- <p>
511
- Even so, AE provides a an optional mixin called <tt>Subjunctive</tt> which
512
- can be used to create assertor methods with English subjunctive terms, such
513
- as <tt>should</tt>, or <tt>must</tt>, <tt>shall</tt> and <tt>will</tt>. To
514
- load this library use:
515
- </p>
516
- <pre>
517
- require 'ae/subjunctive'
518
- </pre>
519
- <p>
520
- Then all that is required it to define your subjunctive method for all
521
- objects. For example:
522
- </p>
523
- <pre>
524
- def will(*args, &amp;block)
525
- Assertor.new(self, :backtrace=&gt;caller).be(*args,&amp;block)
526
- end
527
- </pre>
528
- <p>
529
- It&#8217;s that easy. Because of their popularity AE provides two such
530
- terms, <tt>should</tt> and <tt>must</tt> as optional add-ons.
531
- </p>
532
- <pre>
533
- require 'ae/subjunctive/should'
534
- require 'ae/subjunctive/must'
535
- </pre>
536
- <p>
537
- We will use these two methods interchangeable for the rest of this
538
- demonstration, but to be clear they both work exactly the same way, and
539
- almost exactly like <tt>assert</tt>.
540
- </p>
541
- <p>
542
- Keep in mind, AE &quot;conical&quot; functionality does not entail
543
- subjunctive forms. These are simply options you can load via your
544
- <tt>test_helper.rb</tt>, or similar script, if you prefer these
545
- nomenclatures.
546
- </p>
547
- <h2>Fluent Notation and Antonyms</h2>
548
- <p>
549
- Like <tt>assert</tt>, <tt>should</tt> and <tt>must</tt> can be used as
550
- higher order functions.
551
- </p>
552
- <pre>
553
- 4.should == 4
554
- 4.must == 4
555
- </pre>
556
- <p>
557
- With the antonym of <tt>should!</tt> (read &quot;should not&quot;) or
558
- <tt>shouldnt</tt>, and for <tt>must</tt>, <tt>must!</tt> and <tt>wont</tt>.
559
- </p>
560
- <pre>
561
- 4.should! == 5
562
- 4.shouldnt == 5
563
-
564
- 4.must! == 5
565
- 4.wont == 5
566
- </pre>
567
- <h2>To Be</h2>
568
- <p>
569
- On occasions where the English readability of a specification is hindered,
570
- <tt>be</tt> can be used.
571
- </p>
572
- <pre>
573
- StandardError.must.be.raised? do
574
- unknown_method
575
- end
576
- </pre>
577
- <p>
578
- The <tt>be</tt> method is the same as <tt>assert</tt> with the single
579
- exception that it will compare a lone argument to the receiver using
580
- +equate?+, unlike <tt>assert</tt> which simply checks to see that the
581
- argument evalutates as true.
582
- </p>
583
- <pre>
584
- 10.should.be 10
585
- 10.should.be 10.0
586
- 10.should.be Numeric
587
-
588
- Assertion.assert.raised? do
589
- 10.should.be &quot;40&quot;
590
- end
591
- </pre>
592
- <h2>Indefinite Articles</h2>
593
- <p>
594
- Addtional English forms are <tt>a</tt> and <tt>an</tt>, equivalent to
595
- <tt>be</tt> except that they use <tt>case?</tt> instead of <tt>equate?</tt>
596
- when acting on a single argument.
597
- </p>
598
- <pre>
599
- &quot;hi&quot;.must.be.a String
600
-
601
- Assertion.assert.raised? do
602
- /x/.must.be.a /x/
603
- end
604
- </pre>
605
- <p>
606
- Otherwise they are interchangeble.
607
- </p>
608
- <pre>
609
- &quot;hi&quot;.must.be.an.instance_of?(String)
610
- </pre>
611
- <p>
612
- The indefinite articles work well when a noun follows as an arguments.
613
- </p>
614
- <pre>
615
- palindrome = lambda{ |x| x == x.reverse }
616
-
617
- &quot;abracarba&quot;.must.be.a palindrome
618
- </pre>
619
- <p>
620
- QED.
621
- </p>
622
-
623
-
624
- </div>
625
- </div>
626
-
627
- </body>
628
-
629
- </html>
630
-
631
- <script src="../assets/scripts/spec.js" type="text/javascript" language="javascript"></script>
632
-
633
- <script type="text/javascript" language="javascript">
634
- /*****************************************************************
635
- * $.toc()
636
- * by rebecca murphey
637
- * rmurphey gmail com
638
- *
639
- * This function is called on its own and takes as an argument
640
- * a list of selectors with which it will build a table of
641
- * contents.
642
- *
643
- * The first selector will make up the top level of the TOC;
644
- * the second selector will make up the second level of the TOC;
645
- * etc.
646
- *
647
- * This function returns a div containing nested unordered lists;
648
- * each list item is linked to an anchor tag added before the item
649
- * on the page.
650
- *
651
- * usage: $.toc('h1,h2,h3').prependTo('body');
652
- ************************************************************************/
653
- (function($) {
654
- $.toc = function(tocList) {
655
- $(tocList).addClass('jquery-toc');
656
- var tocListArray = tocList.split(',');
657
- $.each(tocListArray, function(i,v) { tocListArray[i] = $.trim(v); });
658
- var $elements = $('.jquery-toc');
659
- $('body').append('<div></div>');
660
- var $toc = $('body div:last');
661
- var lastLevel = 1;
662
- $toc.append('<ul class="jquery-toc-1"></ul>');
663
- $elements.each(function() {
664
- var $e = $(this);
665
- var text = $e.text();
666
- var anchor = text.replace(/ /g,'-');
667
- $e.before('<a name="' + anchor + '"></a>');
668
- var level;
669
- $.each(tocListArray, function(i,v) {
670
- if (v.match(' ')) {
671
- var vArray = v.split(' ');
672
- var e = vArray[vArray.length - 1];
673
- } else { e = v; }
674
- if ($e.is(e)) { level = i+1; }
675
- });
676
- var className = 'jquery-toc-' + level;
677
- var li = '<li><a href="#' + anchor + '">' + text + '</a></li>';
678
- if (level == lastLevel) {
679
- $('ul.' + className + ':last',$toc).append(li);
680
- } else if (level > lastLevel) {
681
- var parentLevel = level - 1;
682
- var parentClassName = 'jquery-toc-' + parentLevel;
683
- $('ul.' + parentClassName + ':last',$toc).
684
- append('<ul class="' + className + '"></ul>');
685
- $('ul.' + className + ':last',$toc).append(li);
686
- } else if (level < lastLevel) {
687
- $('ul.' + className + ':last',$toc).append(li);
688
- }
689
- lastLevel = level;
690
- });
691
- var $toc_ul = $('ul.jquery-toc-1',$toc);
692
- $toc.remove();
693
- return($toc_ul);
694
- }
695
- })(jQuery);
696
- </script>
697
-
698
- <script>
699
- function toc_toggle() {
700
- $('#toc_side').toggle();
701
- $("pre").addClass("pass");
702
- $("pre:contains('FAIL:')").addClass("fail");
703
- $("pre:contains('ERROR:')").addClass("error");
704
- };
705
-
706
- $.toc('#content h1,h2,h3,h4').appendTo('.toc');
707
-
708
- toc_toggle();
709
- </script>
710
-