ae 1.8.2 → 1.9.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 23a2b354470346c0cce0e01593887716f750919349cac99c6ec35bdb079a56d7
4
+ data.tar.gz: '013992a3d412b79836902cf8234c3acb6629cfbcf3654e1da51d51144bc43990'
5
+ SHA512:
6
+ metadata.gz: ccfba2d7d7d331f1531810b953c9cf38663f81a3dac682179288c09a8472b510de405034d4bd9334a6872f9a46c96b8e8e94c526b7744c1f20b124b98162aa00
7
+ data.tar.gz: bdfe778a71801e72f005f8f467d3a0cf1f8f0dac106d43fd0c6a146d3ac176d7c6b249dfe3ee437983b733419371d0861e6c6159c2c9e9824600e5bb477ddb36
data/HISTORY.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # RELEASE HISTORY
2
2
 
3
+ ## 1.9.0 / 2026-03-30
4
+
5
+ Maintenance release. Modernized project tooling and cleaned up documentation.
6
+
7
+ Changes:
8
+
9
+ * Replace custom Indexer system with standard gemspec.
10
+ * Replace Travis CI with GitHub Actions.
11
+ * Replace Assembly/detroit with Rakefile.
12
+ * Simplify version.rb to use a plain constant.
13
+ * Update minitest adapter for minitest 5+.
14
+ * Update testunit adapter for modern test-unit gem.
15
+ * Fix typos and update URLs to HTTPS.
16
+ * Add LICENSE.txt.
17
+ * Move site from gh-pages to docs/.
18
+ * Remove obsolete files (var/, etc/, MANIFEST, DEMO.rdoc).
19
+ * Clean up .gitignore.
20
+
21
+
3
22
  ## 1.8.2 / 2013-02-18
4
23
 
5
24
  This release primarily fixes one bug --the assertions count
data/LICENSE.txt ADDED
@@ -0,0 +1,24 @@
1
+ (BSD-2-Clause License)
2
+
3
+ Copyright (c) 2008 Thomas Sawyer. All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
17
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18
+ COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22
+ OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # Assertive Expressive
2
2
 
