assay 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|