ae-1.8.2/ 0000755 0000000 0000000 00000000000 12406706117 010611 5 ustar root root ae-1.8.2/NOTICE.md 0000644 0000000 0000000 00000004021 12406706117 012111 0 ustar root root # COPYRIGHT NOTICES
## AE
Copyright:: (c) 2008 Thomas Sawyer
License: BSD-2-Clause
Copyright 2008 Thomas Sawyer. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of
conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other materials
provided with the distribution.
THIS SOFTWARE IS PROVIDED BY Thomas Sawyer ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Thomas Sawyer OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those of the
authors and should not be interpreted as representing official policies, either expressed
or implied, of Thoams Sawyer.
## BlankSlate
Copyright:: (c) 2004,2006 Jim Weirich
License:: Custom
AE::BasicObject is based on Jim Weirich's BlankSlate class.
Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
All rights reserved.
Permission is granted for use, copying, modification, distribution,
and distribution of modified versions of this work as long as the
above copyright notice is included.
ae-1.8.2/metadata.yml 0000644 0000000 0000000 00000005346 12406706117 013124 0 ustar root root --- !ruby/object:Gem::Specification
name: ae
version: !ruby/object:Gem::Version
version: 1.8.2
prerelease:
platform: ruby
authors:
- Trans
autorequire:
bindir: bin
cert_chain: []
date: 2013-02-18 00:00:00.000000000 Z
dependencies:
- !ruby/object:Gem::Dependency
name: ansi
requirement: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
type: :runtime
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
- !ruby/object:Gem::Dependency
name: detroit
requirement: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
- !ruby/object:Gem::Dependency
name: qed
requirement: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
type: :development
prerelease: false
version_requirements: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
description: ! "Assertive Expressive is an assertions library specifically designed
\nfor reuse by other test frameworks."
email:
- transfire@gmail.com
executables: []
extensions: []
extra_rdoc_files:
- DEMO.rdoc
- HISTORY.md
- README.md
- NOTICE.md
files:
- .ruby
- .yardopts
- lib/ae/adapter.rb
- lib/ae/adapters/minitest.rb
- lib/ae/adapters/rspec.rb
- lib/ae/adapters/testunit.rb
- lib/ae/ansi.rb
- lib/ae/assert.rb
- lib/ae/assertion.rb
- lib/ae/assertor.rb
- lib/ae/basic_object.rb
- lib/ae/check.rb
- lib/ae/core_ext/exception.rb
- lib/ae/core_ext/helpers.rb
- lib/ae/core_ext.rb
- lib/ae/expect.rb
- lib/ae/legacy.rb
- lib/ae/must.rb
- lib/ae/pry.rb
- lib/ae/should.rb
- lib/ae/subjunctive.rb
- lib/ae/version.rb
- lib/ae.rb
- lib/ae.yml
- DEMO.rdoc
- HISTORY.md
- README.md
- NOTICE.md
homepage: http://rubyworks.github.com/ae
licenses:
- BSD-2-Clause
post_install_message:
rdoc_options: []
require_paths:
- lib
required_ruby_version: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
required_rubygems_version: !ruby/object:Gem::Requirement
none: false
requirements:
- - ! '>='
- !ruby/object:Gem::Version
version: '0'
requirements: []
rubyforge_project:
rubygems_version: 1.8.24
signing_key:
specification_version: 3
summary: Assertive Expressive
test_files: []
has_rdoc:
ae-1.8.2/HISTORY.md 0000644 0000000 0000000 00000015141 12406706117 012276 0 ustar root root # RELEASE HISTORY
## 1.8.2 / 2013-02-18
This release primarily fixes one bug --the assertions count
global variable wasn't all caps, which prevented assertions
from being counted correctly.
Changes:
* Fix $ASSERTION_COUNTS letter case.
## 1.8.1 / 2011-12-04
Fixed missing ae/ansi.rb file from distribution.
Changes:
* Update manifest, missing ae/ansi.rb
## 1.8.0 / 2011-12-03 / Checkered Flag
This new release improves support for Proc-based assertions and
RSpec-style matchers. In addition, this release sees the optional
Check Ok/No library in a usable state. And, lastly, note the license
has been changed to BSD-2-Clause.
Changes:
* Finalize the Check mixin API.
* Improve Proc and RSpec-style matchers.
* Modernize the build configuration.
* Change licenses to BSD-2-Clause.
## 1.7.4 / 2011-06-08
Quick release fixes an issue due to Ruby 1.9+'s constant look-up
system. Yes, BasicObject has no clue. This is fixed using the
`const_missing` hook.
Changes:
* Add const_missing hook to Assertor class to redirect to
toplevel methods.
## 1.7.3 / 2011-06-06 / D-Day
This release simply adds a new optional help library, `ok.rb`.
The API is still in it's infancy, so it probably will change
but this early release can help refine it's development.
Changes:
* Add option `ok` helper library.
## 1.7.2 / 2011-06-02
Minor release adds color diffs for failed equality comparisons to
the error message, and it fixes an issue in which class references
needed the toplevel prefix (`::`) to ensure they can be found in
all cases. Note that ANSI color diffs can be deactivated via
AE.ansi = false or using the master switch an upcoming release
of the ANSI gem.
Changes:
* Add toplevel prefix (`::`) to class references in assertor.rb.
* Provide ANSI colored diffs for failed equality comparisons.
## 1.7.1 / 2011-05-06
This release adds a specialized message for certain comparison
operators to allow them have a more forensic output. This is done
via ANSI::Diff library. This release also deprecates the optional
dot.rb and detest.rb emulation scripts.
Changes:
* Add special message for comparison assertions.
* Remove optional dot.rb and detest.rb emulation scripts.
## 1.7.0 / 2011-04-28
AE now uses proper namespace for all classes. In particular, the `Assertor`
class has become `AE::Assertor`. Only the `Assertion` class remains outside
the `AE` namespace, as it is now used to map to the current exception class
for raising assertions as defined by current test framework. In addition,
AE's Kernel extensions, which are used to adapt AE for use with any given
test framework have been moved to the AE and AE::Assertor classes as
class methods along with AE's assertion count methods.
Changes:
* All AE classes use proper namespace.
* Framework methods moved to AE::Assertor class.
* Assertion count tracking methods moved to AE::Assertor class.
* AE::Assertion class simplified to a simple subclass of Exception.
## 1.6.1 / 2010-11-05
This release has test passing for Ruby 1.9.2. Ruby 1.9.2 doesn't appear
to like &block and block_given? to be used in same method scope. It
may be a Ruby bug, nonetheless AE has been adjusted to circumvent the
problem.
Changes:
* Use `&block` and not `block_given?`.
## 1.6.0 / 2010-11-04
Support libraries defining toplevel methods, such as `legacy.rb`, now place
their methods in AE::World module instead of Object. AE::World needs to
to be included in the context desired for the testing framework used. This
is important to prevent pollution of the Object namespace.
Changes:
* Toplevel extras are defined in AE::World instead of Object.
* In dot.rb #true/#false methods renamed to `#true!`/`#false!`.
* In dot.rb `#true!`/`#false!` methods can take an error or error message.
## 1.5.0 / 2010-09-06
This release adds adapters for TestUnit, MiniTest and RSpec. AE worked with
them previously but AE assertions were seen as errors rather than nice
assertions. Likewise assertion counts were off in the final tally. These
adapters insert AE's counts so the tally are correct.
In addition to this the Assertion class itself now acts as the final end
point for all assertions, which makes for a very clean interface.
Changes:
* Add adapters for TestUnit, MiniTest and RSpec.
* Move final assertion call to Assertion#test.
## 1.4.0 / 2010-09-02
Version 1.4 brings Ruby 1.9 compatibility. The Assertor class is now a
subclass of BasicObject. This fixes an issues Assertor would had
applying to methods defined both in a class and Kernel.
Changes:
* Assertor is a subclass of BasicObject.
* Use custom BasicObject when using Ruby 1.8.
* Add #assert= which works like `assert ==`.
* Add #refute= which works like `refute ==`.
## 1.3.0 / 2010-06-17
New release of AE adds support for RSpec-style matchers. This means
it should be usable with Shoulda 3.0 and any other matchers library.
This release also cleans up the underlying code, which is now
extremely clean. Lastly a small API change allows #assert to compare
it's argument to the return of it's block using #==, just as #expect
does using #===.
Changes:
* Add RSpec-style matchers support.
* Move #expect code to Assertor.
* #assert method can do equality comparison.
## 1.2.3 / 2010-06-07
This release is a quick fix, which adds a missing `require 'yaml'`.
Changes:
* Add missing require 'yaml'.
## 1.2.2 / 2010-06-06
Version 1.2.2 simply add one new feature --the ability to
use 'object.assert = other' instead of 'object.assert == other'.
This was added simply because I found I often made the mistake
of a missing '=', and since #assert= has no definition, there
was no reason not to have behave accordingly.
Also note that I switched the license from LGPL to MIT.
With regards to reusable libraries and I moving all my
work, such that I am able, to MIT to maximize free usage.
Changes:
* Add `#assert=` method as a shortcut for `#assert ==`.
* Now distributed under MIT license.
## 1.2.0 / 2010-01-27
This release fixes '=~' assertions and now requires the
ae/expect library by default.
Changes:
* Expect method is now loaded by default when requiring 'ae'.
* Fixed bug where #=~ did not work correctly against Assertor.
## 1.1.0 / 2009-09-06
This release provided two major improvements. The first is
the #expect method which is similar to #assert, but uses
case equality (#===) for comparison. And second, an optional
library `ae/legacy.rb`, is has been added that provides
backward compatibility with Test::Unit assertions, should it
be needed.
Changes:
* New #expect method.
* Proved legacy assertion in optional ae/legacy.rb library.
* Added backtrace parameter to flunk calls.
## 1.0.0 / 2009-09-03
This is the initial release of AE.
Changes:
* Happy Birthday!
ae-1.8.2/DEMO.rdoc 0000644 0000000 0000000 00000041114 12406706117 012207 0 ustar root root = Introduction
AE is an assertions framework for Ruby. It's designed
around the concept of an Assertor. The Assertor is an
Assertion Functor, or Higher-Order Function, which
reroutes method calls while monitoring them for failing
conditions.
== What AE Provides
Requiring the AE library.
require 'ae'
Loads two classes, +Assertion+ and +Assertor+, the Kernel
method +assert+ and it's antonyms +assert!+ and +refute+
and a set of core extensions that make writing certain types
of assertions easier.
== Assertion and Assertor Classes
The +Assertion+ class is at the heart of AE. All other AE
methods depend on it. The +Assertion+ class is a subclass
of Exception. When an assertion is made and fails, it is
an instance of Assertion that is raised.
expect Assertion do
msg = "my failure message"
assert false, msg
end
Like any raised exception, the last Assertion message is available
via $!.
(FYI, in Test::Unit the equivalent class was called +AssertionFailedError+.)
Assertions themselves are not generally used in creating tests or
behavior specifications. Rather they are used to create additional
types of assertion methods.
As mentioned above the +Assertor+ class is a type of Higher-Order
function, or Functor, which intercedes with a normal message
invocation to monitor for failed conditions, upon which is raises
Assertion exceptions.
== Assertion Methods
The three methods, +assert+, assert! and +refute+ all
return an Assertor instance when used fluidly, i.e. magic-dot
notation, higher-order notation, functor notation, whatever you
prefer to call it.
assert(AE::Assertor === assert)
Through the use of +method_missing+, the Assertor allows us to write
statements like:
1.assert == 1
If the operation evaluates to false or nil, then an Assertion error
is raised.
expect Assertion do
1.assert == 2
end
The methods assert! and +refute+ are just like +assert+
expect they purport the negative condition. Patterned after Ruby's
own use of "!" as meaning +not+, assert! should be
read "assert not". While +refute+ exists for the sake of those who
find the use of a bang method for this purpose unsuited to them.
== How It Works
An Assertor essentially sits in wait for a method call (via
method_missing). When that happens it applies the method to the
original receiver, but wrapped in a clause that raises an
Assertion should the statement fail. If we wanted to be
pedantic, we could write our assertions like:
raise Assertion.new("1 != 1") unless 1 == 1
Instead of
1.assert == 1
Obviously using Assertor methods are whole lot more concise.
= Assertion Class
The Assertion class is a subclass of Exception and is the error raised when
and assertion fails.
= Assert Method
== Compatible with Test::Unit
The +assert+ method is designed to be backward compatible
with the same method in Test::Unit.
Using an argument, +assert+ will check that an argument evaluates
to true. Optionally one can send along a meaningful message should
the assertion fail.
assert(true, "Not true!")
expect Assertion do
assert(false, "Not true!")
end
== Assert with a Block
In addition +assert+ has been extended to accept a block. Like the case of the
argument, the block is expected to return something that evaluates as true.
assert do
true
end
Assertion.assert.raised? do
assert do
false
end
end
We should also mention that, while probably not very useful, since
the arity of a block can be checked, one can also pass the receiver
into the block as a block argument.
"hi".assert do |s|
/h/ =~ s
end
== Antonyms for Assert
We can state the opposite assertion using assert!.
10.assert! == 9
Or, because some people do not like the use of a bang method, +refute+.
10.refute == 9
These terms can be used just as +assert+ is used in all examples,
but with the opposite inference.
Another way to get the opposite inference, is to use +not+.
10.assert.not == 9
== Lambda Assertions
Passing +assert+ a `Proc` object, or any object that responds to `#call`,
will be used as if it were a block. This allows for a simple way to quickly
create reusable assertions.
palindrome = lambda{ |word| word == word.reverse }
"abracarba".assert palindrome
The message for a failed assertion will come from calling `#to_s` on the
object.
== RSpec-style Assertion Matchers
If an object passed to assert responds to `#matches?` then AE will handle
the object as an RSpec-style mather, the receiver will be passed to the
`#matches?` method to determine if the assertion passes and RSpec matcher
message methods will be used if they are defined.
palindrome = Object.new
def palindrome.matches?(word)
word == word.reverse
end
"abracarba".assert palindrome
== Identity Assertions
Rather then the general form.
x = 10
x.assert.object_id == x.object_id
We can use Ruby's own equal? method.
x.assert.equal?(x)
AE provides identical? method as an alternative
to make it a bit more clear.
x.assert.identical?(x)
== Equality Assertions
The most common assertion is that of value equality (==),
as we have seen throughout this document. But other forms of
equality can be verified as easily. We have already mentioned
identity. In addition there is type equality.
17.assert.eql? 17
Assertion.assert.raised? do
17.assert.eql? 17.0
end
And there is case equality.
Numeric.assert === 3
== Checking Equality with a Block
Because operators can not take blocks, and at times blocks can
be convenient means of supplying a value to an assertion,
AE has defined alternate renditions of the equality methods.
For equal? and eql?, the method names are the same, they simply
can take a block in place of an argument if need be.
For value equality (==), the method is called eq?.
10.assert.eq? do
10.0
end
And should it fail...
Assertion.assert.raised? do
10.assert.eq? do
20
end
end
== Case Equality
For case equality (===), it is case?.
Numeric.assert.case? do
"3".to_i
end
Assertion.assert.raised? do
Numeric.assert.case? do
"3"
end
end
== Regular Expressions
Regular Expressions can be used to make assertions in much the same way as equality.
/i/.assert =~ "i"
Assertion.assert.raised? do
/i/.assert =~ "g"
end
Conversely the String class recognizes the #=~ method as well.
"i".assert =~ /i/
Assertion.assert.raised? do
"i".assert =~ /g/
end
== Exception Assertions
Validating errors is easy too, as has already been shown
in the document to verify assertion failures.
StandardError.assert.raised? do
unknown_method
end
== Assertions on Object State
While testing or specifying the internal state of an object is
generally considered poor form, there are times when it is
necessary. Assert combined with +instance_eval+ makes it easy too.
class X
attr :a
def initialize(a); @a = a; end
end
x = X.new(1)
x.assert.instance_eval do
@a == 1
end
== Catch/Try Assertions
Catch/Try throws can be tested via Symbol#thrown?.
:hookme.assert.thrown? do
throw :hookme
end
Alternatively, a lambda containing the potential throw
can be the receiver using throws?.
hook = lambda{ throw :hookme }
hook.assert.throws?(:hookme)
== Assertions on Proc Changes
I have to admit I'm not sure how this is useful,
but I found it in the Bacon API and ported it over
just for sake of thoroughness.
a = 0
l = lambda{ a }
l.assert.change?{ a +=1 }
== Assertion on literal True, False and Nil
Ruby already provides the #nil? method.
nil.assert.nil?
AE adds true? and false? which acts accordingly.
true.assert.true?
false.assert.false?
== Send Assertions
Assert that a method can be successfully called.
"STRING".assert.send?(:upcase)
== Numeric Delta and Epsilon
You may wish to assert that a numeric value is with some
range.
3.in_delta?(1,5)
Or minimum range.
3.in_epsilon?(3,5)
== Verifying Object State
Not surprisingly if underlying object state needs to be verified, +instance_eval+
can be used in conjunction with +assert+.
class X
attr :a
def initialize(a); @a = a; end
end
x = X.new(4)
x.instance_eval do
@a.assert == 4
end
However #instance_eval is a reserved method for the underlying Assertor class,
so it cannot be used on #assert, e.g.
x.assert.instance_eval do
@a == "obvisouly wrong"
end
AE offers an optional helper method for times when testing underlying private
or protected methods is important, called #pry. See the QED on pry for more
information.
For some testing underlying implementation might be considered poor
form. You will get no argument here. It should be used thoughtfully,
but I would not bet against there being occasions when such validations
might be needed.
= Subjunctives
Okay. I can hear the BDDers rumbling, "where's the *should?*"
AE has nothing against "should", but there are different
approaches for utilizing should nomenclature in specifications,
and AE wants to be open to these techniques. One of which
is how Shoulda (http://shoulda.rubyforge.org) utilizes
+should+ in a way analogous to RSpec's use of +it+.
Even so, AE provides an optional mixin called +Subjunctive+ which
can be used to create assertor methods with English subjunctive
terms, such as +should+, or +must+, +shall+ and +will+.
To load this library use:
require 'ae/subjunctive'
Then all that is required it to define a subjunctive method for all
objects. For example:
def will(*args, &block)
Assertor.new(self, :backtrace=>caller).be(*args,&block)
end
It's that easy. Because of their commonality AE provides two such terms,
+should+ and +must+ as optional add-ons out-of-the-box.
require 'ae/should'
require 'ae/must'
We will use these two methods interchangeable for the rest of this
demonstration, but to be clear they both work exactly the same way,
and almost exactly like +assert+.
Keep in mind, AE "conical" functionality does not entail the subjunctive
forms. These are simply options you can load via your test_helper.rb,
or similar script, if you prefer these nomenclatures.
== Fluent Notation and Antonyms
Like +assert+, +should+ and +must+ can be used as higher order functions.
4.should == 4
4.must == 4
Antonyms provided for +should+ as should! (read "should not") and +shouldnt+.
For +must+ +must+, they are must! and +wont+.
4.should! == 5
4.shouldnt == 5
4.must! == 5
4.wont == 5
== To Be
On occasions where the English readability of a specification is hindered,
+be+ can be used.
StandardError.must.be.raised? do
unknown_method
end
The +be+ method is the same as +assert+ with the single exception
that it will compare a lone argument to the receiver using +equate?+,
unlike +assert+ which simply checks to see that the argument evaluates
as true.
10.should.be 10
10.should.be 10.0
10.should.be Numeric
Assertion.assert.raised? do
10.should.be "40"
end
== Indefinite Articles
Additional English forms are +a+ and +an+, equivalent to +be+ except
that they use case? (same as #===) instead of
equate? when acting on a single argument.
"hi".must.be.a String
Assertion.assert.raised? do
/x/.must.be.a /x/
end
Otherwise they are interchangeable.
"hi".must.be.an.instance_of?(String)
The indefinite articles work well when a noun follows as an arguments.
palindrome = lambda{ |x| x == x.reverse }
"abracarba".must.be.a palindrome
= Expect Method
Expect is another assertion nomenclature available for use in your
tests or specifications. Inspired by Jay Fields' Expectations library,
it provides convenient syntax for creating exception and case equality
assertions.
require 'ae/expect'
== Underlying Comparison
Expect uses #=== for comparison. So providing an argument and a block to
#expect we can test for a somewhat broader range of compassion than #assert.
For example we can test for a subclass.
expect Numeric do
3
end
Assertion.assert.raised? do
expect Numeric do
"3"
end
end
== Exception Expectation
If the comparator is an Exception class or a instance of an Exception class,
then #expect will check to see if the block raises that kind of exception.
expect StandardError do
some_undefined_method
end
expect Assertion do
expect(nil)
end
This is an important distinction to note because it means #expect can not be used
if verify instances of Exception classes.
Assertion.assert.raised? do
expect Exception do
Exception.new
end
end
== Regex Expectations
That #expect entails #=== also means we can check for Regexp matches.
expect /x/ do
"oooxooo"
end
== Expected Method
We can use #expected to make the receiver the object of expectation.
x = "dummy"
/x/.expected do
"x"
end
== Without Block
Without a block, the receiver is compared to the argument.
x.expect String
== Negative Forms
Like #assert, #expect has a negated form called #expect!
expect! /x/ do
"o"
end
The pure word form for those who do not like the clever use of the
explimation mark is #forbid.
forbid /x/ do
"o"
end
== Functor, or Higher Order Function
Like #assert, #expect can be used used as a *fluid* notation.
10.expect == 10
In which case it works just like #assert, including negative forms.
10.expect! == 11
10.forbid == 11
= Assertion Counts
AE tracks the number of assertions made and the number that failed to pass.
We can reset the count using the +recount+ class method.
old_counts = AE::Assertor.recount
For example if we have one assertion pass and another fail.
assert(true)
expect Assertion do
assert(false)
end
We will see that AE counted three assertions and one failure.
counts = AE::Assertor.counts.dup
counts[:total].assert == 3
counts[:pass].assert == 2
counts[:fail].assert == 1
The #expect call is an assertion too, which is why the total count is 3
rather than 2.
Now that we are done checking counts we will restore them so that
any other demos being run with this will tally correctly.
AE::Assertor.recount(old_counts)
AE::Assertor.counts[:total] += 3
AE::Assertor.counts[:pass] += 3
= Matchers
Matchers are simply Procs or objects with the proper interface that can be
passed to #assert or #refute (or other Assertor) as an ecapsulated test.
== Proc or #to_proc
Passing a Proc object or an object that responds to :to_proc, will use it
as if it were a block of the method. This allows for a simple way to quickly
create reusable assertions.
palindrome = lambda{ |word| word == word.reverse }
"abracarba".assert palindrome
== #matches?
Additionally if an object responds to #matches? then the receiver
will be passed to this method to determine if the assertion passes.
palindrome = Object.new
def palindrome.matches?(word)
word == word.reverse
end
"abracarba".assert palindrome
== RSpec, Shoulda and other 3rd-Party Matchers
With tha addition of #matches?, AE supports the same interface for matchers
as RSpec. Any matcher library designed for use with RSpec should therefore
be usable with AE as well. This includes RSpecs own matchers and Shoulda's
excellent Rails matchers.
== Check Ok/No
The Check library is an optional library that can be used
to conveniently speed-up construction of reptitive assertions.
To use it, first require the library, then include the mixin
into the namespace in which you will utilize it.
require 'ae/check'
include AE::Check
Now we can define ok/no check procedures. A one-off procedure is
defined with a block only.
check do |x, y|
x == y
end
ok 1,1
no 1,2
To define reusable check procedures, give the procedure a name.
check :palindrome do |x|
x.reverse == x
end
This will also cause the current check method to be set.
Later in the code, the check procedure can be reset to this
by just passing the name.
check :palindrome
ok 'abracarba'
no 'foolishness'
The Check mixin comes preloaded with a few standard checks.
By default the `:equality` procedure is used.
check :equality
ok 1=>1.0
Notice the use of the hash argument here. This is a useful construct for
many check procedures becuase it it akin to the `#=>` pattern we often
see in code examples and it also allows for multiple assertions in one call.
For instance, in the case of `:equality`, multiple entries convey a
meaning of logical-or.
ok 1=>2, 1=>1
This would pass becuase the second assertion of equality is true.
Another built in check is `:case_equality` which uses `#===` instead of `#==`
to make the comparison.
check :case_equality
ok 1=>Integer
ae-1.8.2/.yardopts 0000644 0000000 0000000 00000000070 12406706117 012454 0 ustar root root --title "AE API"
--protected
--private
lib/
-
[A-Z]*.*
ae-1.8.2/.ruby 0000664 0000000 0000000 00000000000 12406706117 011563 0 ustar root root ae-1.8.2/README.md 0000644 0000000 0000000 00000011435 12406706117 012074 0 ustar root root # Assertive Expressive
[Homepage](http://rubyworks.github.com/ae) /
[Source Code](http://github.com/rubyworks/ae) /
[Documentation](http://rubydoc.info/gems/ae) /
[User Manual](http://wiki.github.com/rubyworks/ae) /
[Report Issue](http://github.com/rubyworks/ae/issues) /
[Mailing List](http://googlegroups.com/group/rubyworks-mailinglist) /
[IRC Channel](irc://irc.freenode.net/rubyworks)
[](http://travis-ci.org/rubyworks/ae)
[](http://badge.fury.io/rb/ae)
## About
Assertive Expressive (AE) is an assertions framework
intended for reuse by any TDD, BDD or similar system.
## Features
* Clear, simple and concise syntax.
* Uses higher-order functions and fluid notation.
* Reusable core extensions ease assertion construction.
* Core extensions are standardized around Ruby Facets.
* But Facets is not a dependency; the extensions are built-in.
* Easily extensible allowing for alternate notations.
* Eats it's own dog food.
## Synopsis
AE defines the method `assert`. It's is compatible with the method
as defined by Test::Unit and MiniTest, which verifies truth of a
single argument (and can accept an optional failure message).
assert(true)
In addition AE's `assert` method has been extended to accept a block,
the result of which is likewise verified.
assert{true}
But the real power the AE's +assert+ method lies in it's use
without argument or block. In that case it returns an instance of
`Assertor`. An `Assertor` is an *Assertions Functor*, or
*Higher-Order Function*. It is a function that operates on
another function. With it, we can make assertions like so:
x.assert == y
a.assert.include? e
StandardError.assert.raised? do
...
end
And so forth. Any method can be used in conjunction with +assert+
to make an assertion. Eg.
class String
def daffy?
/daffy/i =~ self
end
end
"Daffy Duck".assert.daffy?
When an assertion fails an Assertion exception is raised. Any test
framework can catch this exception and process it accordingly.
Technically the framework should check to see that the exception
object responds affirmatively to the #assertion? method. This way any
type of exception can be used as a means of assertion, not just AE's
Assertion class.
Please have a look at the QED and API documentation to learn more.
## Integration
Generally speaking, AE can be used with any test framework simply by putting
`require 'ae'` in a test helper script. However to fully
integrate with a test framework and ensure the test framework recognizes
AE assertions (as more than just exceptions) and to ensure assertion
counts are correct, a little extra interfacing code may be necessary.
Lucky for you AE has already done the leg work for the most common
test frameworks:
require 'ae/adapters/testunit'
require 'ae/adapters/minitest'
require 'ae/adapters/rspec'
(Note that Cucumber does not need an adapter.)
AE also includes a script that will automatically detect the current
test framework by checking for the existence of their respective
namespace modules.
require 'ae/adapter'
## Nomenclature
With AE, defining assertions centers around the #assert method. So
*assert* can be thought of as AE's primary _nomenclature_. However, variant
nomenclatures have been popularized by other test frameworks, in particular
*should* and *must*. If you prefer one of them terms, AE provides optional
libraries that can loaded for utilizing them.
require 'ae/should'
require 'ae/must'
By loading one of these scripts (or both) into your test system (e.g. via a test
helper script) you gain access to subjunctive terminology. See the API documentation
for the Subjunctive module for details.
## Legacy
To ease transition from TestUnit style assertion methods, AE provides
a TestUnit legacy module.
require 'ae/legacy'
This provides a module `AE::Legacy::Assertions` which is included in AE::World
and can be mixed into your test environment to provide old-school assertion
methods, e.g.
assert_equal(foo, bar, "it failed")
## Installation
### Gem Installs
Install AE in the usual fashion:
$ gem install ae
### Site Installs
Local installation requires Setup.rb.
$ gem install setup
Then download the tarball package from GitHub
and do:
$ tar -xvzf ae-1.0.0.tgz
$ cd ae-1.0.0.tgz
$ sudo setup.rb all
Windows users use 'ruby setup.rb all'.
## Copyrights & License
Copyright (c) 2008 Rubyworks. All rights reserved.
Unless otherwise provided for by the originating author, this
program is distributed under the terms of the *BSD-2-Clause* license.
Portions of this program may be copyrighted by others.
See the NOTICE.rdoc file for details.
AE is a [Rubyworks](http://rubyworks.github.com) project.
ae-1.8.2/lib/ 0000755 0000000 0000000 00000000000 12406706117 011357 5 ustar root root ae-1.8.2/lib/ae.rb 0000644 0000000 0000000 00000001246 12406706117 012274 0 ustar root root module AE
# TODO: Should we really be reseting a constant for ::Assertion?
# How about using a variable instead?
# Set Assertion class. This is a convenience method
# for framework adapters, used to set the exception class
# that a framework uses to raise an assertion error.
#
# @param [Class] exception_class
# The Exception subclass used to raise assertions.
#
def self.assertion_error=(exception_class)
verbose, $VERBOSE = $VERBOSE, nil
Object.const_set(:Assertion, exception_class)
$VERBOSE = verbose
end
end
require 'ae/version'
require 'ae/assert'
require 'ae/expect'
class ::Object
include AE::Assert
include AE::Expect
end
ae-1.8.2/lib/ae.yml 0000644 0000000 0000000 00000002244 12406706117 012471 0 ustar root root ---
revision: 2013
type: ruby
sources:
- var
authors:
- name: Trans
email: transfire@gmail.com
organizations: []
requirements:
- name: ansi
- groups:
- build
development: true
name: detroit
- groups:
- test
development: true
name: qed
conflicts: []
alternatives: []
resources:
- type: home
uri: http://rubyworks.github.com/ae
label: Homepage
- type: code
uri: http://github.com/rubyworks/ae
label: Source Code
- type: docs
uri: http://rubydoc.info/gems/ae
label: Documentation
- type: wiki
uri: http://wiki.github.com/rubyworks/ae
label: User Guide
- type: bugs
uri: http://github.com/rubyworks/ae/issues
label: Issue Tracker
- type: mail
uri: http://groups.google.com/group/rubyworks-mailinglist
label: Mailing List
repositories:
- name: upstream
scm: git
uri: git://github.com/rubyworks/ae.git
categories: []
copyrights:
- holder: Rubyworks
year: '2008'
license: BSD-2-Clause
customs: []
paths:
lib:
- lib
created: '2008-08-17'
summary: Assertive Expressive
title: AE
version: 1.8.2
name: ae
description: ! "Assertive Expressive is an assertions library specifically designed
\nfor reuse by other test frameworks."
date: '2013-02-18'
ae-1.8.2/lib/ae/ 0000755 0000000 0000000 00000000000 12406706117 011744 5 ustar root root ae-1.8.2/lib/ae/must.rb 0000644 0000000 0000000 00000003026 12406706117 013262 0 ustar root root module AE
require 'ae/subjunctive'
# Must
#
# "It is not enough to succeed. Others must fail."
# --Gore Vidal (1925 - )
#
# @note THIS IS AN OPTIONAL LIBRARY.
module Must
# The #must method is functionaly the same as #should.
#
# @example
# 4.must == 3 #=> Assertion Error
#
# @example
# 4.must do
# self == 4
# end
#
# @return [Assertor] Assertion functor.
def must(*args, &block)
Assertor.new(self, :backtrace=>caller).be(*args, &block)
end
# Same as 'object.must == other'.
#
# @return [Assertor] Assertion functor.
def must=(cmp)
Assertor.new(self, :backtrace=>caller) == cmp
end
# Designate a negated expectation via a *functor*.
# Read this as "must not".
#
# @example
# 4.must! == 4 #=> Assertion Error
#
# @return [Assertor] Assertion functor.
def must!(*args, &block)
Assertor.new(self, :backtrace=>caller).not.be(*args, &block)
end
# TODO: Are these negation methods needed now, since Ruby 1.9 allows for
# redefining `!` as a method?
# Perhaps not literally the counter-term to *must* (rather *will*),
# but close enough for our purposes, and conveys the appropriate
# semantics.
alias_method :wont, :must!
# Alias for #must! method.
alias_method :must_not, :must!
# Alias for #must! method.
alias_method :mustnt, :must!
end
end
class ::Object #:nodoc:
include AE::Must
end
# Copyright (c) 2008 Thomas Sawyer
ae-1.8.2/lib/ae/check.rb 0000644 0000000 0000000 00000006116 12406706117 013352 0 ustar root root module AE
# The Ok mixin is a reusable assertion helper that
# makes it easy to construct parameterized assertions
# with an elegant syntax.
#
module Check
# The Check::Proc class encapsulates a labeled procedure
# for making assertions using the `ok`/`no` methods.
#
class Proc
# Setup new check procedure.
def initialize(options={}, &check)
@name = options[:name]
@message = options[:message] || @name
@check = check
end
#
def message(&block)
if block
@message = message
end
@message
end
#
def message=(msg)
@message = msg
end
# Call check procedure.
def call(*args)
@check.call(*args)
end
#
def to_s(*args)
case @message
when nil
@name.to_s
when ::Proc
@message.call(*args)
else
# TODO: count %\S and apply `% args.map{|a|a.inspect}[0,count]`
@message.to_s
end
end
#
def ok!(*args)
assert(call(*args), to_s(*args))
end
#
def no!(*args)
refute(call(*args), to_s(*args))
end
end
# TODO: Better way to customize error message so it can have
# arguments in the messages ?
# Built-in check procedures.
TABLE = {
:equality => Check::Proc.new(:message=>"should be equal"){|h| h.any?{|a,b| b==a}},
:case_equality => Check::Proc.new(:message=>"should be equal"){|h| h.any?{|a,b| b===a}}
}
#
def self.table
@table ||= TABLE.dup
end
# Define a univerally available ok/no check.
#
# AE::Check.define(:palindrome) do |x|
# x.reverse == x
# end
#
def self.define(name, &block)
table[name] = Check::Proc.new(name, &block)
end
#
def check_table
Check.table
end
# Define an ok/no check procedure. A one-off procedure is defined
# with a block.
#
# check do |x, y|
# x == y
# end
#
# ok 1,1
# no 1,2
#
# The check method can also be used to define reusable checks.
#
# check(:palindrome) do |x|
# x.reverse == x
# end
#
# This will also cause the current check to be set.
# Later in the code, the check procedure can be restored
# by just passing the symbolic name.
#
# check :palindrome
#
# ok 'abracarba'
# no 'foolishness'
#
def check(name=nil, &block)
if name
if block
check_table[name] = Check::Proc.new(:name=>name, &block)
end
@__check__ = check_table[name]
else
#raise ArgumentError if block.arity == 0
@__check__ = Check::Proc.new(&block)
end
end
#
def ok(*args)
__check__.ok!(*args)
end
#
def no(*args)
__check__.no!(*args)
end
# Returns the current check.
def __check__
@__check__ || check_table[:equality]
end
end
end
module AE::World
# It's upto the test framework to include where needed.
include AE::Check
end
ae-1.8.2/lib/ae/adapter.rb 0000644 0000000 0000000 00000000262 12406706117 013711 0 ustar root root if defined?(::MiniTest)
require 'ae/adapters/minitest'
elsif defined?(::Test::Unit)
require 'ae/adapters/testunit'
elsif defined?(::RSpec)
require 'ae/adapters/rspec'
end
ae-1.8.2/lib/ae/version.rb 0000644 0000000 0000000 00000000577 12406706117 013767 0 ustar root root module AE
# Access project metadata.
#
# @return [Hash]
def self.metadata
@metadata ||= (
require 'yaml'
YAML.load(File.new(File.dirname(__FILE__) + '/../ae.yml'))
)
end
#
def self.const_missing(name)
key = name.to_s.downcase
metadata[key] || super(name)
end
# Becuase Ruby 1.8~ gets in the way :(
VERSION = metadata['version']
end
ae-1.8.2/lib/ae/legacy.rb 0000644 0000000 0000000 00000024124 12406706117 013540 0 ustar root root module AE
module Legacy #:nodoc:
# Test::Unit Legacy Assertions
#
# This module provides a compatibility layer for Test::Unit.
# This is an optional module and is intended for providing
# an easier transition from Test::Unit to AE assertions.
#
# Note that two methods are not provided, +#assert_nothing_raised+,
# and +#assert_nothing_thrown+.
#
module Assertions
# Private method upon which all of the legacy assertions are based
# (except for #assert itself).
#
# @raise [Assertion] If test fails.
#
# @return nothing
def __assert__(test, msg=nil)
msg = "failed assertion (no message given)" unless msg
raise Assertion.new(msg, :backtrace=>caller[1..-1]) unless test
end
private :__assert__
# The assertion upon which all other assertions are based.
#
# @example
# assert [1, 2].include?(5)
#
# @return [Assertor] if `test` not given
def assert(test=nil, msg=nil)
if test
msg = "failed assertion (no message given)" unless msg
raise Assertion.new(msg, :backtrace=>caller) unless test
else
Assertor.new(self, :backtrace=>caller) # TODO: Probably remove this!
end
end
# Passes if the block yields true.
#
# @example
# assert_block "Couldn't do the thing" do
# do_the_thing
# end
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_block(msg=nil) # :yields:
test = ! yield
msg = "assertion failed" unless msg
__assert__(test, msg)
end
# Passes if expected == +actual.
#
# Note that the ordering of arguments is important,
# since a helpful error message is generated when this
# one fails that tells you the values of expected and actual.
#
# @example
# assert_equal 'MY STRING', 'my string'.upcase
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_equal(exp, act, msg=nil)
test = (exp == act)
msg = "Expected #{act.inspect} to be equal to #{exp.inspect}" unless msg
__assert__(test, msg)
end
# Passes if expected_float and actual_float are equal within delta tolerance.
#
# @example
# assert_in_delta 0.05, (50000.0 / 10**6), 0.00001
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_in_delta(exp, act, delta, msg=nil)
test = (exp.to_f - act.to_f).abs <= delta.to_f
msg = "Expected #{exp} to be within #{delta} of #{act}" unless msg
__assert__(test, msg)
end
# Passes if object .instance_of? klass
#
# @example
# assert_instance_of String, 'foo'
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_instance_of(cls, obj, msg=nil)
test = (cls === obj)
msg = "Expected #{obj} to be a #{cls}" unless msg
__assert__(test, msg)
end
# Passes if object .kind_of? klass
#
# @example
# assert_kind_of Object, 'foo'
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_kind_of(cls, obj, msg=nil)
test = obj.kind_of?(cls)
msg = "Expected #{obj.inspect} to be a kind of #{cls}" unless msg
__assert__(test, msg)
end
# Passes if string =~ pattern.
#
# @example
# assert_match(/\d+/, 'five, 6, seven')
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_match(exp, act, msg=nil)
test = (act =~ exp)
msg = "Expected #{act.inspect} to match #{exp.inspect}" unless msg
__assert__(test, msg)
end
# Passes if object is nil.
#
# @example
# assert_nil [1, 2].uniq!
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_nil(obj, msg=nil)
test = obj.nil?
msg = "Expected #{obj.inspect} to be nil" unless msg
__assert__(test, msg)
end
# Passes if regexp !~ string
#
# @example
# assert_no_match(/two/, 'one 2 three')
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_no_match(exp, act, msg=nil)
test = (act !~ exp)
msg = "Expected #{act.inspect} to match #{exp.inspect}" unless msg
__assert__(test, msg)
end
# Passes if expected != actual
#
# @example
# assert_not_equal 'some string', 5
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_not_equal(exp, act, msg=nil)
test = (exp != act)
msg = "Expected #{act.inspect} to not be equal to #{exp.inspect}" unless msg
__assert__(test, msg)
end
# Passes if ! object .nil?
#
# @example
# assert_not_nil '1 two 3'.sub!(/two/, '2')
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_not_nil(obj, msg=nil)
test = ! obj.nil?
msg = "Expected #{obj.inspect} to not be nil" unless msg
__assert__(test, msg)
end
# Passes if ! actual .equal? expected
#
# @example
# assert_not_same Object.new, Object.new
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_not_same(exp, act, msg=nil)
test = ! exp.equal?(act)
msg = "Expected #{act.inspect} to not be the same as #{exp.inspect}" unless msg
__assert__(test, msg)
end
# Compares the +object1+ with +object2+ using operator.
#
# Passes if object1.send(operator, object2) is true.
#
# @example
# assert_operator 5, :>=, 4
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_operator(o1, op, o2, msg="")
test = o1.__send__(op, o2)
msg = "Expected #{o1}.#{op}(#{o2}) to be true" unless msg
__assert__(test, msg)
end
# Passes if the block raises one of the given exceptions.
#
# @example
# assert_raise RuntimeError, LoadError do
# raise 'Boom!!!'
# end
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_raises(*args)
msg = (Module === args.last ? nil : args.pop)
begin
yield
msg = "Expected #{exp} to be raised" unless msg
__assert__(false, msg)
rescue Exception => e
test = (exp === e)
msg = "Expected #{exp} to be raised, but got #{e.class}" unless msg
__assert__(test, msg)
return e
end
end
alias_method :assert_raise, :assert_raises
# Provides a way to assert that a procedure
# does not raise an exception.
#
# @example
# refute_raises(StandardError){ raise }
#
#def assert_raises!(exception, &block)
# begin
# block.call(*a)
# rescue exception
# raise Assertion
# end
#end
#alias_method :refute_raises, :assert_raises!
# Passes if +object+ respond_to? +method+.
#
# @example
# assert_respond_to 'bugbear', :slice
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_respond_to(obj, meth, msg=nil)
msg = "Expected #{obj} (#{obj.class}) to respond to ##{meth}" unless msg
#flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
#obj, meth = meth, obj if flip
test = obj.respond_to?(meth)
__assert__(test, msg)
end
# Passes if +actual+ .equal? +expected+ (i.e. they are the same instance).
#
# @example
# o = Object.new
# assert_same(o, o)
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_same(exp, act, msg=nil)
msg = "Expected #{act.inspect} to be the same as #{exp.inspect}" unless msg
test = exp.equal?(act)
__assert__(test, msg)
end
# Passes if the method send returns a true value.
# The parameter +send_array+ is composed of:
#
# * A receiver
# * A method
# * Arguments to the method
#
# @example
# assert_send [[1, 2], :include?, 4]
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_send(send_array, msg=nil)
r, m, *args = *send_array
test = r.__send__(m, *args)
msg = "Expected #{r}.#{m}(*#{args.inspect}) to return true" unless msg
__assert__(test, msg)
end
# Passes if the block throws expected_symbol
#
# @example
# assert_throws :done do
# throw :done
# end
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_throws(sym, msg=nil)
msg = "Expected #{sym} to have been thrown" unless msg
test = true
catch(sym) do
begin
yield
rescue ArgumentError => e # 1.9 exception
default += ", not #{e.message.split(/ /).last}"
rescue NameError => e # 1.8 exception
default += ", not #{e.name.inspect}"
end
test = false
end
__assert__(test, msg)
end
# Assert that an Array, or any other object the responds to #include?
# thus contains the given element.
#
# @raise [Assertion] if test fails
#
# @return nothing
def assert_includes(elem, array, msg=nil)
test = array.include?(elem)
msg = "Expected #{elem.inspect} is not found in #{array.inspect}" unless msg
__assert__(test, msg)
end
# Flunk always fails.
#
# @example
# flunk 'Not done testing yet.'
#
# @raise [Assertion] always
#
# @return nothing
def flunk(msg=nil)
__assert__(false, msg)
end
end #module Assertions
end #module Legacy
module World
include AE::Legacy::Assertions
end
end
ae-1.8.2/lib/ae/core_ext/ 0000755 0000000 0000000 00000000000 12406706117 013554 5 ustar root root ae-1.8.2/lib/ae/core_ext/helpers.rb 0000644 0000000 0000000 00000006627 12406706117 015556 0 ustar root root # Nearly all, if not all, of these core extension are available from Ruby Facets.
# hack
NoArgument = Object.new
module Kernel
# Is literally true.
def true?
TrueClass === self
end
# Is literally false.
def false?
FalseClass === self
end
# Are identical, eg. object_id's are equal.
def identical?(exp)
exp.object_id == object_id
end
# Alias for #identical?
alias_method :identical_to?, :identical?
# Word form of #==. Also can take a block.
def eq?(value=NoArgument) #:yield:
if block_given?
self == yield
else
self == value
end
end
# Word form of #===. Also can take a block.
def case?(value=NoArgument) #:yield:
if block_given?
self === yield
else
self === value
end
end
# Word form for #=~. Also can take a block.
def match?(value=NoArgument)
if block_given?
self =~ yield
else
self =~ value
end
end
# Broad equality.
def equate?(x)
equal?(x) || eql?(x) || self == x || self === x
end
# Can a message be sent to the receiver successfully?
def send?(method, *args, &block)
begin
__send__(method, *args, &block)
true
rescue NoMethodError
false
end
end
#
#def returns?(value) #:yield:
# value == yield
#end
unless method_defined?(:public_send)
#
def public_send(m,*a,&b)
raise NoMethodError unless respond_to?(m)
__send__(m,*a,&b)
end
end
end
class Object
# Allows equal? to take a block.
def equal?(value=NoArgument) #:yield:
if block_given?
super(yield)
else
super
end
end
# Allows eql? to take a block.
def eql?(value=NoArgument) #:yield:
if block_given?
super(yield)
else
super
end
end
end
class Numeric
# Is self and given number within delta tolerance.
#
# 0.05.in_delta?(50000.0 / 10**6, 0.00001)
#
def in_delta?(orig, delta=0.001)
#(num.to_f - to_f).abs <= delta.to_f
delta >= (orig - self).abs
end
# Alias for #in_delta.
alias_method :close?, :in_delta?
# Verify epsilon tolerance.
def in_epsilon?(orig, epsilon=0.001)
in_delta?(orig, [orig, self].min * epsilon)
end
end
class Module
# Is a given class or module an ancestor of this
# class or module?
#
# class X ; end
# class Y < X ; end
#
# Y.is?(X) #=> true
#
def is?(base)
Module===base && ancestors.slice(1..-1).include?(base)
end
end
class Proc
#
def raises?(exception=Exception, *args)
begin
call(*args)
false
rescue exception => error
exception === error
end
end
#
def throws?(sym, *args)
catch(sym) do
begin
call(*args)
rescue ArgumentError # 1.9 exception
rescue NameError # 1.8 exception
end
return false
end
return true
end
# TODO: Put in facets?
# TODO: wrong place, change yield?
def change?
pre_result = yield
called = call
post_result = yield
pre_result != post_result
end
end
class Symbol
# Does the block throw this symbol?
#
def thrown?(*args)
catch(self) do
begin
yield(*args)
rescue ArgumentError # 1.9 exception
rescue NameError # 1.8 exception
end
return false
end
return true
end
end
class Exception
#
def self.raised? #:yeild:
begin
yield
false
rescue self
true
end
end
end
# Copyright (c) 2008,2009 Thomas Sawyer
ae-1.8.2/lib/ae/core_ext/exception.rb 0000644 0000000 0000000 00000000553 12406706117 016102 0 ustar root root class Exception
# Is this exception the result of an assertion?
def assertion?
@assertion || false
end
# Set +true+/+false+ if the this exception is
# an assertion.
def set_assertion(boolean)
@assertion = !!boolean
end
#
def negative?
@negative || false
end
#
def set_negative(boolean)
@negative = !!boolean
end
end
ae-1.8.2/lib/ae/ansi.rb 0000644 0000000 0000000 00000000552 12406706117 013225 0 ustar root root require 'ansi/diff'
module AE
# Default ANSI mode is "on".
@ansi = true
# ANSI mode.
#
# @return [Boolean] ANSI mode.
def self.ansi?
@ansi
end
# To turn of ANSI colorized error messages off, set
# ansi to +false+ in your test helper.
#
# @example
# AE.ansi = false
#
def self.ansi=(boolean)
@ansi = boolean
end
end
ae-1.8.2/lib/ae/pry.rb 0000644 0000000 0000000 00000001724 12406706117 013107 0 ustar root root require 'ae/basic_object'
module Kernel
# TODO: Is th cache really neccessry?
#
$PRY_TABLE = {}
# Pry allows you to test private and protected methods
# thru a public-only interface.
#
# Generally one should avoid testing private and protected
# methods directly, instead relying on tests of public methods to
# indirectly test them, because private and protected methods are
# considered implementation details. But sometimes it is necessary
# to test them directly, or if you wish to achieve *absolute
# coverage*, say in a mission critical system.
#
# @return [Pry] pry functor
def pry
$PRY_TABLE[self] ||= Pry.new do |op, *a, &b|
__send__(op, *a, &b)
end
end
# Pry Functor
class Pry < AE::BasicObject
#instance_methods.each{ |m| private m unless m.to_s =~ /^__/ }
def initialize(&function)
@function = function
end
def method_missing(op, *a, &b)
@function.call(op, *a, &b)
end
end
end
ae-1.8.2/lib/ae/should.rb 0000644 0000000 0000000 00000002602 12406706117 013567 0 ustar root root require 'ae/subjunctive'
module AE
# Should
#
# "Always and never are two words you should always
# remember never to use."
# --Wendell Johnson
#
# @note THIS IS AN OPTIONAL LIBRARY.
module Should
# Make an assertion in subjunctive tense.
#
# 4.should == 3 #=> Assertion Error
#
# 4.should do
# self == 4
# end
#
# @return [Assertor] Assertion functor.
def should(*args, &block)
Assertor.new(self, :backtrace=>caller).be(*args, &block)
end
# Same as 'object.should == other'.
#
# @return [Assertor] Assertion functor.
def should=(cmp)
Assertor.new(self, :backtrace=>caller).assert == cmp
end
# Designate a negated expectation via a *functor*.
# Read this as "should not".
#
# 4.should! = 4 #=> Assertion Error
#
# @return [Assertor] Assertion functor.
def should!(*args, &block)
Assertor.new(self, :backtrace=>caller).not.be(*args, &block)
end
# NOTE: It would be nice if their were a single term that
# meant the opposite of should, rather than a two word compound.
# Alias for #should! method.
alias_method :should_not, :should!
# Alias for #should! method.
alias_method :shouldnt, :should!
end
end
class ::Object #:nodoc:
include AE::Should
end
# Copyright (c) 2008 Thomas Sawyer, Rubyworks
ae-1.8.2/lib/ae/core_ext.rb 0000644 0000000 0000000 00000000241 12406706117 014076 0 ustar root root require 'ae/core_ext/exception'
require 'ae/core_ext/helpers'
# We need BasicObject for Assertor.
unless defined?(BasicObject)
require 'ae/basic_object'
end
ae-1.8.2/lib/ae/basic_object.rb 0000644 0000000 0000000 00000006436 12406706117 014711 0 ustar root root if RUBY_VERSION >= '1.9'
module AE
BasicObject = ::BasicObject
end
else
module AE
# BasicObject provides an abstract base class with no predefined
# methods (except for \_\_send__ and \_\_id__).
# BasicObject is useful as a base class when writing classes that
# depend upon method_missing (e.g. dynamic proxies).
#
# BasicObject is based on BlankSlate by Jim Weirich.
#
# Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
# All rights reserved.
class BasicObject #:nodoc:
# Hide the method named +name+ in the BlankSlate class. Don't
# hide +instance_eval+ or any method beginning with "__".
def self.hide(name)
name = name.to_s
if instance_methods.include?(name) and
name !~ /^(__|instance_eval|instance_exec)/
@hidden_methods ||= {}
@hidden_methods[name.to_sym] = instance_method(name)
undef_method name
end
end
def self.find_hidden_method(name)
@hidden_methods ||= {}
@hidden_methods[name.to_sym] || superclass.find_hidden_method(name)
end
# Redefine a previously hidden method so that it may be called on a blank
# slate object.
def self.reveal(name)
hidden_method = find_hidden_method(name)
fail "Don't know how to reveal method '#{name}'" unless hidden_method
define_method(name, hidden_method)
end
#
instance_methods.each { |m| hide(m) }
end
end
# Since Ruby is very dynamic, methods added to the ancestors of
# BlankSlate after BlankSlate is defined will show up in the
# list of available BlankSlate methods. We handle this by defining a
# hook in the Object and Kernel classes that will hide any method
# defined after BlankSlate has been loaded.
#
module Kernel
class << self
alias_method :basic_object_method_added, :method_added
# Detect method additions to Kernel and remove them in the
# BasicObject class.
def method_added(name)
result = basic_object_method_added(name)
return result if self != Kernel
AE::BasicObject.hide(name)
result
end
end
end
# Same as above, except in Object.
#
class Object
class << self
alias_method :basic_object_method_added, :method_added
# Detect method additions to Object and remove them in the
# BlankSlate class.
def method_added(name)
result = basic_object_method_added(name)
return result if self != Object
AE::BasicObject.hide(name)
result
end
def find_hidden_method(name)
nil
end
end
end
# Also, modules included into Object need to be scanned and have their
# instance methods removed from blank slate. In theory, modules
# included into Kernel would have to be removed as well, but a
# "feature" of Ruby prevents late includes into modules from being
# exposed in the first place.
#
class Module #:nodoc:
alias basic_object_original_append_features append_features
def append_features(mod)
result = basic_object_original_append_features(mod)
return result if mod != Object
instance_methods.each do |name|
AE::BasicObject.hide(name)
end
result
end
end
end
ae-1.8.2/lib/ae/assert.rb 0000644 0000000 0000000 00000004440 12406706117 013574 0 ustar root root require 'ae/assertor'
module AE
# The Assert module is simple a conatiner module for the core
# extension methods: #assert, #expect, etc.
#
# This module is included directory into the Object class.
module Assert
# Assert a operational relationship.
#
# 4.assert == 3
#
# If only a single test argument is given then #assert
# simply validates that it evalutate to true. An optional
# message argument can be given in this case which will
# be used instead of the deafult message.
#
# assert(4==3, "not the same thing")
#
# In block form, #assert ensures the block evalutes
# truthfully, i.e. not as nil or false.
#
# assert{ 4==3 }
#
# @return [Assertor] Assertion functor.
def assert(*args, &block)
Assertor.new(self, :backtrace=>caller).assert(*args, &block)
end
# Same as 'object.assert == other'.
#
# @return [Assertor] Assertion functor.
def assert=(cmp)
Assertor.new(self, :backtrace=>caller).assert == cmp
end
# Opposite of assert.
#
# 4.refute == 4 #=> Assertion Error
#
# @return [Assertor] Assertion functor.
def refute(*args, &block)
Assertor.new(self, :backtrace=>caller).not.assert(*args, &block)
end
# Same as 'object.refute == other'.
#
# @return [Assertor] Assertion functor.
def refute=(cmp)
Assertor.new(self, :backtrace=>caller).not.assert == cmp
end
# Alias for #refute. Read it as "assert not".
#
# 4.assert! == 4
#
# NOTE: This method would not be necessary if Ruby would allow
# +!=+ to be define as a method, or at least +!+ as a unary method.
# Looks like this is possible in Ruby 1.9, but we will wait until
# Ruby 1.9 is the norm.
alias_method :assert!, :refute
# Directly raise an Assertion failure.
#
# @param message [String]
# Error message.
#
# @param backtrace [String]
# Backtrace, used to pass up an error from lower in the stack.
#
# @raise [Assertion]
# Assertion error with given `message`.
def flunk(message=nil, backtrace=nil)
#Assertor.new(self, :backtrace=>caller).assert(false, message)
Assertor.assert(false, message, backtrace || caller)
end
end
end
# Copyright (c) 2008 Thomas Sawyer
ae-1.8.2/lib/ae/assertor.rb 0000644 0000000 0000000 00000027505 12406706117 014144 0 ustar root root require 'ae/assertion'
require 'ae/basic_object'
require 'ae/ansi'
module AE
# Assertor is the underlying class of the whole system. It implements
# the flutent assertion notation.
#
# An Assertor is an Assertion Functor. A Functor is a succinct name for what
# is also known as Higher Order Function. In other words, it is a function
# that acts on a function. It is very similiar to a delegator in most
# respects, but is conditioned on the operation applied, rather then simply
# passing-off to an alternate reciever.
#
class Assertor < AE::BasicObject
# Initial settings of assertion counts.
ZERO_COUNTS = {:total=>0,:pass=>0,:fail=>0}
# Initialize assertion counts global variable.
$ASSERTION_COUNTS = ZERO_COUNTS.dup
# Returns Hash used to track assertion counts.
def self.counts
$ASSERTION_COUNTS
end
# Reset assertion counts.
#
# reset - Hash which can be used to set counts manually (optional).
#
# Returns the Hash of previous counts.
def self.recount(reset=nil)
old_counts = counts.dup
if reset
reset.each do |type, value|
counts[type.to_sym] = value
end
else
counts.replace(ZERO_COUNTS.dup)
end
return old_counts
end
# Increment assertion counts. If +pass+ is +true+ then +:total+
# and +:pass+ are increased. If +pass+ if +false+ then +:total+
# and +:fail+ are incremented.
def self.increment_counts(pass)
counts[:total] += 1
if pass
counts[:pass] += 1
else
counts[:fail] += 1
end
return counts
end
# Basic assertion. This method by-passes all the Assertor fluent
# constructs and performs the underlying assertion procedure. It
# is used by Assertor as the end call of an assertion.
def self.assert(pass, error=nil, negated=nil, backtrace=nil)
pass = negated ^ !!pass
increment_counts(pass)
if !pass
backtrace = backtrace || caller
raise_assertion(error, negated, backtrace)
end
return pass
end
# The intent of the method is to raise an assertion failure
# class that the test framework supports.
def self.raise_assertion(error, negated, backtrace=nil)
if not ::Exception === error
error = assertion_error.new(error)
end
error.set_negative(negated)
error.set_backtrace(backtrace || caller)
error.set_assertion(true)
fail error
end
# Returns the Exception class to be raised when an assertion fails.
def self.assertion_error
::Assertion
end
# NOT HAPPENING
## Is ::Assay defined. This is used for integration of the Assay library.
#def self.assay?
# @_assay ||= defined?(::Assay)
#end
#
#def self.message(sym, neg, *args, &blk)
# if method = Message.lookup(sym)
# method = "non_#{method}" if neg
# Message.send(method, *args, &blk)
# else
# nil
# end
#end
#
if ::RUBY_VERSION >= '1.9'
eval "private :==, :!, :!=" # using eval here b/c it's a syntax error in 1.8-
end
# New Assertor.
#
def initialize(delegate, opts={}) #, backtrace)
@delegate = delegate
@message = opts[:message]
@backtrace = opts[:backtrace] || caller #[1..-1]
@negated = !!opts[:negated]
end
# TODO: Should #not return a new Assertor instead of in place negation?
# Negate the meaning of the assertion.
#
def not(msg=nil)
@negated = !@negated
@message = msg if msg
self
end
# Internal assert, provides all functionality associated
# with external #assert method. (See Assert#assert)
#
# NOTE: I'm calling YAGNI on using extra arguments to pass
# to the block. The interface is much nicer if a macro is
# created to handle any neccessry arguments. Eg.
#
# assert something(parameter)
#
# instead of
#
# assert something, parameter
#
# Returns +true+ or +false+ based on assertions success.
#
def assert(*args, &block)
return self if !block && args.empty?
target = args.shift unless block
error = nil
# Block
if block
match = args.shift
result = block.arity > 0 ? block.call(@delegate) : block.call
if match
pass = (match == result)
error = @message || "#{match.inspect} == #{result.inspect}"
else
pass = result
error = @message || block.inspect # "#{result.inspect}"
end
# Proc-style
elsif proc_assertion?(target)
pass, error = proc_apply(target)
# Assay-style assertions
#elsif assay_assertion?(target)
# pass, error = assay_assertion_apply(target)
# RSpec-style matchers
elsif rspec_matcher?(target)
pass, error = rspec_matcher_apply(target)
# Truthiness
else
pass = target # truthiness
error = args.shift # optional message for TestUnit compatiability
end
__assert__(pass, error)
end
# TODO: Should we deprecate the receiver matches in favor of #expected ?
# In other words, should || @delegate
be dropped?
# Internal expect, provides all functionality associated
# with external #expect method. (See Expect#expect)
#
def expect(*args, &block)
return self if !block && args.empty? # same as #assert
pass = false
error = nil
if block
match = args.shift || @delegate # TODO: see above
if exception?(match)
$DEBUG, debug = false, $DEBUG # b/c it always spits-out a NameError
begin
block.arity > 0 ? block.call(@delegate) : block.call
pass = false
error = "#{match} not raised"
rescue match => error
pass = true
error = "#{match} raised"
rescue ::Exception => error
pass = false
error = "#{match} expected but #{error.class} was raised"
ensure
$DEBUG = debug
end
else
result = block.arity > 0 ? block.call(@delegte) : block.call
pass = (match === result)
error = @message || "#{match.inspect} === #{result.inspect}"
end
## Matcher
#elsif target.respond_to?(:matches?)
# pass = target.matches?(@delegate)
# error = @message || matcher_message(target) #|| target.inspect
# if target.respond_to?(:exception)
# #error_class = target.failure_class
# error = target.exception #failure(:backtrace=>@backtrace, :negated=>@negated)
# end
# Case Equality
else
target = args.shift
pass = (target === @delegate)
error = @message || "#{target.inspect} === #{@delegate.inspect}"
end
__assert__(pass, error)
end
#
def flunk(message=nil, backtrace=nil)
__assert__(false, message || @message)
end
# Ruby seems to have a quark in it's implementation whereby
# this must be defined explicitly, otherwise it somehow
# skips #method_missing.
def =~(match)
method_missing(:"=~", match)
end
#
def send(op, *a, &b)
method_missing(op, *a, &b)
end
#
def inspect
@delegate.inspect
end
private
# AE-STYLE ASSERTIONS
#
def proc_assertion?(target)
::Proc === target || target.respond_to?(:call) || target.respond_to?(:to_proc)
end
#
def proc_apply(target)
call = target.method(:call) rescue target.to_proc
pass = call.arity != 0 ? call.call(@delegate) : call.call
error = @message || (
to_s = target.method(:to_s)
to_s.arity == 0 ? to_s.call : to_s.call(@negated)
)
return pass, error
end
# ASSAY-STYLE ASSERTIONS
# (not yet supported b/c api is not 100%)
# Is the `assertion` object an assay-style assertion?
def assay_assertion?(assertion)
assertion.respond_to?(:exception) && assertion.respond_to?(:pass?)
end
#
def assay_assertion_apply(assay)
if @negated
pass = assay.fail?(@delegate)
error = assay #.exception(@message || )
else
pass = assay.pass?(@delegate)
error = assay #.exception(@message || )
end
return pass, error
end
# RSPEC-STYLE MATCHERS
# Is `target` an Rspec-style Matcher?
def rspec_matcher?(target)
target.respond_to?(:matches?)
end
#
def rspec_matcher_apply(matcher)
pass = matcher.matches?(@delegate)
error = @message || rspec_matcher_message(matcher)
return pass, error
end
# TODO: Is there anything to be done with matcher.description?
#
def rspec_matcher_message(matcher)
if @negated
if matcher.respond_to?(:failure_message_for_should_not)
return matcher.failure_message_for_should_not
end
if matcher.respond_to?(:negative_failure_message)
return matcher.negative_failure_message
end
end
if matcher.respond_to?(:failure_message_for_should)
return matcher.failure_message_for_should
end
if matcher.respond_to?(:failure_message)
return matcher.failure_message
end
return matcher.to_s # TODO: or just `nil` ?
end
# TODO: Should we use a more libreral determination of exception.
# e.g. respond_to?(:exception)
.
# Is the +object+ an Exception or an instance of one?
def exception?(object)
::Exception === object or ::Class === object and object.ancestors.include?(::Exception)
end
# TODO: In future should probably be `@delegate.public_send(sym, *a, &b)`.
# Converts a missing method into an Assertion.
def method_missing(sym, *args, &block)
error = @message || compare_message(sym, *args, &block) || generic_message(sym, *args, &block)
pass = @delegate.__send__(sym, *args, &block)
__assert__(pass, error)
end
# TODO: Can the handling of the message be simplified/improved?
# Simple assert.
def __assert__(pass, error=nil)
Assertor.assert(pass, error, @negated, @backtrace)
end
#
COMPARISON_OPERATORS = { :"==" => :"!=" }
# Message to use when making a comparion assertion.
#
# NOTE: This message utilizes the ANSI gem to produce colorized
# comparisons. If you need to remove color output (for non-ANSI
# terminals) you can either set `AE.ansi = false` or use the
# ANSI library's master switch to deactive all ANSI codes,
# which can be set in your test helper.
#
# @param operator [Symbol] operator/method
#
# @see http://rubyworks.github.com/ansi
def compare_message(operator, *args, &blk)
return nil unless COMPARISON_OPERATORS.key?(operator)
prefix = ""
a, b = @delegate.inspect, args.first.inspect
if @negated
op = COMPARISON_OPERATORS[operator]
if op
operator = op
else
prefix = "NOT "
end
end
if AE.ansi?
diff = ::ANSI::Diff.new(a,b)
a = diff.diff1
b = diff.diff2
end
if a.size > 13 or b.size > 13
prefix + "a #{operator} b\na) " + a + "\nb) " + b
else
prefix + "#{a} #{operator} #{b}"
end
end
# Puts together a suitable error message.
#
# @param op [Symbol] operator/method
#
# @return [String] message
def generic_message(op, *a, &b)
inspection = @delegate.send(:inspect)
if @negated
"! #{inspection} #{op} #{a.collect{|x| x.inspect}.join(',')}"
else
"#{inspection} #{op} #{a.collect{|x| x.inspect}.join(',')}"
end
#self.class.message(m)[@delegate, *a] )
end
# @see http://redmine.ruby-lang.org/issues/3768
def self.const_missing(const)
::Object.const_get(const)
end
end
end
# DO WE MAKE THESE EXCEPTIONS?
#class BasicObject
# def assert
# end
#end
# Copyright (c) 2008 Thomas Sawyer
ae-1.8.2/lib/ae/adapters/ 0000755 0000000 0000000 00000000000 12406706117 013547 5 ustar root root ae-1.8.2/lib/ae/adapters/minitest.rb 0000644 0000000 0000000 00000002543 12406706117 015734 0 ustar root root require 'ae'
AE.assertion_error = ::MiniTest::Assertion
module MiniTest #:nodoc:
class Unit #:nodoc:
# MiniTest tracks assertion counts internally in it's Unit class via the
# +assertion_count+ attribute. To work with AE we need add in AE's assertion
# total by overriding the +assertion_count+ method.
#
# @return [Integer] Number of assertions made.
def assertion_count
@assertion_count + AE::Assertor.counts[:total]
end
# To teach MiniTest to recognize AE's expanded concept of assertions
# we add in an extra capture clause to it's #puke method.
#
# @return [String] Status code is `S`, `F`, or `E`.
def puke k, m, e
case e
when MiniTest::Skip
@skips += 1
return "S" unless @verbose
e = "Skipped:\n#{m}(#{k}) [#{location e}]:\n#{e.message}\n"
when MiniTest::Assertion
@failures += 1
e = "Failure:\n#{m}(#{k}) [#{location e}]:\n#{e.message}\n"
else
if e.respond_to?(:assertion?) && e.assertion?
@failures += 1
e = "Failure:\n#{m}(#{c}) [#{location e}]:\n#{e.message}\n"
else
@errors += 1
b = MiniTest::filter_backtrace(e.backtrace).join "\n "
e = "Error:\n#{m}(#{k}):\n#{e.class}: #{e.message}\n #{b}\n"
end
end
@report << e
e[0, 1]
end
end
end
ae-1.8.2/lib/ae/adapters/rspec.rb 0000644 0000000 0000000 00000000324 12406706117 015207 0 ustar root root require 'ae'
AE.assertion_error = ::RSpec::Expectations::ExpectationNotMetError
# TODO: Teach RSpec the expanded concept of assertions, as Exception
# classes that respond to `#assertion?` in the affirmative.
ae-1.8.2/lib/ae/adapters/testunit.rb 0000644 0000000 0000000 00000004067 12406706117 015762 0 ustar root root require 'ae'
AE.assertion_error = ::Test::Unit::AssertionFailedError
# TestUnit uses #add_assertion on it's +result+ object to track counts.
# We capture the result object by overriding the TestCase#run method,
# store it in a global variable and then use it when AE increments
# assertion counts.
#
# In addition we teach #run to recognize any Exception class that
# responds to #assertion? in the affirmative as an assertion
# rather than an error.
#
module Test #:nodoc:
module Unit #:nodoc:
class TestCase #:nodoc:
# These exceptions are not caught by #run.
PASSTHROUGH_EXCEPTIONS = [NoMemoryError, SignalException, Interrupt, SystemExit]
# Runs the individual test method represented by this
# instance of the fixture, collecting statistics, failures
# and errors in result.
def run(result)
$_test_unit_result = result
yield(STARTED, name)
@_result = result
begin
setup
__send__(@method_name)
rescue AssertionFailedError => e
add_failure(e.message, e.backtrace)
rescue Exception => e
if e.respond_to?(:assertion?) && e.assertion?
add_failure(e.message, e.backtrace)
else
raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
add_error($!)
end
ensure
begin
teardown
rescue AssertionFailedError => e
add_failure(e.message, e.backtrace)
rescue Exception => e
if e.respond_to?(:assertion?) && e.assertion?
add_failure(e.message, e.backtrace)
else
raise if PASSTHROUGH_EXCEPTIONS.include? $!.class
add_error($!)
end
end
end
result.add_run
yield(FINISHED, name)
end
end
end
end
class AE::Assertor #:nodoc:
def self.increment_counts(pass)
$_test_unit_result.add_assertion if $_test_unit_result
counts[:total] += 1
if pass
counts[:pass] += 1
else
counts[:fail] += 1
end
return counts
end
end
ae-1.8.2/lib/ae/assertion.rb 0000644 0000000 0000000 00000002750 12406706117 014304 0 ustar root root require 'ae/core_ext'
module AE
# The Assertion class is simply a subclass of Exception that is used
# by AE as the default error raised when an assertion fails.
#
# "The reserve of modern assertions is sometimes pushed to extremes,
# in which the fear of being contradicted leads the writer to strip
# himself of almost all sense and meaning."
# -- Sir Winston Churchill (1874 - 1965)
#
#
class Assertion < Exception
# @deprecated
# This will be removed in favor of `AE::Assertor.counts`.
def self.counts
AE::Assertor.counts
end
# New assertion (failure).
#
# @param message [String] the failure message
# @param options [Hash] options such as :backtrace
#
def initialize(message=nil, options={})
super(message)
backtrace = options[:backtrace]
set_backtrace(backtrace) if backtrace
set_assertion(true)
end
# Technically any object that affirmatively responds to #assertion?
# can be taken to be an Assertion. This makes it easier for various
# libraries to work together without having to depend upon a common
# Assertion base class.
def assertion?
true
end
# Parents error message prefixed with "(assertion)".
#
# @return [String] error message
def to_s
'(assertion) ' + super
end
end
end
# Set top-level Assertion to AE::Assertion if not already present.
Assertion = AE::Assertion unless defined?(Assertion)
ae-1.8.2/lib/ae/expect.rb 0000644 0000000 0000000 00000003310 12406706117 013556 0 ustar root root module AE
require 'ae/assertor'
# = Expect
#
# "When love and skill work together, expect a masterpiece."
# --John Ruskin (1819 - 1900)
#
module Expect
# The #expect method is a convenient tool for defining
# certain sets of expectations in your specifications.
#
# Expect is used to expect a result from a block of code.
# If the argument to expect is a subclass of Exception
# or instance thereof, then the block is monitored for
# the raising of such an exception.
#
# expect StandardError do
# raise ArgumentError
# end
#
# All other expectations are compared using case equality (#===).
# This allows one to verify matching Regexp.
#
# expect /x/ do
# "x"
# end
#
# As well as checking that an object is an instance of a given Class.
#
# expect String do
# "x"
# end
#
# Like #assert it can be used to designate an expectation
# via a *functor*.
#
# 4.expect == 3
#
def expect(*args, &block)
Assertor.new(self, :backtrace=>caller).expect(*args, &block)
end
# Designate a negated expectation. Read this as "expect not".
#
# See #expect.
#
def expect!(*args, &block)
Assertor.new(self, :backtrace=>caller).not.expect(*args, &block)
end
# Alias for #expect! method.
alias_method :forbid, :expect!
# Like #expect but uses the reciever as the object
# of expectation.
#
# @example
# /x/.expected do
# "oooxooo"
# end
#
def expected(*args, &block)
expect(self, *args, &block)
end
end
end
# Copyright (c) 2008 Thomas Sawyer
ae-1.8.2/lib/ae/subjunctive.rb 0000644 0000000 0000000 00000003347 12406706117 014641 0 ustar root root require 'ae/assertor'
module AE
# Subjunctive
#
# Mixin for Assertor that provides additional English-eque verbage
# such as 'be' and 'an'. This makes it easier to create assertor
# methods of subjunctive terms like 'should'.
#
# @note THIS IS AN OPTIONAL LIBRARY.
module Subjunctive
# Like #assert, except if an argument is provided and no block,
# uses #equate? to compare the argument to the receiver. This
# allows for statements of the form:
#
# 5.should.be Numeric
#
def be(*args, &block)
return self if args.empty? && !block
block = args.shift if !block && ::Proc === args.first
if block
pass = block.arity > 0 ? block.call(@delegate) : block.call #@delegate.instance_eval(&block)
msg = args.shift || @message || block.inspect
else
pass = args.shift.equate?(@delegate)
msg = args.shift
end
__assert__(pass, msg)
end
# Alias of #be.
#
# 5.assert.is Numeric
#
alias_method :is , :be
alias_method :does, :be
# The indefinite article is like #be, except that it compares a lone argument
# with #case?, rather than #equate?
#
def a(*args, &block)
return self if args.empty? && !block
block = args.shift if !block && ::Proc === args.first
if block
pass = block.arity > 0 ? block.call(@delegate) : block.call #@delegate.instance_eval(&block)
msg = args.shift || @message || block.inspect
else
pass = (args.shift === @delegate) # case equality
msg = args.shift
end
__assert__(pass, msg)
end
alias_method :an, :a
end
end#module AE
class AE::Assertor
include ::AE::Subjunctive
end
# Copyright (c) 2008 Thomas Sawyer