3
- [Homepage](http://rubyworks.github.com/ae) /
4
- [Source Code](http://github.com/rubyworks/ae) /
5
- [Documentation](http://rubydoc.info/gems/ae) /
6
- [User Manual](http://wiki.github.com/rubyworks/ae) /
7
- [Report Issue](http://github.com/rubyworks/ae/issues) /
8
- [Mailing List](http://googlegroups.com/group/rubyworks-mailinglist) /
9
- [IRC Channel](irc://irc.freenode.net/rubyworks)    
10
- [![Build Status](https://secure.travis-ci.org/rubyworks/qed.png)](http://travis-ci.org/rubyworks/ae)
11
- [![Gem Version](https://badge.fury.io/rb/qed.png)](http://badge.fury.io/rb/ae)
3
+ [Website](https://rubyworks.github.io/ae) /
4
+ [API](https://rubydoc.info/gems/ae) /
5
+ [Report Issue](https://github.com/rubyworks/ae/issues) /
6
+ [Source Code](https://github.com/rubyworks/ae)
7
+
8
+ [![Gem Version](https://img.shields.io/gem/v/ae.svg?style=flat)](https://rubygems.org/gems/ae)
9
+ [![Build Status](https://github.com/rubyworks/ae/actions/workflows/test.yml/badge.svg)](https://github.com/rubyworks/ae/actions/workflows/test.yml)
12
10
 
13
11
 
14
12
  ## About
@@ -25,12 +23,12 @@ intended for reuse by any TDD, BDD or similar system.
25
23
  * Core extensions are standardized around Ruby Facets.
26
24
  * But Facets is not a dependency; the extensions are built-in.
27
25
  * Easily extensible allowing for alternate notations.
28
- * Eats it's own dog food.
26
+ * Eats its own dog food.
29
27
 
30
28
 
31
29
  ## Synopsis
32
30
 
33
- AE defines the method `assert`. It's is compatible with the method
31
+ AE defines the method `assert`. It is compatible with the method
34
32
  as defined by Test::Unit and MiniTest, which verifies truth of a
35
33
  single argument (and can accept an optional failure message).
36
34
 
@@ -154,6 +152,20 @@ and do:
154
152
  Windows users use 'ruby setup.rb all'.
155
153
 
156
154
 
155
+ ## Contributing
156
+
157
+ If you would like to contribute code to the AE project, for the upstream
158
+ repository and create a branch for you changes. When your changes are ready
159
+ for review (and no, they do not have to 100% perfect if you still have some issues
160
+ you need help working out).
161
+
162
+ It you need to personally discuss some ideas or issue you try to get up with us
163
+ via the mailing list or the IRC channel.
164
+
165
+ * [Source Code](https://github.com/rubyworks/ae) /
166
+ * [Mailing List](https://groups.google.com/group/rubyworks-mailinglist)
167
+
168
+
157
169
  ## Copyrights & License
158
170
 
159
171
  Copyright (c) 2008 Rubyworks. All rights reserved.
@@ -162,7 +174,7 @@ Unless otherwise provided for by the originating author, this
162
174
  program is distributed under the terms of the *BSD-2-Clause* license.
163
175
  Portions of this program may be copyrighted by others.
164
176
 
165
- See the NOTICE.rdoc file for details.
177
+ See the NOTICE.md file for details.
166
178
 
167
- AE is a [Rubyworks](http://rubyworks.github.com) project.
179
+ AE is a [Rubyworks](https://rubyworks.github.io) project.
168
180
 
@@ -0,0 +1,92 @@
1
+ # Introduction
2
+
3
+ AE is an assertions framework for Ruby. It's designed
4
+ around the concept of an Assertor. The Assertor is an
5
+ Assertion Functor, or Higher-Order Function, which
6
+ reroutes method calls while monitoring them for failing
7
+ conditions.
8
+
9
+
10
+ ## What AE Provides
11
+
12
+ Requiring the AE library.
13
+
14
+ require 'ae'
15
+
16
+ Loads two classes, +Assertion+ and +Assertor+, the Kernel
17
+ method +assert+ and it's antonyms +assert!+ and +refute+
18
+ and a set of core extensions that make writing certain types
19
+ of assertions easier.
20
+
21
+
22
+ ## Assertion and Assertor Classes
23
+
24
+ The +Assertion+ class is at the heart of AE. All other AE
25
+ methods depend on it. The +Assertion+ class is a subclass
26
+ of Exception. When an assertion is made and fails, it is
27
+ an instance of Assertion that is raised.
28
+
29
+ expect Assertion do
30
+ msg = "my failure message"
31
+ assert false, msg
32
+ end
33
+
34
+ Like any raised exception, the last Assertion message is available
35
+ via `$!`.
36
+
37
+ (FYI, in Test::Unit the equivalent class was called +AssertionFailedError+.)
38
+
39
+ Assertions themselves are not generally used in creating tests or
40
+ behavior specifications. Rather they are used to create additional
41
+ types of assertion methods.
42
+
43
+ As mentioned above the +Assertor+ class is a type of Higher-Order
44
+ function, or Functor, which intercedes with a normal message
45
+ invocation to monitor for failed conditions, upon which is raises
46
+ Assertion exceptions.
47
+
48
+
49
+ ## Assertion Methods
50
+
51
+ The three methods, +assert+, <tt>assert!</tt> and +refute+ all
52
+ return an Assertor instance when used fluidly, i.e. magic-dot
53
+ notation, higher-order notation, functor notation, whatever you
54
+ prefer to call it.
55
+
56
+ assert(AE::Assertor === assert)
57
+
58
+ Through the use of +method_missing+, the Assertor allows us to write
59
+ statements like:
60
+
61
+ 1.assert == 1
62
+
63
+ If the operation evaluates to false or nil, then an Assertion error
64
+ is raised.
65
+
66
+ expect Assertion do
67
+ 1.assert == 2
68
+ end
69
+
70
+ The methods <tt>assert!</tt> and +refute+ are just like +assert+
71
+ expect they purport the negative condition. Patterned after Ruby's
72
+ own use of "<tt>!</tt>" as meaning +not+, <tt>assert!</tt> should be
73
+ read "assert not". While +refute+ exists for the sake of those who
74
+ find the use of a bang method for this purpose unsuited to them.
75
+
76
+
77
+ ## How It Works
78
+
79
+ An Assertor essentially sits in wait for a method call (via
80
+ method_missing). When that happens it applies the method to the
81
+ original receiver, but wrapped in a clause that raises an
82
+ Assertion should the statement fail. If we wanted to be
83
+ pedantic, we could write our assertions like:
84
+
85
+ raise Assertion.new("1 != 1") unless 1 == 1
86
+
87
+ Instead of
88
+
89
+ 1.assert == 1
90
+
91
+ Obviously using Assertor methods are whole lot more concise.
92
+
@@ -0,0 +1,4 @@
1
+ # Assertion Class
2
+
3
+ The Assertion class is a subclass of Exception and is the error raised when
4
+ and assertion fails.
data/demo/03_assert.md ADDED
@@ -0,0 +1,300 @@
1
+ # Assert Method
2
+
3
+ ## Compatible with Test::Unit
4
+
5
+ The `assert` method is designed to be backward compatible
6
+ with the same method in `Test::Unit`.
7
+
8
+ Using an argument, `assert` will check that an argument evaluates
9
+ to true. Optionally one can send along a meaningful message should
10
+ the assertion fail.
11
+
12
+ assert(true, "Not true!")
13
+
14
+ expect Assertion do
15
+ assert(false, "Not true!")
16
+ end
17
+
18
+
19
+ ## Assert with a Block
20
+
21
+ In addition +assert+ has been extended to accept a block. Like the case of the
22
+ argument, the block is expected to return something that evaluates as true.
23
+
24
+ assert do
25
+ true
26
+ end
27
+
28
+ Assertion.assert.raised? do
29
+ assert do
30
+ false
31
+ end
32
+ end
33
+
34
+ We should also mention that, while probably not very useful, since
35
+ the arity of a block can be checked, one can also pass the receiver
36
+ into the block as a block argument.
37
+
38
+ "hi".assert do |s|
39
+ /h/ =~ s
40
+ end
41
+
42
+
43
+ ## Antonyms for Assert
44
+
45
+ We can state the opposite assertion using `assert!`.
46
+
47
+ 10.assert! == 9
48
+
49
+ Or, because some people do not like the use of a bang method, +refute+.
50
+
51
+ 10.refute == 9
52
+
53
+ These terms can be used just as +assert+ is used in all examples,
54
+ but with the opposite inference.
55
+
56
+ Another way to get the opposite inference, is to use +not+.
57
+
58
+ 10.assert.not == 9
59
+
60
+ ## Lambda Assertions
61
+
62
+ Passing +assert+ a `Proc` object, or any object that responds to `#call`,
63
+ will be used as if it were a block. This allows for a simple way to quickly
64
+ create reusable assertions.
65
+
66
+ palindrome = lambda{ |word| word == word.reverse }
67
+
68
+ "abracarba".assert palindrome
69
+
70
+ The message for a failed assertion will come from calling `#to_s` on the
71
+ object.
72
+
73
+ ## RSpec-style Assertion Matchers
74
+
75
+ If an object passed to assert responds to `#matches?` then AE will handle
76
+ the object as an RSpec-style mather, the receiver will be passed to the
77
+ `#matches?` method to determine if the assertion passes and RSpec matcher
78
+ message methods will be used if they are defined.
79
+
80
+ palindrome = Object.new
81
+
82
+ def palindrome.matches?(word)
83
+ word == word.reverse
84
+ end
85
+
86
+ "abracarba".assert palindrome
87
+
88
+
89
+ ## Identity Assertions
90
+
91
+ Rather then the general form.
92
+
93
+ x = 10
94
+ x.assert.object_id == x.object_id
95
+
96
+ We can use Ruby's own `equal?`> method.
97
+
98
+ x.assert.equal?(x)
99
+
100
+ AE provides `identical?`> method as an alternative
101
+ to make it a bit more clear.
102
+
103
+ x.assert.identical?(x)
104
+
105
+
106
+ ## Equality Assertions
107
+
108
+ The most common assertion is that of value equality (`==`),
109
+ as we have seen throughout this document. But other forms of
110
+ equality can be verified as easily. We have already mentioned
111
+ identity. In addition there is *type equality*.
112
+
113
+ 17.assert.eql? 17
114
+
115
+ Assertion.assert.raised? do
116
+ 17.assert.eql? 17.0
117
+ end
118
+
119
+ And there is *case equality*.
120
+
121
+ Numeric.assert === 3
122
+
123
+
124
+ ## Checking Equality with a Block
125
+
126
+ Because operators can not take blocks, and at times blocks can
127
+ be convenient means of supplying a value to an assertion,
128
+ AE has defined alternate renditions of the equality methods.
129
+ For equal? and eql?, the method names are the same, they simply
130
+ can take a block in place of an argument if need be.
131
+
132
+ For *value equality* (`==`), the method is called *eq?*.
133
+
134
+ 10.assert.eq? do
135
+ 10.0
136
+ end
137
+
138
+ And should it fail,
139
+
140
+ Assertion.assert.raised? do
141
+ 10.assert.eq? do
142
+ 20
143
+ end
144
+ end
145
+
146
+
147
+ ## Case Equality
148
+
149
+ For *case equality* (`===`), it is `case?`.
150
+
151
+ Numeric.assert.case? do
152
+ "3".to_i
153
+ end
154
+
155
+ Assertion.assert.raised? do
156
+ Numeric.assert.case? do
157
+ "3"
158
+ end
159
+ end
160
+
161
+
162
+ ## Regular Expressions
163
+
164
+ Regular Expressions can be used to make assertions in much the same way as equality.
165
+
166
+ /i/.assert =~ "i"
167
+
168
+ Assertion.assert.raised? do
169
+ /i/.assert =~ "g"
170
+ end
171
+
172
+ Conversely the String class recognizes the #=~ method as well.
173
+
174
+ "i".assert =~ /i/
175
+
176
+ Assertion.assert.raised? do
177
+ "i".assert =~ /g/
178
+ end
179
+
180
+
181
+ ## Exception Assertions
182
+
183
+ Validating errors is easy too, as has already been shown
184
+ in the document to verify assertion failures.
185
+
186
+ StandardError.assert.raised? do
187
+ unknown_method
188
+ end
189
+
190
+
191
+ ## Assertions on Object State
192
+
193
+ While testing or specifying the internal state of an object is
194
+ generally considered poor form, there are times when it is
195
+ necessary. Assert combined with +instance_eval+ makes it easy too.
196
+
197
+ class X
198
+ attr :a
199
+ def initialize(a); @a = a; end
200
+ end
201
+
202
+ x = X.new(1)
203
+
204
+ x.assert.instance_eval do
205
+ @a == 1
206
+ end
207
+
208
+
209
+ ## Catch/Try Assertions
210
+
211
+ Catch/Try throws can be tested via `Symbol#thrown?`.
212
+
213
+ :hookme.assert.thrown? do
214
+ throw :hookme
215
+ end
216
+
217
+ Alternatively, a lambda containing the potential throw
218
+ can be the receiver using `throws?`.
219
+
220
+ hook = lambda{ throw :hookme }
221
+
222
+ hook.assert.throws?(:hookme)
223
+
224
+
225
+ ## Assertions on Proc Changes
226
+
227
+ I have to admit I'm not sure how this is useful,
228
+ but I found it in the Bacon API and ported it over
229
+ just for sake of thoroughness.
230
+
231
+ a = 0
232
+
233
+ l = lambda{ a }
234
+
235
+ l.assert.change?{ a +=1 }
236
+
237
+
238
+ ## Assertion on literal True, False and Nil
239
+
240
+ Ruby already provides the #nil? method.
241
+
242
+ nil.assert.nil?
243
+
244
+ AE adds `true?` and `false?` which acts accordingly.
245
+
246
+ true.assert.true?
247
+ false.assert.false?
248
+
249
+
250
+ ## Send Assertions
251
+
252
+ Assert that a method can be successfully called.
253
+
254
+ "STRING".assert.send?(:upcase)
255
+
256
+
257
+ ## Numeric Delta and Epsilon
258
+
259
+ You may wish to assert that a numeric value is with some
260
+ range.
261
+
262
+ 3.in_delta?(1,5)
263
+
264
+ Or minimum range.
265
+
266
+ 3.in_epsilon?(3,5)
267
+
268
+
269
+ ## Verifying Object State
270
+
271
+ Not surprisingly if underlying object state needs to be verified, +instance_eval+
272
+ can be used in conjunction with +assert+.
273
+
274
+ class X
275
+ attr :a
276
+ def initialize(a); @a = a; end
277
+ end
278
+
279
+ x = X.new(4)
280
+
281
+ x.instance_eval do
282
+ @a.assert == 4
283
+ end
284
+
285
+ However #instance_eval is a reserved method for the underlying Assertor class,
286
+ so it cannot be used on #assert, e.g.
287
+
288
+ x.assert.instance_eval do
289
+ @a == "obvisouly wrong"
290
+ end
291
+
292
+ AE offers an optional helper method for times when testing underlying private
293
+ or protected methods is important, called #pry. See the QED on pry for more
294
+ information.
295
+
296
+ For some testing underlying implementation might be considered poor
297
+ form. You will get no argument here. It should be used thoughtfully,
298
+ but I would not bet against there being occasions when such validations
299
+ might be needed.
300
+
@@ -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 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/should'
28
+ require 'ae/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 `test_helper.rb`,
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 `should!` (read "should not") and `shouldnt`.
47
+ For `must`, they are `must!` 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 `case?` (same as `#===`) instead of `equate?` when
83
+ 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
+