expectation 0.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/contracts.rb +197 -0
- data/lib/core/exception.rb +15 -0
- data/lib/expectation/assertions.rb +19 -23
- data/lib/expectation/version.rb +1 -1
- data/lib/expectation.rb +59 -112
- data/test/assertions_test.rb +2 -1
- data/test/contracts_module_test.rb +48 -0
- data/test/contracts_singleton_test.rb +28 -0
- data/test/contracts_test.rb +88 -0
- data/test/coverage/assets/0.10.0/application.css +799 -0
- data/test/coverage/assets/0.10.0/application.js +1707 -0
- data/test/coverage/assets/0.10.0/colorbox/border.png +0 -0
- data/test/coverage/assets/0.10.0/colorbox/controls.png +0 -0
- data/test/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
- data/test/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_green.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_red.png +0 -0
- data/test/coverage/assets/0.10.0/favicon_yellow.png +0 -0
- data/test/coverage/assets/0.10.0/loading.gif +0 -0
- data/test/coverage/assets/0.10.0/magnify.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
- data/test/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/test/coverage/index.html +72 -0
- data/test/exception_extension_test.rb +19 -0
- data/test/expection_test.rb +46 -0
- data/test/matching_test.rb +77 -0
- data/test/test_helper.rb +20 -7
- metadata +42 -18
- data/test/expect_test.rb +0 -119
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ba45fedcad85c3bc355804668620c834db45f2a1
|
4
|
+
data.tar.gz: 19766d7a77e76bd18e51e246ab1fee0ed0be3209
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 321eeaddc541552fd4261b5b6b9ca5f2095280abdc974ef3cb104077f5fee924d4d53cdf3218d839decf553099073276e0fa3d22dae07af26ca1ca77030e1654
|
7
|
+
data.tar.gz: 6b40a3e8403b34dea1eac1d877b62c62a1a0d5d7de9798cda203e1492305e32fbe00ba5fc252803c746c6b9b4e47772a1c66d1787866f440e3a6f3aa88063551
|
data/lib/contracts.rb
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: radiospiel (mailto:eno@radiospiel.org)
|
3
|
+
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
4
|
+
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
5
|
+
#++
|
6
|
+
|
7
|
+
# The Contract module provides annotation support. That basically
|
8
|
+
# means you can define expectations outside (or, to be more specific, before)
|
9
|
+
# the function definition.
|
10
|
+
#
|
11
|
+
# We currently support the following annotations:
|
12
|
+
#
|
13
|
+
# - expects!
|
14
|
+
# - returns!
|
15
|
+
#
|
16
|
+
# == Example
|
17
|
+
#
|
18
|
+
# class Foo
|
19
|
+
#
|
20
|
+
# +Expects(value1: Fixnum, value2: /.@./)
|
21
|
+
# +Returns(Fixnum)
|
22
|
+
#
|
23
|
+
# def bar(value1, value2)
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
module Contracts
|
28
|
+
class Error < ArgumentError; end
|
29
|
+
|
30
|
+
def self.current_contracts
|
31
|
+
Thread.current[:current_contracts] ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.consume_current_contracts
|
35
|
+
r, Thread.current[:current_contracts] = Thread.current[:current_contracts], nil
|
36
|
+
r
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.included(klass)
|
40
|
+
klass.extend ClassMethods
|
41
|
+
end
|
42
|
+
|
43
|
+
class AnnotatedMethod
|
44
|
+
def initialize(method, annotations)
|
45
|
+
@method = method
|
46
|
+
|
47
|
+
@before_annotations = annotations.select { |annotation| annotation.respond_to?(:before_call) }
|
48
|
+
@after_annotations = annotations.select { |annotation| annotation.respond_to?(:after_call) }
|
49
|
+
@exception_annotations = annotations.select { |annotation| annotation.respond_to?(:on_exception) }
|
50
|
+
|
51
|
+
annotations.each do |annotation|
|
52
|
+
annotation.method = method
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def invoke(receiver, *args, &blk)
|
57
|
+
@before_annotations.each do |annotation|
|
58
|
+
annotation.before_call(receiver, *args, &blk)
|
59
|
+
end
|
60
|
+
|
61
|
+
# instance methods are UnboundMethod, class methods are Method.
|
62
|
+
rv = @method.is_a?(Method) ? @method.call(*args, &blk)
|
63
|
+
: @method.bind(receiver).call(*args, &blk)
|
64
|
+
|
65
|
+
@after_annotations.each do |annotation|
|
66
|
+
annotation.after_call(rv, receiver, *args, &blk)
|
67
|
+
end
|
68
|
+
|
69
|
+
return rv
|
70
|
+
rescue StandardError => exc
|
71
|
+
@exception_annotations.each do |annotation|
|
72
|
+
annotation.on_exception(exc, receiver, *args, &blk)
|
73
|
+
end
|
74
|
+
raise exc
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module ClassMethods
|
79
|
+
def singleton_method_added(name)
|
80
|
+
if annotations = Contracts.consume_current_contracts
|
81
|
+
method = singleton_method(name)
|
82
|
+
annotated_method = Contracts::AnnotatedMethod.new(method, annotations)
|
83
|
+
|
84
|
+
klass = self
|
85
|
+
|
86
|
+
define_singleton_method name do |*args, &blk|
|
87
|
+
annotated_method.invoke klass, *args, &blk
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
super
|
92
|
+
end
|
93
|
+
|
94
|
+
def method_added(name)
|
95
|
+
if annotations = Contracts.consume_current_contracts
|
96
|
+
method = instance_method(name)
|
97
|
+
annotated_method = Contracts::AnnotatedMethod.new(method, annotations)
|
98
|
+
|
99
|
+
define_method name do |*args, &blk|
|
100
|
+
annotated_method.invoke self, *args, &blk
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
super
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# A Base contract.
|
110
|
+
class Base
|
111
|
+
#
|
112
|
+
# This is the unary "+" operator. It adds the contract to the current_contracts array.
|
113
|
+
def +@
|
114
|
+
Contracts.current_contracts << self
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# contains the method once the contract is initialized, which happens
|
119
|
+
# in the Class#{singleton_,}method_added callback.
|
120
|
+
attr :method, true
|
121
|
+
|
122
|
+
#
|
123
|
+
# Returns a description of the method; i.e. Class#name or Class.name
|
124
|
+
def method_name
|
125
|
+
if method.is_a?(Method) # A singleton method?
|
126
|
+
# The method owner is the singleton class of the class. Sadly, the
|
127
|
+
# the singleton class has no name; hence we try to construct the name
|
128
|
+
# from its to_s description.
|
129
|
+
klass_name = method.owner.to_s.gsub(/#<(.*?):(.*)>/, "\\2")
|
130
|
+
"#{klass_name}.#{method.name}"
|
131
|
+
else
|
132
|
+
"#{method.owner}##{method.name}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
require "expectation"
|
139
|
+
|
140
|
+
class Contracts::Expects < Contracts::Base
|
141
|
+
attr :expectations
|
142
|
+
|
143
|
+
def initialize(expectations)
|
144
|
+
@expectations = expectations
|
145
|
+
end
|
146
|
+
|
147
|
+
def before_call(receiver, *args, &blk)
|
148
|
+
@parameter_names ||= method.parameters.map(&:last)
|
149
|
+
|
150
|
+
@parameter_names.each_with_index do |parameter_name, idx|
|
151
|
+
next unless expectation = expectations[parameter_name]
|
152
|
+
|
153
|
+
Expectation.match! args[idx], expectation
|
154
|
+
end
|
155
|
+
rescue Expectation::Error
|
156
|
+
raise Contracts::Error, "#{$!} in call to `#{method_name}`", caller[5..-1]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
module Contracts::ClassMethods
|
161
|
+
def Expects(expectation)
|
162
|
+
expect! expectation => Hash
|
163
|
+
Contracts::Expects.new(expectation)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Contracts::Returns < Contracts::Base
|
168
|
+
attr :expectation
|
169
|
+
|
170
|
+
def initialize(expectation)
|
171
|
+
@expectation = expectation
|
172
|
+
end
|
173
|
+
|
174
|
+
def after_call(rv, receiver, *args, &blk)
|
175
|
+
Expectation.match! rv, expectation
|
176
|
+
rescue Expectation::Error
|
177
|
+
raise Contracts::Error, "#{$!} in return of `#{method_name}`", caller[5..-1]
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
module Contracts::ClassMethods
|
182
|
+
def Returns(expectation)
|
183
|
+
Contracts::Returns.new(expectation)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class Contracts::Nothrows < Contracts::Base
|
188
|
+
def on_exception(rv, method, receiver, *args, &blk)
|
189
|
+
raise Contracts::Error, "Nothrow method `#{method_name}` raised exception: #{$!}", caller[5..-1]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
module Contracts::ClassMethods
|
194
|
+
def Nothrow
|
195
|
+
Contracts::Nothrows.new
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: radiospiel (mailto:eno@radiospiel.org)
|
3
|
+
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
4
|
+
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
5
|
+
#++
|
6
|
+
|
7
|
+
class Exception
|
8
|
+
# Create an ArgumentError with an adjusted backtrace. We don't want to
|
9
|
+
# see the user all the annotation internals.
|
10
|
+
def reraise_with_current_backtrace!
|
11
|
+
set_backtrace caller[2..-1]
|
12
|
+
raise self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -3,24 +3,16 @@
|
|
3
3
|
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
4
4
|
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
5
5
|
#++
|
6
|
-
# By requiring "expectation/assertions" you add expect! und unexpect! assertions
|
7
|
-
# to your test/unit testcases.
|
8
6
|
|
9
|
-
if !defined?(::Expectation::Assertions)
|
10
|
-
|
11
|
-
if !defined?(::Expectation)
|
12
|
-
require_relative "../expectation"
|
13
|
-
end
|
14
7
|
|
15
8
|
# The Expectation::Assertions module provides expect! and inexpect!
|
16
9
|
# assertions to use from within test cases.
|
17
10
|
#
|
18
11
|
# == Example
|
19
|
-
#
|
20
|
-
# require_relative 'test_helper'
|
21
|
-
# require 'expectation/assertions'
|
22
12
|
#
|
23
13
|
# class ExpectationTest < Test::Unit::TestCase
|
14
|
+
# include Expectation::Assertions
|
15
|
+
#
|
24
16
|
# def test_one
|
25
17
|
# end
|
26
18
|
# end
|
@@ -28,23 +20,27 @@ end
|
|
28
20
|
module Expectation::Assertions
|
29
21
|
# verifies the passed in expectations
|
30
22
|
def expect!(*expectation, &block)
|
31
|
-
|
32
|
-
|
23
|
+
exc = nil
|
24
|
+
|
25
|
+
begin
|
26
|
+
Expectation.expect!(*expectation, &block)
|
27
|
+
rescue Expectation::Error
|
28
|
+
exc = $!
|
29
|
+
end
|
30
|
+
|
31
|
+
assert_block(exc && exc.message) { !exc }
|
33
32
|
end
|
34
33
|
|
35
34
|
# verifies the failure of the passed in expectations
|
36
35
|
def inexpect!(*expectation, &block)
|
37
|
-
|
38
|
-
assert_block("Expectation(s) should fail, but didn't") { !good }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
36
|
+
exc = nil
|
43
37
|
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
begin
|
39
|
+
Expectation.expect!(*expectation, &block)
|
40
|
+
rescue Expectation::Error
|
41
|
+
exc = $!
|
42
|
+
end
|
47
43
|
|
48
|
-
|
49
|
-
|
44
|
+
assert_block("Expectation(s) should fail, but didn't") { exc }
|
45
|
+
end
|
50
46
|
end
|
data/lib/expectation/version.rb
CHANGED
data/lib/expectation.rb
CHANGED
@@ -3,6 +3,12 @@
|
|
3
3
|
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
4
4
|
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
5
5
|
#++
|
6
|
+
|
7
|
+
module Expectation; end
|
8
|
+
|
9
|
+
require_relative "core/exception"
|
10
|
+
require_relative "expectation/assertions"
|
11
|
+
|
6
12
|
# The Expectation module implements methods to verify one or more values
|
7
13
|
# against set of expectations. This is a subset of
|
8
14
|
# design-by-contract programming (see http://en.wikipedia.org/wiki/Design_by_contract)
|
@@ -24,136 +30,77 @@
|
|
24
30
|
# end
|
25
31
|
|
26
32
|
module Expectation
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.timeout
|
32
|
-
Thread.current[:expectation_timeout]
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.last_error=(error)
|
36
|
-
Thread.current[:expectation_last_error] = error
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.last_error
|
40
|
-
Thread.current[:expectation_last_error]
|
41
|
-
end
|
42
|
-
|
43
|
-
def expect!(*expectations, &block)
|
44
|
-
return if Expectation.met_expectations?(*expectations, &block)
|
45
|
-
|
46
|
-
# build exception with adjusted backtrace.
|
47
|
-
backtrace = caller #[3 .. -1]
|
33
|
+
class Error < ArgumentError
|
34
|
+
attr :value, :expectation, :info
|
48
35
|
|
49
|
-
|
50
|
-
|
51
|
-
|
36
|
+
def initialize(value, expectation, info = nil)
|
37
|
+
@value, @expectation, @info =
|
38
|
+
value, expectation, info
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
message = "#{value.inspect} does not match #{expectation.inspect}"
|
43
|
+
message += ", #{info}" if info
|
44
|
+
message
|
52
45
|
end
|
53
|
-
|
54
|
-
raise e
|
55
|
-
end
|
56
|
-
|
57
|
-
# Verifies a number of expectations. If one or more expectations are
|
58
|
-
# not met it raises an ArgumentError.
|
59
|
-
#
|
60
|
-
# This method can be enabled or disabled at runtime using
|
61
|
-
# Expectation.enable and Expectation.disable.
|
62
|
-
def expect(*expectations, &block)
|
63
|
-
expect!(*expectations, &block)
|
64
|
-
end
|
65
|
-
|
66
|
-
# A do nothing expect method. This is the standin for expect, when
|
67
|
-
# Expectation are disabled.
|
68
|
-
def expect_dummy!(*expectations, &block) #:nodoc:
|
69
46
|
end
|
70
47
|
|
71
|
-
# Verifies a number of expectations. Raises an ArgumentError if one
|
72
|
-
# or more expectations are not met.
|
73
48
|
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
49
|
+
# Verifies a number of expectations. If one or more expectations are
|
50
|
+
# not met it raises an ArgumentError (on the first failing expectation).
|
51
|
+
def expect!(*expectations, &block)
|
52
|
+
expectations.each do |expectation|
|
53
|
+
if expectation.is_a?(Hash)
|
54
|
+
expectation.all? do |actual, exp|
|
55
|
+
match! actual, exp
|
56
|
+
end
|
81
57
|
else
|
82
|
-
|
58
|
+
match! expectation, :truish
|
83
59
|
end
|
84
60
|
end
|
85
61
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
begin
|
91
|
-
timeout, Expectation.timeout = Expectation.timeout, nil
|
62
|
+
match! block, :__block if block
|
63
|
+
rescue Error
|
64
|
+
$!.reraise_with_current_backtrace!
|
65
|
+
end
|
92
66
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
101
|
-
ensure
|
102
|
-
Expectation.timeout = timeout
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Does a value meet the expectation? Retruns +true+ or +false+.
|
107
|
-
def self.met?(value, expectation) #:nodoc:
|
108
|
-
case expectation
|
109
|
-
when :truish then !!value
|
110
|
-
when :fail then false
|
111
|
-
when Array then expectation.any? { |e| met?(value, e) }
|
112
|
-
when Proc then expectation.arity == 0 ? expectation.call : expectation.call(value)
|
113
|
-
when Regexp then value.is_a?(String) && expectation =~ value
|
114
|
-
else expectation === value
|
115
|
-
end
|
67
|
+
#
|
68
|
+
# Does a value match an expectation?
|
69
|
+
def match?(value, expectation)
|
70
|
+
match! value, expectation
|
71
|
+
true
|
72
|
+
rescue Error
|
73
|
+
false
|
116
74
|
end
|
117
75
|
|
118
|
-
#
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
next true if met?(value[key], expect)
|
132
|
-
|
133
|
-
failed_value, failed_expectation, message = value[key], expect, "at key #{key.inspect}"
|
134
|
-
false
|
135
|
-
end
|
136
|
-
end
|
76
|
+
# Matches a value against an expectation. Raises an Expectation::Error
|
77
|
+
# if the expectation could not be matched.
|
78
|
+
def match!(value, expectation, key=nil)
|
79
|
+
match = case expectation
|
80
|
+
when :truish then !!value
|
81
|
+
when :fail then false
|
82
|
+
when Array then expectation.any? { |e| _match?(value, e) }
|
83
|
+
when Proc then expectation.arity == 0 ? expectation.call : expectation.call(value)
|
84
|
+
when Regexp then value.is_a?(String) && expectation =~ value
|
85
|
+
when :__block then value.call
|
86
|
+
when Hash then Hash === value &&
|
87
|
+
expectation.each { |key, exp| match! value[key], exp, key }
|
88
|
+
else expectation === value
|
137
89
|
end
|
138
|
-
|
139
|
-
# are we good?
|
140
|
-
return true if good
|
141
|
-
|
142
|
-
Expectation.last_error = "#{failed_value.inspect} does not meet expectation #{failed_expectation.inspect}#{message && ", #{message}"}"
|
143
90
|
|
144
|
-
return
|
145
|
-
end
|
91
|
+
return if match
|
146
92
|
|
147
|
-
|
148
|
-
def self.enable
|
149
|
-
alias_method :expect, :expect!
|
93
|
+
raise Error.new(value, expectation, key && "at key #{key.inspect}")
|
150
94
|
end
|
151
95
|
|
152
|
-
|
153
|
-
|
154
|
-
|
96
|
+
private
|
97
|
+
|
98
|
+
def _match?(value, expectation)
|
99
|
+
match! value, expectation
|
100
|
+
true
|
101
|
+
rescue Error
|
102
|
+
false
|
155
103
|
end
|
156
104
|
end
|
157
105
|
|
158
|
-
Expectation.enable
|
159
106
|
Object.send :include, Expectation
|
data/test/assertions_test.rb
CHANGED
@@ -2,9 +2,10 @@
|
|
2
2
|
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
3
3
|
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
4
4
|
require_relative 'test_helper'
|
5
|
-
require "expectation/assertions"
|
6
5
|
|
7
6
|
class AssertionsTest < Test::Unit::TestCase
|
7
|
+
include Expectation::Assertions
|
8
|
+
|
8
9
|
def test_expectations
|
9
10
|
expect! 1 => 1
|
10
11
|
inexpect! 1 => 2
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Author:: radiospiel (mailto:eno@radiospiel.org)
|
2
|
+
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
3
|
+
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
4
|
+
require_relative 'test_helper'
|
5
|
+
|
6
|
+
require "contracts"
|
7
|
+
|
8
|
+
class ContractsModuleTest < Test::Unit::TestCase
|
9
|
+
module M
|
10
|
+
include Contracts
|
11
|
+
|
12
|
+
+Expects(one: 1)
|
13
|
+
def needs_one(one)
|
14
|
+
one * 2
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Klass
|
19
|
+
extend M
|
20
|
+
end
|
21
|
+
|
22
|
+
class Instance
|
23
|
+
include M
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_class_method
|
27
|
+
assert_nothing_raised() {
|
28
|
+
Klass.needs_one(1)
|
29
|
+
}
|
30
|
+
|
31
|
+
e = assert_raise(Contracts::Error) {
|
32
|
+
Klass.needs_one(2)
|
33
|
+
}
|
34
|
+
assert e.backtrace.first.include?("test/contracts_module_test.rb:")
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_instance_method
|
38
|
+
instance = Instance.new
|
39
|
+
assert_nothing_raised() {
|
40
|
+
instance.needs_one(1)
|
41
|
+
}
|
42
|
+
|
43
|
+
e = assert_raise(Contracts::Error) {
|
44
|
+
instance.needs_one(2)
|
45
|
+
}
|
46
|
+
assert e.backtrace.first.include?("test/contracts_module_test.rb:")
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Author:: radiospiel (mailto:eno@radiospiel.org)
|
2
|
+
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
3
|
+
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
4
|
+
require_relative 'test_helper'
|
5
|
+
|
6
|
+
require "contracts"
|
7
|
+
|
8
|
+
class ContractsSingletonTest < Test::Unit::TestCase
|
9
|
+
class Foo
|
10
|
+
include Contracts
|
11
|
+
|
12
|
+
+Expects(one: 1)
|
13
|
+
def self.klass_method(one)
|
14
|
+
one * 2
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_class_method
|
19
|
+
assert_nothing_raised() {
|
20
|
+
Foo.klass_method(1)
|
21
|
+
}
|
22
|
+
|
23
|
+
e = assert_raise(Contracts::Error) {
|
24
|
+
Foo.klass_method(2)
|
25
|
+
}
|
26
|
+
assert e.backtrace.first.include?("test/contracts_singleton_test.rb:")
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Author:: radiospiel (mailto:eno@radiospiel.org)
|
2
|
+
# Copyright:: Copyright (c) 2011, 2012 radiospiel
|
3
|
+
# License:: Distributes under the terms of the Modified BSD License, see LICENSE.BSD for details.
|
4
|
+
require_relative 'test_helper'
|
5
|
+
|
6
|
+
require "contracts"
|
7
|
+
|
8
|
+
class ContractsTest < Test::Unit::TestCase
|
9
|
+
class Foo
|
10
|
+
include Contracts
|
11
|
+
|
12
|
+
+Expects(a: 1)
|
13
|
+
def sum(a, b, c)
|
14
|
+
a + b + c
|
15
|
+
end
|
16
|
+
|
17
|
+
+Returns(2)
|
18
|
+
def returns_arg(r)
|
19
|
+
r
|
20
|
+
end
|
21
|
+
|
22
|
+
+Expects(v: Fixnum)
|
23
|
+
def throw_on_one(v)
|
24
|
+
raise if v == 1
|
25
|
+
end
|
26
|
+
|
27
|
+
+Nothrow()
|
28
|
+
def unexpected_throw_on_one(v)
|
29
|
+
raise if v == 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
attr :foo
|
34
|
+
|
35
|
+
def setup
|
36
|
+
@foo = Foo.new
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_contracts_check_number_of_arguments
|
40
|
+
e = assert_raise(ArgumentError) {
|
41
|
+
foo.sum(1) # scripts/test:67:in `f': wrong number of arguments (1 for 3) (ArgumentError)
|
42
|
+
}
|
43
|
+
assert e.backtrace.first.include?("test/contracts_test.rb:")
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_expects_contract
|
47
|
+
rv = nil
|
48
|
+
assert_nothing_raised() { rv = foo.sum(1,2,3) }
|
49
|
+
assert_equal(rv, 6)
|
50
|
+
|
51
|
+
e = assert_raise(Contracts::Error) {
|
52
|
+
foo.sum(2,2,3)
|
53
|
+
}
|
54
|
+
assert e.backtrace.first.include?("test/contracts_test.rb:")
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_returns_contract
|
58
|
+
assert_nothing_raised() {
|
59
|
+
foo.returns_arg(2)
|
60
|
+
}
|
61
|
+
|
62
|
+
e = assert_raise(Contracts::Error) {
|
63
|
+
foo.returns_arg(1)
|
64
|
+
}
|
65
|
+
assert e.backtrace.first.include?("test/contracts_test.rb:")
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_nothrow_contract
|
69
|
+
assert_nothing_raised() {
|
70
|
+
foo.unexpected_throw_on_one(2)
|
71
|
+
}
|
72
|
+
|
73
|
+
e = assert_raise(Contracts::Error) {
|
74
|
+
foo.unexpected_throw_on_one(1)
|
75
|
+
}
|
76
|
+
assert e.backtrace.first.include?("test/contracts_test.rb:")
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_still_throws_fine
|
80
|
+
assert_nothing_raised() {
|
81
|
+
foo.throw_on_one(2)
|
82
|
+
}
|
83
|
+
|
84
|
+
assert_raise(RuntimeError) {
|
85
|
+
foo.throw_on_one(1)
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|