ae 1.0.0 → 1.1.0
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/MANIFEST +3 -1
- data/{README → README.rdoc} +40 -17
- data/demo/01_overview.rdoc +25 -30
- data/demo/03_assert.rdoc +55 -22
- data/demo/04_subjunctive.rdoc +32 -59
- data/demo/05_expect.qed +83 -0
- data/doc/qedoc/index.html +119 -113
- data/lib/ae.rb +1 -0
- data/lib/ae/assertor.rb +14 -0
- data/lib/ae/core_ext.rb +2 -2
- data/lib/ae/expect.rb +124 -0
- data/meta/homepage +1 -1
- data/meta/version +1 -1
- metadata +8 -8
data/demo/05_expect.qed
ADDED
@@ -0,0 +1,83 @@
|
|
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
|
+
|
9
|
+
== Underlying Comparison
|
10
|
+
|
11
|
+
Expect uses #=== for comparison. So providing an argument and a block to
|
12
|
+
#expect we can test for a somewhat broader range of compassion than #assert.
|
13
|
+
For example we can test for a subclass.
|
14
|
+
|
15
|
+
expect Numeric do
|
16
|
+
3
|
17
|
+
end
|
18
|
+
|
19
|
+
Assertion.assert.raised? do
|
20
|
+
expect Numeric do
|
21
|
+
"3"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
== Exception Expectation
|
27
|
+
|
28
|
+
If the comparator is an Exception class or a instance of an Exception class,
|
29
|
+
then #expect will check to see if the block raises that kind of exception.
|
30
|
+
|
31
|
+
expect StandardError do
|
32
|
+
some_undefined_method
|
33
|
+
end
|
34
|
+
|
35
|
+
expect Assertion do
|
36
|
+
expect(nil)
|
37
|
+
end
|
38
|
+
|
39
|
+
This is an important distinction to note because it means #expect can not be used
|
40
|
+
if verify instances of Exception classes.
|
41
|
+
|
42
|
+
Assertion.assert.raised? do
|
43
|
+
expect Exception do
|
44
|
+
Exception.new
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
== Regex Expectations
|
50
|
+
|
51
|
+
That #expect entails #=== also means we can check for Regexp matches.
|
52
|
+
|
53
|
+
expect /x/ do
|
54
|
+
"oooxooo"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
== Expected Method
|
59
|
+
|
60
|
+
We can use #expected to make the receiver the object of expectation.
|
61
|
+
|
62
|
+
x = "dummy"
|
63
|
+
|
64
|
+
/x/.expected do
|
65
|
+
"x"
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
== Function without Block
|
70
|
+
|
71
|
+
Without a block, the receiver is compared to the argument.
|
72
|
+
|
73
|
+
x.expect String
|
74
|
+
|
75
|
+
|
76
|
+
== Functor, or Higher Order Function
|
77
|
+
|
78
|
+
Like #assert, #expect can be used used as a *fluid* notation.
|
79
|
+
|
80
|
+
10.expect == 10
|
81
|
+
|
82
|
+
In which case it works just like #assert.
|
83
|
+
|
data/doc/qedoc/index.html
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
/* Debug borders */
|
9
9
|
/* p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 { border: 1px solid red; } */
|
10
10
|
|
11
|
-
body { font-size:
|
11
|
+
body { font-size: 14px; line-height: 20px; margin: 1em 5% 1em 5%; font-family: Verdana, Arial, Helvetica, sans-serif; }
|
12
12
|
a { color: #336; text-decoration: underline; }
|
13
13
|
a:visited { color: #334; }
|
14
14
|
em { font-style: italic; }
|
@@ -114,20 +114,16 @@ Requiring the AE library.
|
|
114
114
|
</pre>
|
115
115
|
<p>
|
116
116
|
Loads two classes, <tt>Assertion</tt> and <tt>Assertor</tt>, the Kernel
|
117
|
-
method <tt>assert</tt> and it’s ancillaries
|
117
|
+
method <tt>assert</tt> and it’s ancillaries <tt>assert!</tt> and
|
118
118
|
<tt>refute</tt> and a set of core extensions that make writing certain
|
119
119
|
types of assertions easier.
|
120
120
|
</p>
|
121
121
|
<h2>Assertion and Assertor Classes</h2>
|
122
122
|
<p>
|
123
|
-
The <tt>Assertion</tt> class is
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
The <tt>Assertion</tt> class is at the heart of AE. All other AE method
|
128
|
-
resolve by… The <tt>Assertion</tt> class is at subclass of Exception.
|
129
|
-
When an assertion is made, and fails, it is an instance of Assertion that
|
130
|
-
is raised.
|
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.
|
131
127
|
</p>
|
132
128
|
<pre>
|
133
129
|
Assertion.assert.raised? do
|
@@ -137,13 +133,11 @@ is raised.
|
|
137
133
|
</pre>
|
138
134
|
<p>
|
139
135
|
Like any raised exception, the last Assertion message is available via
|
140
|
-
|
136
|
+
<tt>$!</tt>.
|
141
137
|
</p>
|
142
138
|
<p>
|
143
|
-
(FYI, in Test::Unit the equivalent class was called
|
144
|
-
|
145
|
-
was discoverd to be the choosen term in minitest —proving good ideas
|
146
|
-
find their way to the top.)
|
139
|
+
(FYI, in Test::Unit the equivalent class was called
|
140
|
+
<tt>AssertionFailedError</tt>.)
|
147
141
|
</p>
|
148
142
|
<p>
|
149
143
|
Assertions themsevles are not generally used in creating tests or behavior
|
@@ -151,21 +145,22 @@ specifications. Rather they are used to create additonal types of assertion
|
|
151
145
|
methods.
|
152
146
|
</p>
|
153
147
|
<p>
|
154
|
-
As mentioned above the <tt>Assertor</tt> class is a type of
|
155
|
-
|
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
|
156
150
|
monitor for failed conditions, upon which is raises Assertion exceptions.
|
157
151
|
</p>
|
158
152
|
<h2>Assertion Methods</h2>
|
159
153
|
<p>
|
160
|
-
The three methods, <tt>assert</tt>,
|
161
|
-
return an Assertor instance when used fluidly, i.e. magic-dot notation,
|
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,
|
162
156
|
higher-order notation, functor notation, whatever you prefer to call it.
|
163
157
|
</p>
|
164
158
|
<pre>
|
165
159
|
assert(Assertor === assert)
|
166
160
|
</pre>
|
167
161
|
<p>
|
168
|
-
|
162
|
+
Through the use of <tt>method_missing</tt>, the Assertor allows us to write
|
163
|
+
statements like:
|
169
164
|
</p>
|
170
165
|
<pre>
|
171
166
|
1.assert == 1
|
@@ -180,14 +175,14 @@ raised.
|
|
180
175
|
end
|
181
176
|
</pre>
|
182
177
|
<p>
|
183
|
-
The methods
|
184
|
-
expect they purport the negative condition. Patterned after
|
185
|
-
own use of
|
186
|
-
"assert not". While
|
187
|
-
|
188
|
-
them.
|
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’s own use of "<tt>!</tt>" as meaning <tt>not</tt>,
|
181
|
+
<tt>assert!</tt> should be read "assert not". 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.
|
189
184
|
</p>
|
190
|
-
<h2>How It
|
185
|
+
<h2>How It Works</h2>
|
191
186
|
<p>
|
192
187
|
An Assertor essentially sits in wait for a method call (via
|
193
188
|
method_missing). When that happens it applies the method to the original
|
@@ -212,13 +207,13 @@ Obviously using Assertor methods are whole lot more concise.
|
|
212
207
|
<h1>Assert Method</h1>
|
213
208
|
<h2>Compatible with Test::Unit</h2>
|
214
209
|
<p>
|
215
|
-
The
|
216
|
-
method in
|
210
|
+
The <tt>assert</tt> method is designed to be backward compatible with the
|
211
|
+
same method in <tt>Test::Unit</tt>.
|
217
212
|
</p>
|
218
213
|
<p>
|
219
|
-
Using an argument,
|
220
|
-
Optionally one can send along a meaningful message should the
|
221
|
-
fail.
|
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.
|
222
217
|
</p>
|
223
218
|
<pre>
|
224
219
|
assert(true, "Not true!")
|
@@ -229,9 +224,9 @@ fail.
|
|
229
224
|
</pre>
|
230
225
|
<h2>Assert with a Block</h2>
|
231
226
|
<p>
|
232
|
-
In addition
|
233
|
-
the argument, the block is expected to return something that
|
234
|
-
true.
|
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.
|
235
230
|
</p>
|
236
231
|
<pre>
|
237
232
|
assert do
|
@@ -256,23 +251,24 @@ block as a block argument.
|
|
256
251
|
</pre>
|
257
252
|
<h2>Antonyms for Assert</h2>
|
258
253
|
<p>
|
259
|
-
We can state the opposite assertion using
|
254
|
+
We can state the opposite assertion using <tt>assert!</tt>.
|
260
255
|
</p>
|
261
256
|
<pre>
|
262
257
|
10.assert! == 9
|
263
258
|
</pre>
|
264
259
|
<p>
|
265
|
-
Or, because some people do not like the use of a bang method,
|
260
|
+
Or, because some people do not like the use of a bang method,
|
261
|
+
<tt>refute</tt>.
|
266
262
|
</p>
|
267
263
|
<pre>
|
268
264
|
10.refute == 9
|
269
265
|
</pre>
|
270
266
|
<p>
|
271
|
-
These terms can be used just as
|
272
|
-
the opposite inference.
|
267
|
+
These terms can be used just as <tt>assert</tt> is used in all examples,
|
268
|
+
but with the opposite inference.
|
273
269
|
</p>
|
274
270
|
<p>
|
275
|
-
Another way to get the opposite inference, is to use
|
271
|
+
Another way to get the opposite inference, is to use <tt>not</tt>.
|
276
272
|
</p>
|
277
273
|
<pre>
|
278
274
|
10.assert.not == 9
|
@@ -286,24 +282,24 @@ Rather then the general form:
|
|
286
282
|
x.assert.object_id == x.object_id
|
287
283
|
</pre>
|
288
284
|
<p>
|
289
|
-
We can use Ruby’s own
|
285
|
+
We can use Ruby’s own <tt>equal?</tt> method.
|
290
286
|
</p>
|
291
287
|
<pre>
|
292
288
|
x.assert.equal?(x)
|
293
289
|
</pre>
|
294
290
|
<p>
|
295
|
-
AE provides
|
296
|
-
clear.
|
291
|
+
AE provides <tt>identical?</tt> method as an alternative to make it a bit
|
292
|
+
more clear.
|
297
293
|
</p>
|
298
294
|
<pre>
|
299
295
|
x.assert.identical?(x)
|
300
296
|
</pre>
|
301
297
|
<h2>Equality Assertions</h2>
|
302
298
|
<p>
|
303
|
-
The most common assertion is that of value equality (
|
304
|
-
throughout this document. But other forms of equality can be
|
305
|
-
easily. We have already mentioned identity. In addition there
|
306
|
-
|
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>.
|
307
303
|
</p>
|
308
304
|
<pre>
|
309
305
|
17.assert.eql? 17
|
@@ -313,7 +309,7 @@ Equality*.
|
|
313
309
|
end
|
314
310
|
</pre>
|
315
311
|
<p>
|
316
|
-
And there is
|
312
|
+
And there is <em>case equality</em>.
|
317
313
|
</p>
|
318
314
|
<pre>
|
319
315
|
Numeric.assert === 3
|
@@ -323,11 +319,12 @@ And there is *Case Equality*.
|
|
323
319
|
Because operators can not take blocks, and at times blocks can be
|
324
320
|
convenient means of supplying a value to an assertion, AE has defined
|
325
321
|
alternate renditions of the equality methods. For equal? and eql?, the
|
326
|
-
method
|
322
|
+
method names are the same, they simply can take a block in place of an
|
327
323
|
argument if need be.
|
328
324
|
</p>
|
329
325
|
<p>
|
330
|
-
For
|
326
|
+
For <em>value equality</em> (<tt>==</tt>), the method is called
|
327
|
+
<tt>eq?</tt>.
|
331
328
|
</p>
|
332
329
|
<pre>
|
333
330
|
10.assert.eq? do
|
@@ -345,7 +342,7 @@ And should it fail…
|
|
345
342
|
end
|
346
343
|
</pre>
|
347
344
|
<p>
|
348
|
-
For
|
345
|
+
For <em>case equality</em> (<tt>===</tt>), it is <tt>case?</tt>.
|
349
346
|
</p>
|
350
347
|
<pre>
|
351
348
|
Numeric.assert.case? do
|
@@ -388,7 +385,7 @@ with <tt>instance_eval</tt> makes it easy too.
|
|
388
385
|
</pre>
|
389
386
|
<h2>Catch/Try Assertions</h2>
|
390
387
|
<p>
|
391
|
-
Catch/Try throws can be tested via
|
388
|
+
Catch/Try throws can be tested via <tt>Symbol#thrown?</tt>.
|
392
389
|
</p>
|
393
390
|
<pre>
|
394
391
|
:hookme.assert.thrown? do
|
@@ -397,7 +394,7 @@ Catch/Try throws can be tested via +Symbol#thrown?+.
|
|
397
394
|
</pre>
|
398
395
|
<p>
|
399
396
|
Alternatively, a lambda containing the potential throw can be the receiver
|
400
|
-
using
|
397
|
+
using <tt>throws?</tt>.
|
401
398
|
</p>
|
402
399
|
<pre>
|
403
400
|
hook = lambda{ throw :hookme }
|
@@ -424,7 +421,7 @@ Ruby already provides the #nil? method.
|
|
424
421
|
nil.assert.nil?
|
425
422
|
</pre>
|
426
423
|
<p>
|
427
|
-
AE
|
424
|
+
AE adds <tt>true?</tt> and <tt>false?</tt> which acts accordingly.
|
428
425
|
</p>
|
429
426
|
<pre>
|
430
427
|
true.assert.true?
|
@@ -461,25 +458,60 @@ reusable assertions.
|
|
461
458
|
|
462
459
|
"abracarba".assert palindrome
|
463
460
|
</pre>
|
461
|
+
<h2>Verifying Object State</h2>
|
464
462
|
<p>
|
465
|
-
|
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…
|
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.
|
466
499
|
</p>
|
467
500
|
|
468
501
|
<h1>Subjunctives</h1>
|
469
502
|
<p>
|
470
|
-
Okay. I can hear the BDDers rumbling, "where’s the
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
<tt>it</tt>.
|
503
|
+
Okay. I can hear the BDDers rumbling, "where’s the should?"
|
504
|
+
AE has nothing against "should", 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’s use of <tt>it</tt>.
|
477
509
|
</p>
|
478
510
|
<p>
|
479
|
-
Even so, AE provides a an optional mixin called Subjunctive which
|
480
|
-
used to create assertor methods
|
481
|
-
<tt>should</tt
|
482
|
-
|
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:
|
483
515
|
</p>
|
484
516
|
<pre>
|
485
517
|
require 'ae/subjunctive'
|
@@ -504,26 +536,26 @@ terms, <tt>should</tt> and <tt>must</tt> as optional add-ons.
|
|
504
536
|
<p>
|
505
537
|
We will use these two methods interchangeable for the rest of this
|
506
538
|
demonstration, but to be clear they both work exactly the same way, and
|
507
|
-
almost exactly like
|
539
|
+
almost exactly like <tt>assert</tt>.
|
508
540
|
</p>
|
509
541
|
<p>
|
510
542
|
Keep in mind, AE "conical" functionality does not entail
|
511
|
-
subjunctive forms
|
512
|
-
|
513
|
-
|
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.
|
514
546
|
</p>
|
515
547
|
<h2>Fluent Notation and Antonyms</h2>
|
516
548
|
<p>
|
517
|
-
Like <tt>assert</tt>, <tt>should</tt> and <tt>must</tt> can be used as
|
518
|
-
higher order
|
549
|
+
Like <tt>assert</tt>, <tt>should</tt> and <tt>must</tt> can be used as
|
550
|
+
higher order functions.
|
519
551
|
</p>
|
520
552
|
<pre>
|
521
553
|
4.should == 4
|
522
554
|
4.must == 4
|
523
555
|
</pre>
|
524
556
|
<p>
|
525
|
-
With the antonym of
|
526
|
-
<tt>shouldnt</tt>, and for <tt>must</tt>,
|
557
|
+
With the antonym of <tt>should!</tt> (read "should not") or
|
558
|
+
<tt>shouldnt</tt>, and for <tt>must</tt>, <tt>must!</tt> and <tt>wont</tt>.
|
527
559
|
</p>
|
528
560
|
<pre>
|
529
561
|
4.should! == 5
|
@@ -545,22 +577,30 @@ On occasions where the English readability of a specification is hindered,
|
|
545
577
|
<p>
|
546
578
|
The <tt>be</tt> method is the same as <tt>assert</tt> with the single
|
547
579
|
exception that it will compare a lone argument to the receiver using
|
548
|
-
+equate?+, unlike <tt>assert</tt> which simply
|
580
|
+
+equate?+, unlike <tt>assert</tt> which simply checks to see that the
|
549
581
|
argument evalutates as true.
|
550
582
|
</p>
|
551
583
|
<pre>
|
552
584
|
10.should.be 10
|
553
585
|
10.should.be 10.0
|
554
586
|
10.should.be Numeric
|
587
|
+
|
588
|
+
Assertion.assert.raised? do
|
589
|
+
10.should.be "40"
|
590
|
+
end
|
555
591
|
</pre>
|
556
592
|
<h2>Indefinite Articles</h2>
|
557
593
|
<p>
|
558
|
-
Addtional
|
559
|
-
|
560
|
-
|
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.
|
561
597
|
</p>
|
562
598
|
<pre>
|
563
599
|
"hi".must.be.a String
|
600
|
+
|
601
|
+
Assertion.assert.raised? do
|
602
|
+
/x/.must.be.a /x/
|
603
|
+
end
|
564
604
|
</pre>
|
565
605
|
<p>
|
566
606
|
Otherwise they are interchangeble.
|
@@ -569,47 +609,13 @@ Otherwise they are interchangeble.
|
|
569
609
|
"hi".must.be.an.instance_of?(String)
|
570
610
|
</pre>
|
571
611
|
<p>
|
572
|
-
The indefinite articles work well when a noun
|
612
|
+
The indefinite articles work well when a noun follows as an arguments.
|
573
613
|
</p>
|
574
614
|
<pre>
|
575
615
|
palindrome = lambda{ |x| x == x.reverse }
|
576
616
|
|
577
617
|
"abracarba".must.be.a palindrome
|
578
618
|
</pre>
|
579
|
-
<h2>Verifying Object State</h2>
|
580
|
-
<p>
|
581
|
-
The block notation of the subjunctive form is similar to <tt>assert</tt>,
|
582
|
-
with the important exception that the block is is evaluated in the scope of
|
583
|
-
the receiver via #instance_eval, if no block parameter is designated. This
|
584
|
-
can be also be used to test the state of an object.
|
585
|
-
</p>
|
586
|
-
<pre>
|
587
|
-
class X
|
588
|
-
attr :a
|
589
|
-
def initialize(a); @a = a; end
|
590
|
-
end
|
591
|
-
|
592
|
-
x = X.new(4)
|
593
|
-
|
594
|
-
x.must do
|
595
|
-
4 == @a
|
596
|
-
end
|
597
|
-
</pre>
|
598
|
-
<p>
|
599
|
-
And should it fail…
|
600
|
-
</p>
|
601
|
-
<pre>
|
602
|
-
Assertion.assert.raised? do
|
603
|
-
x.must do
|
604
|
-
5 == @a
|
605
|
-
end
|
606
|
-
end
|
607
|
-
</pre>
|
608
|
-
<p>
|
609
|
-
For some this might seem controversial —to test underlying
|
610
|
-
implementation. And you will get no argument here, it should be used
|
611
|
-
thoughtfully, but there are occasions when such validations are necessary.
|
612
|
-
</p>
|
613
619
|
<p>
|
614
620
|
QED.
|
615
621
|
</p>
|