assay 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.ruby +46 -41
- data/COPYING.rdoc +38 -0
- data/HISTORY.rdoc +18 -1
- data/QED.rdoc +1100 -0
- data/README.rdoc +139 -16
- data/lib/assay.rb +82 -29
- data/lib/assay.yml +46 -41
- data/lib/assay/{adapters → adapter}/minitest.rb +0 -0
- data/lib/assay/{adapters → adapter}/testunit.rb +0 -0
- data/lib/assay/assertable.rb +174 -0
- data/lib/assay/assertion.rb +98 -124
- data/lib/assay/assertor.rb +187 -0
- data/lib/assay/boolean_assay.rb +15 -0
- data/lib/assay/case_assay.rb +17 -0
- data/lib/assay/compare_assay.rb +38 -0
- data/lib/assay/core_ext/kernel.rb +52 -0
- data/lib/assay/core_ext/na.rb +9 -0
- data/lib/assay/directory_assay.rb +20 -0
- data/lib/assay/empty_assay.rb +17 -0
- data/lib/assay/equal_assay.rb +35 -0
- data/lib/assay/equality_assay.rb +18 -0
- data/lib/assay/execution_assay.rb +59 -0
- data/lib/assay/false_assay.rb +17 -0
- data/lib/assay/file_assay.rb +17 -0
- data/lib/assay/identity_assay.rb +49 -0
- data/lib/assay/include_assay.rb +17 -0
- data/lib/assay/instance_assay.rb +17 -0
- data/lib/assay/kind_assay.rb +18 -0
- data/lib/assay/less_assay.rb +18 -0
- data/lib/assay/less_equal_assay.rb +25 -0
- data/lib/assay/like_assay.rb +17 -0
- data/lib/assay/match_assay.rb +17 -0
- data/lib/assay/more_assay.rb +18 -0
- data/lib/assay/more_equal_assay.rb +25 -0
- data/lib/assay/nil_assay.rb +15 -0
- data/lib/assay/nomatch_assay.rb +17 -0
- data/lib/assay/output_assay.rb +35 -0
- data/lib/assay/path_assay.rb +17 -0
- data/lib/assay/raise_assay.rb +109 -0
- data/lib/assay/rescue_assay.rb +55 -0
- data/lib/assay/respond_assay.rb +17 -0
- data/lib/assay/return_assay.rb +46 -0
- data/lib/assay/silent_assay.rb +59 -0
- data/lib/assay/stderr_assay.rb +30 -0
- data/lib/assay/stdout_assay.rb +30 -0
- data/lib/assay/throw_assay.rb +89 -0
- data/lib/assay/true_assay.rb +20 -0
- data/lib/assay/unequal_assay.rb +37 -0
- data/lib/assay/within_assay.rb +39 -0
- data/test/case_compare_assay.rb +59 -0
- data/test/case_empty_assay.rb +51 -0
- data/test/case_equal_assay.rb +53 -0
- data/test/case_equality_assay.rb +55 -0
- data/test/case_false_assay.rb +48 -0
- data/test/case_identity_assay.rb +51 -0
- data/test/case_include_assay.rb +51 -0
- data/test/case_instance_assay.rb +51 -0
- data/test/case_kind_assay.rb +51 -0
- data/test/case_less_assay.rb +53 -0
- data/test/case_less_equal_assay.rb +53 -0
- data/test/case_like_assay.rb +57 -0
- data/test/case_match_assay.rb +45 -0
- data/test/case_more_assay.rb +53 -0
- data/test/case_more_equal_assay.rb +53 -0
- data/test/case_nil_assay.rb +48 -0
- data/test/case_nomatch_assay.rb +47 -0
- data/test/case_raise_assay.rb +51 -0
- data/test/case_respond_assay.rb +51 -0
- data/test/case_throw_assay.rb +51 -0
- data/test/case_true_assay.rb +48 -0
- data/test/case_unequal_assay.rb +55 -0
- data/test/case_within_assay.rb +61 -0
- data/test/helper.rb +36 -0
- metadata +135 -108
- data/APACHE2.txt +0 -205
- data/NOTICE.rdoc +0 -18
- data/lib/assay/assertions/compare_failure.rb +0 -61
- data/lib/assay/assertions/delta_failure.rb +0 -80
- data/lib/assay/assertions/empty_failure.rb +0 -76
- data/lib/assay/assertions/equality_failure.rb +0 -100
- data/lib/assay/assertions/execution_failure.rb +0 -90
- data/lib/assay/assertions/false_failure.rb +0 -72
- data/lib/assay/assertions/identity_failure.rb +0 -85
- data/lib/assay/assertions/instance_failure.rb +0 -76
- data/lib/assay/assertions/kind_failure.rb +0 -80
- data/lib/assay/assertions/match_failure.rb +0 -85
- data/lib/assay/assertions/nil_failure.rb +0 -75
- data/lib/assay/assertions/raise_failure.rb +0 -134
- data/lib/assay/assertions/response_failure.rb +0 -86
- data/lib/assay/assertions/same_failure.rb +0 -82
- data/lib/assay/assertions/throw_failure.rb +0 -122
- data/lib/assay/assertions/true_failure.rb +0 -79
- data/lib/assay/matcher.rb +0 -48
- data/qed/01_failure_classes.rdoc +0 -75
- data/qed/02_assertives.rdoc +0 -118
- data/qed/03_matchers.rdoc +0 -118
- data/qed/04_lookup.rdoc +0 -10
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'assertion'
|
2
|
+
|
3
|
+
# LikeAssay defines an assertion for broad equality.
|
4
|
+
#
|
5
|
+
class LikeAssay < Assertion
|
6
|
+
|
7
|
+
register :like
|
8
|
+
|
9
|
+
#
|
10
|
+
# Test assertion for `#like?`.
|
11
|
+
#
|
12
|
+
def self.pass?(subject, criterion)
|
13
|
+
subject.like?(criterion)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'compare_assay'
|
2
|
+
|
3
|
+
# Compare assertion is used to test a comparision
|
4
|
+
# made by `#>`.
|
5
|
+
#
|
6
|
+
class MoreAssay < CompareAssay
|
7
|
+
|
8
|
+
register :>, :more_than
|
9
|
+
|
10
|
+
#
|
11
|
+
# Check assertion using `#>` method call.
|
12
|
+
#
|
13
|
+
def self.pass?(subject, criterion)
|
14
|
+
subject > criterion
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative 'compare_assay'
|
2
|
+
|
3
|
+
# Compare assertion is used to test a comparision made by `#>=`.
|
4
|
+
#
|
5
|
+
# NOTE: We are taking some leeway here with the name of this class,
|
6
|
+
# which ordinarily would be called `GreaterThanOrEqualAssay`.
|
7
|
+
# However, such a name is a bit winded. The shortest name then,
|
8
|
+
# without resorting to abbreviations, is _more-equal_, a monosyllabic
|
9
|
+
# reading of the operator itself. Since it is ordinarily meaningless
|
10
|
+
# to say something is "more equal" than something else, why not allow
|
11
|
+
# it to be meaningful and save ourselves all that uneccessary verbage?
|
12
|
+
#
|
13
|
+
class MoreEqualAssay < CompareAssay
|
14
|
+
|
15
|
+
register :>=, :more_equal
|
16
|
+
|
17
|
+
#
|
18
|
+
# Check assertion using `#>=` method.
|
19
|
+
#
|
20
|
+
def self.pass?(subject, criterion)
|
21
|
+
subject >= criterion
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'match_assay'
|
2
|
+
|
3
|
+
# Ruby 1.9+ allows #!~ to redfined as it's own method, so a corresponding
|
4
|
+
# assay is required to cover it.
|
5
|
+
#
|
6
|
+
class NoMatchAssay < MatchAssay
|
7
|
+
|
8
|
+
register :!~, :nomatch
|
9
|
+
|
10
|
+
#
|
11
|
+
# Check no match assertion with `#!~` method.
|
12
|
+
#
|
13
|
+
def self.pass?(matcher, matchee)
|
14
|
+
matcher !~ matchee
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'assertion'
|
2
|
+
|
3
|
+
# Assert that there is output, either from stdout or stderr.
|
4
|
+
#
|
5
|
+
# OutputAssay.pass?(/foo/){ puts 'foo!' } #=> true
|
6
|
+
#
|
7
|
+
class OutputAssay < Assertion
|
8
|
+
|
9
|
+
register :output
|
10
|
+
|
11
|
+
#
|
12
|
+
# Compare +match+ against $stdout and $stderr via `#===` method.
|
13
|
+
#
|
14
|
+
# Note that $stdout and $stderr are temporarily reouted to StringIO
|
15
|
+
# objects and the results have any trailing newline chomped off.
|
16
|
+
#
|
17
|
+
def self.pass?(match, &block)
|
18
|
+
require 'stringio'
|
19
|
+
|
20
|
+
begin
|
21
|
+
stdout, stderr = $stdout, $stderr
|
22
|
+
newout, newerr = StringIO.new, StringIO.new
|
23
|
+
$stdout, $stderr = newout, newerr
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
$stdout, $stderr = stdout, stderr
|
27
|
+
end
|
28
|
+
|
29
|
+
newout, newerr = newout.string.chomp("\n"), newerr.string.chomp("\n")
|
30
|
+
|
31
|
+
match === newout || match === newerr
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'assertion'
|
2
|
+
|
3
|
+
# Assert the existance of a file with `File.file?` call.
|
4
|
+
#
|
5
|
+
class PathAssay < Assertion
|
6
|
+
|
7
|
+
register :path
|
8
|
+
|
9
|
+
#
|
10
|
+
# Check assertion using `File.exist?` method.
|
11
|
+
#
|
12
|
+
def self.pass?(path)
|
13
|
+
File.exist?(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require_relative 'rescue_assay'
|
2
|
+
|
3
|
+
#
|
4
|
+
class RaiseAssay < RescueAssay
|
5
|
+
|
6
|
+
register :raised
|
7
|
+
|
8
|
+
#
|
9
|
+
# Check assertion.
|
10
|
+
#
|
11
|
+
def self.pass?(*exceptions)
|
12
|
+
exceptions = [RuntimeError] if exceptions.empty?
|
13
|
+
begin
|
14
|
+
yield
|
15
|
+
false
|
16
|
+
rescue Exception => e
|
17
|
+
exceptions.any? do |x|
|
18
|
+
x.instance_of?(Module) ? x === e : e.class == x
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Check negated assertion.
|
25
|
+
#
|
26
|
+
def self.fail?(*exceptions)
|
27
|
+
exceptions = [RuntimeError] if exceptions.empty?
|
28
|
+
begin
|
29
|
+
yield
|
30
|
+
true
|
31
|
+
rescue Exception => e
|
32
|
+
!exceptions.any? do |x|
|
33
|
+
x.instance_of?(Module) ? x === e : e.class == x
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# TODO: How to add `but got class` to message?
|
39
|
+
# May have to override `#assert!` and `#refute!`.
|
40
|
+
|
41
|
+
#
|
42
|
+
#
|
43
|
+
#
|
44
|
+
def self.assert_message(*exceptions)
|
45
|
+
exp = exceptions.map{ |e| e.inspect }.join(' or ')
|
46
|
+
"raise #{exp}" #, but was #{err} instead."
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
#
|
51
|
+
#
|
52
|
+
def self.refute_message(*exceptions)
|
53
|
+
exp = exceptions.map{ |e| e.inspect }.join(' or ')
|
54
|
+
"! raise #{exp}" #, but was #{err} instead."
|
55
|
+
end
|
56
|
+
|
57
|
+
=begin
|
58
|
+
#
|
59
|
+
#
|
60
|
+
#
|
61
|
+
def self.assert!(*exp) #:yeild:
|
62
|
+
options = (Hash === exp.last ? exp.pop : {})
|
63
|
+
|
64
|
+
exp = exp.first
|
65
|
+
|
66
|
+
begin
|
67
|
+
yield
|
68
|
+
test = false
|
69
|
+
arguments = [exp]
|
70
|
+
rescue Exception => err
|
71
|
+
test = (exp === err)
|
72
|
+
arguments = [exp, err]
|
73
|
+
end
|
74
|
+
|
75
|
+
message = options[:message] || pass_message(*arguments)
|
76
|
+
backtrace = options[:backtrace] || caller
|
77
|
+
|
78
|
+
if !test
|
79
|
+
fail self, message, backtrace
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
#
|
85
|
+
#
|
86
|
+
def self.refute!(*exp) #:yield:
|
87
|
+
options = (Hash === exp.last ? exp.pop : {})
|
88
|
+
|
89
|
+
#exp = exp.first
|
90
|
+
|
91
|
+
begin
|
92
|
+
yield
|
93
|
+
test = true
|
94
|
+
arguments = exp
|
95
|
+
rescue Exception => err
|
96
|
+
test = !exp.any?{ |e| e === err }
|
97
|
+
arguments = exp #+ [err]
|
98
|
+
end
|
99
|
+
|
100
|
+
message = options[:message] || fail_message(*arguments)
|
101
|
+
backtrace = options[:backtrace] || caller
|
102
|
+
|
103
|
+
if !test
|
104
|
+
fail self, message, backtrace
|
105
|
+
end
|
106
|
+
end
|
107
|
+
=end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'assertion'
|
2
|
+
|
3
|
+
# Assert that a kind of exception class is rescued
|
4
|
+
# from the execution of a block.
|
5
|
+
#
|
6
|
+
class RescueAssay < Assertion
|
7
|
+
|
8
|
+
register :rescue
|
9
|
+
|
10
|
+
#
|
11
|
+
# Check assertion.
|
12
|
+
#
|
13
|
+
def self.pass?(*exceptions)
|
14
|
+
exceptions = [RuntimeError] if exceptions.empty?
|
15
|
+
begin
|
16
|
+
yield
|
17
|
+
false
|
18
|
+
rescue Exception => e
|
19
|
+
exceptions.any? do |x|
|
20
|
+
x === e
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Check negated assertion.
|
27
|
+
#
|
28
|
+
def self.fail?(*exceptions)
|
29
|
+
exceptions = [RuntimeError] if exceptions.empty?
|
30
|
+
begin
|
31
|
+
yield
|
32
|
+
true
|
33
|
+
rescue Exception => e
|
34
|
+
!exceptions.any? do |x|
|
35
|
+
x === e
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO: How to add `but got class` message to error?
|
41
|
+
# May have to override #assert! and #refute! method.
|
42
|
+
|
43
|
+
#
|
44
|
+
def self.assert_message(*exceptions)
|
45
|
+
exp = exceptions.map{ |e| e.inspect }.join(' or ')
|
46
|
+
"raise #{exp}" #, but was #{err} instead."
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
def self.refute_message(*exceptions)
|
51
|
+
exp = exceptions.map{ |e| e.inspect }.join(' or ')
|
52
|
+
"! raise #{exp}" #, but was #{err} instead."
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'assertion'
|
2
|
+
|
3
|
+
# Does an object #respond_to? a method call.
|
4
|
+
#
|
5
|
+
class RespondAssay < Assertion
|
6
|
+
|
7
|
+
register :respond_to
|
8
|
+
|
9
|
+
# Check assertion.
|
10
|
+
def self.pass?(reciever, method_name)
|
11
|
+
#flip = (Symbol === obj) && ! (Symbol === meth) # HACK for specs
|
12
|
+
#obj, meth = meth, obj if flip
|
13
|
+
reciever.respond_to?(method_name)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'execution_assay'
|
2
|
+
|
3
|
+
# Assert that a block of code returns a specific result, also
|
4
|
+
# fails if an error is raised in the block.
|
5
|
+
#
|
6
|
+
class ReturnAssay < ExecutionAssay
|
7
|
+
|
8
|
+
register :returns
|
9
|
+
|
10
|
+
#
|
11
|
+
# Check that a block returns a specific value comparing
|
12
|
+
# the +returns+ argument and actual returned value with
|
13
|
+
# the `#==` operator.
|
14
|
+
#
|
15
|
+
def self.pass?(returns, *arguments) #:yield:
|
16
|
+
begin
|
17
|
+
result = yield(*arguments)
|
18
|
+
returns == result
|
19
|
+
rescue Exception
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Check that a block does NOT return a specific value comparing
|
26
|
+
# the +returns+ argument and actual returned value with
|
27
|
+
# the `#==` operator.
|
28
|
+
#
|
29
|
+
def self.fail?(returns, *arguments) #:yield:
|
30
|
+
begin
|
31
|
+
result = yield(*arguments)
|
32
|
+
returns != result
|
33
|
+
rescue Exception
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
##
|
40
|
+
##
|
41
|
+
#def self.assert_message(*arguments, &block)
|
42
|
+
# "#{block}.call(*#{arguments.inspect})"
|
43
|
+
#end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative 'output_assay'
|
2
|
+
|
3
|
+
# Assert that there is no output, either from stdout or stderr.
|
4
|
+
#
|
5
|
+
# SilentAssay.pass?{ puts 'foo!' } #=> false
|
6
|
+
#
|
7
|
+
class SilentAssay < OutputAssay
|
8
|
+
|
9
|
+
register :silent
|
10
|
+
|
11
|
+
#
|
12
|
+
# Compare +match+ against $stdout and $stderr via `#===` method.
|
13
|
+
#
|
14
|
+
# Note that $stdout and $stderr are temporarily reouted to StringIO
|
15
|
+
# objects and the results have any trailing newline chomped off.
|
16
|
+
#
|
17
|
+
def self.pass?(&block)
|
18
|
+
require 'stringio'
|
19
|
+
|
20
|
+
begin
|
21
|
+
stdout, stderr = $stdout, $stderr
|
22
|
+
newout, newerr = StringIO.new, StringIO.new
|
23
|
+
$stdout, $stderr = newout, newerr
|
24
|
+
yield
|
25
|
+
ensure
|
26
|
+
$stdout, $stderr = stdout, stderr
|
27
|
+
end
|
28
|
+
|
29
|
+
newout, newerr = newout.string.chomp("\n"), newerr.string.chomp("\n")
|
30
|
+
|
31
|
+
newout.empty? && newerr.empty?
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO: Assertable isn't dealing with no-argument assertions well,
|
35
|
+
# see if this can be improved.
|
36
|
+
|
37
|
+
#
|
38
|
+
# Opposite of `SilentAssay.pass?`.
|
39
|
+
#
|
40
|
+
def self.fail?(&block)
|
41
|
+
! pass?(&block)
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
#
|
46
|
+
#
|
47
|
+
def self.assert_message(*)
|
48
|
+
"unexpected output"
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
#
|
53
|
+
#
|
54
|
+
def self.refute_message(*)
|
55
|
+
"expected output"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|