qed 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{LICENSE → COPYING} +2 -2
- data/MANIFEST +2 -16
- data/README.rdoc +58 -21
- data/bin/qed +13 -13
- data/demo/01_spec.qed +6 -3
- data/doc/qedoc/index.html +13 -10
- data/lib/qed.rb +4 -3
- data/lib/qed/document.rb +9 -10
- data/lib/qed/{utilities/extract.rb → extract.rb} +0 -0
- data/lib/qed/script.rb +7 -1
- data/meta/requires +2 -0
- data/meta/version +1 -1
- metadata +25 -15
- data/lib/qed/assertion.rb +0 -23
- data/lib/qed/doubles/mock.rb +0 -94
- data/lib/qed/doubles/spy.rb +0 -191
- data/lib/qed/doubles/stub.rb +0 -94
- data/lib/qed/expectation.rb +0 -60
- data/lib/qed/grammar/assert.rb +0 -104
- data/lib/qed/grammar/expect.rb +0 -121
- data/lib/qed/grammar/legacy/assert.rb +0 -291
- data/lib/qed/grammar/should.rb +0 -52
- data/lib/qed/utilities/monitor.rb +0 -23
data/lib/qed/assertion.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
|
3
|
-
# = Assertion
|
4
|
-
#
|
5
|
-
# This is the core class of the whole specification system.
|
6
|
-
#
|
7
|
-
class Assertion < Exception
|
8
|
-
|
9
|
-
def initialize(message, backtrace=nil)
|
10
|
-
super(message)
|
11
|
-
set_backtrace(backtrace) if backtrace
|
12
|
-
end
|
13
|
-
|
14
|
-
def to_str
|
15
|
-
message.to_s.strip
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
# Copyright (c) 2008 Tiger Ops
|
23
|
-
|
data/lib/qed/doubles/mock.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
|
3
|
-
# = Mock
|
4
|
-
#
|
5
|
-
class Mock < Module
|
6
|
-
attr :object
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
super()
|
10
|
-
@table = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
def __table__ ; @table ; end
|
15
|
-
|
16
|
-
# TODO: Ruby has retry, but I need continue!
|
17
|
-
def method_missing(meth, *args, &block)
|
18
|
-
table = @table
|
19
|
-
interface = [meth, args, block_given?]
|
20
|
-
|
21
|
-
table[interface] = nil
|
22
|
-
|
23
|
-
define_method(meth) do |*args|
|
24
|
-
result = super
|
25
|
-
result.assert == table[interface]
|
26
|
-
return result
|
27
|
-
end
|
28
|
-
|
29
|
-
Setter.new(table, interface)
|
30
|
-
end
|
31
|
-
|
32
|
-
#
|
33
|
-
class Setter
|
34
|
-
def initialize(table, interface)
|
35
|
-
@table = table
|
36
|
-
@interface = interface
|
37
|
-
end
|
38
|
-
|
39
|
-
def ==(result)
|
40
|
-
@table[@interface] = result
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# = Mock::Delegator
|
45
|
-
#
|
46
|
-
class Delegator
|
47
|
-
instance_methods(true).each{ |m| protected m unless m.to_s =~ /^__/ }
|
48
|
-
|
49
|
-
def initialize(object, mock_module)
|
50
|
-
@instance_delegate = object
|
51
|
-
extend(mock_module)
|
52
|
-
end
|
53
|
-
|
54
|
-
def method_missing(s, *a, &b)
|
55
|
-
@instance_delegate.__send__(s, *a, &b)
|
56
|
-
end
|
57
|
-
end#class Delegator
|
58
|
-
|
59
|
-
end#class Mock
|
60
|
-
|
61
|
-
class ::Object
|
62
|
-
# Create mock object.
|
63
|
-
def mock(mock_module=nil)
|
64
|
-
if mock_module
|
65
|
-
Mock::Delegator.new(self, mock_module)
|
66
|
-
else
|
67
|
-
@_mock ||= Mock.new
|
68
|
-
extend(@_mock)
|
69
|
-
@_mock
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# We can't remove the module per-say. So we have to
|
74
|
-
# just neuter it. This is a very weak solution, but
|
75
|
-
# it will suffice for the moment.
|
76
|
-
#--
|
77
|
-
# TODO: Use Carats for #unmix.
|
78
|
-
#++
|
79
|
-
def remove_mock(mock_module=nil)
|
80
|
-
mock_module ||= @_mock
|
81
|
-
obj = self
|
82
|
-
mod = Module.new
|
83
|
-
mock_module.__table__.each do |interface, result|
|
84
|
-
meth = interface[0]
|
85
|
-
mod.module_eval do
|
86
|
-
define_method(meth, &obj.class.instance_method(meth).bind(obj))
|
87
|
-
end
|
88
|
-
end
|
89
|
-
extend(mod)
|
90
|
-
end
|
91
|
-
end#class ::Object
|
92
|
-
|
93
|
-
end#module Quarry
|
94
|
-
|
data/lib/qed/doubles/spy.rb
DELETED
@@ -1,191 +0,0 @@
|
|
1
|
-
raise "Spy class is under construction"
|
2
|
-
|
3
|
-
module QED
|
4
|
-
|
5
|
-
# = Spy
|
6
|
-
#
|
7
|
-
# Spy (aka DuckHunter) is a decoy object which is dropped into
|
8
|
-
# methods which records the calls made against it --hence a method probe.
|
9
|
-
# Of course, it is not perfect --an inescapable matter it seems for any
|
10
|
-
# internal probe. There are a couple of issues related to conditionals.
|
11
|
-
# Since the method test for a certain condition against the decoy, how
|
12
|
-
# is the decoy to respond? Thus ceratin paths in the code may never get
|
13
|
-
# exceuted and thus go unmapped. If Ruby had better conditional reflection
|
14
|
-
# (i.e. if 'if', 'case', 'unless', 'when', etc. were true methods) then
|
15
|
-
# this could be fixed by making the Probe reentrant, mapping out variant
|
16
|
-
# true/false/nil replies. The likely insurmountable problem though is the
|
17
|
-
# Halting problem. A probe can cause some methods to complete execution.
|
18
|
-
# It's pretty rare, but it can happen and little can be done about it (I think).
|
19
|
-
#
|
20
|
-
# Note, the alternative to this kind of probe is a program that examines, rather
|
21
|
-
# then executes, the code. This would circumvent the above problems, but run
|
22
|
-
# into difficulties with dynamic evals. It would also be more complicated,
|
23
|
-
# but might prove a better means in the future.
|
24
|
-
#
|
25
|
-
# This script is provided for experimetnal purposes. Please inform the author
|
26
|
-
# if you find ways to improve it or put it to an interesting use.
|
27
|
-
#
|
28
|
-
# == Synopsis
|
29
|
-
#
|
30
|
-
# require 'methodprobe'
|
31
|
-
#
|
32
|
-
# def amethod(x)
|
33
|
-
# x + 1
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# p method(:amethod).signiture
|
37
|
-
# p method(:amethod).signiture(:class)
|
38
|
-
# p method(:amethod).signiture(:pretty)
|
39
|
-
#
|
40
|
-
# produces
|
41
|
-
#
|
42
|
-
# [["+"]]
|
43
|
-
# [{"+"=>[["Fixnum"]]}]
|
44
|
-
# [["+( Fixnum )"]]
|
45
|
-
#
|
46
|
-
class Spy
|
47
|
-
|
48
|
-
def self.duckcall
|
49
|
-
begin
|
50
|
-
yield
|
51
|
-
rescue TypeError => e
|
52
|
-
self.send(e.message)
|
53
|
-
retry
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
attr_reader :ducks, :decoys
|
58
|
-
|
59
|
-
def initialize
|
60
|
-
@ducks, @decoys = {}, {}
|
61
|
-
end
|
62
|
-
|
63
|
-
def initialize_copy(from)
|
64
|
-
initialize
|
65
|
-
end
|
66
|
-
|
67
|
-
def method_missing(aSym, *args)
|
68
|
-
aSymStr = aSym.to_s
|
69
|
-
|
70
|
-
# This will happen the first time
|
71
|
-
@ducks[aSymStr] ||= [] #unless @ducks[aSymStr]
|
72
|
-
@ducks[aSymStr] << args.collect { |a| "#{a.class}" }
|
73
|
-
|
74
|
-
decoy = self.dup
|
75
|
-
|
76
|
-
@decoys[aSymStr] ||= [] #unless @decoys[aSymStr]
|
77
|
-
@decoys[aSymStr] << decoy
|
78
|
-
|
79
|
-
# build proxy?
|
80
|
-
#begin
|
81
|
-
# d = <<-HERE
|
82
|
-
# def self.#{aSymStr}(*args)
|
83
|
-
# # This will happen the subsequent times
|
84
|
-
# @ducks["#{aSymStr}"] << args.collect { |a| #{'"#{a.class}"'} }
|
85
|
-
# @ducks["#{aSymStr}"].uniq!
|
86
|
-
# decoy = self.dup
|
87
|
-
# @decoys["#{aSymStr}"] = [] unless @decoys["#{aSymStr}"]
|
88
|
-
# @decoys["#{aSymStr}"] << decoy
|
89
|
-
# decoy
|
90
|
-
# end
|
91
|
-
# HERE
|
92
|
-
# instance_eval d
|
93
|
-
#rescue SyntaxError
|
94
|
-
# puts "This error may be avoidable by returning the failing duck type as the error message."
|
95
|
-
# raise
|
96
|
-
#end
|
97
|
-
|
98
|
-
decoy
|
99
|
-
end
|
100
|
-
|
101
|
-
end # class MethodProbe
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
class ::Method
|
107
|
-
|
108
|
-
# Outputs migration information.
|
109
|
-
def migration
|
110
|
-
parameters = []; argc = self.arity
|
111
|
-
if argc > 0
|
112
|
-
argc.times { parameters << Quarry::Probe.new }
|
113
|
-
Probe.duckcall { self.call(*parameters) }
|
114
|
-
elsif argc < 0
|
115
|
-
raise "(NYI) method takes unlimited arguments"
|
116
|
-
end
|
117
|
-
return parameters
|
118
|
-
end
|
119
|
-
private :migration
|
120
|
-
|
121
|
-
# Outputs signiture information.
|
122
|
-
def signature(detail=nil)
|
123
|
-
ds = []
|
124
|
-
case detail
|
125
|
-
when :complete, :all, :full
|
126
|
-
ds = migration
|
127
|
-
when :class, :with_class
|
128
|
-
migration.each { |dh| ds << dh.ducks }
|
129
|
-
when :pp, :pretty, :prettyprint, :pretty_print
|
130
|
-
migration.each do |dh|
|
131
|
-
responders = []
|
132
|
-
dh.ducks.each do |responder, argss|
|
133
|
-
argss.each { |args| responders << "#{responder}( #{args.join(',')} )" }
|
134
|
-
end
|
135
|
-
ds << responders
|
136
|
-
end
|
137
|
-
else
|
138
|
-
migration.each { |dh| ds << dh.ducks.keys }
|
139
|
-
end
|
140
|
-
return ds
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
=begin test
|
150
|
-
|
151
|
-
require 'test/unit'
|
152
|
-
|
153
|
-
# " I am a Duck Hunter ! "
|
154
|
-
|
155
|
-
class TC_MethodProbe < Test::Unit::TestCase
|
156
|
-
|
157
|
-
# fixture
|
158
|
-
def amethod(x)
|
159
|
-
x + 1
|
160
|
-
end
|
161
|
-
|
162
|
-
def test_signiture_default
|
163
|
-
assert_nothing_raised {
|
164
|
-
method(:amethod).signature
|
165
|
-
}
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_signiture_with_class
|
169
|
-
assert_nothing_raised {
|
170
|
-
method(:amethod).signature(:class)
|
171
|
-
}
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_signiture_pp
|
175
|
-
assert_nothing_raised {
|
176
|
-
method(:amethod).signature(:pp)
|
177
|
-
}
|
178
|
-
end
|
179
|
-
|
180
|
-
def test_signiture_all
|
181
|
-
assert_nothing_raised {
|
182
|
-
method(:amethod).signature(:complete)
|
183
|
-
}
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
|
-
=end
|
189
|
-
|
190
|
-
# Copyright (c) 2004,2008 Thomas Sawyer
|
191
|
-
|
data/lib/qed/doubles/stub.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
|
3
|
-
# = Stub
|
4
|
-
#
|
5
|
-
class Stub < Module
|
6
|
-
attr :object
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
super()
|
10
|
-
@table = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
def __table__ ; @table ; end
|
15
|
-
|
16
|
-
#
|
17
|
-
def method_missing(meth, *args, &block)
|
18
|
-
table = @table
|
19
|
-
interface = [meth, args, block_given?]
|
20
|
-
|
21
|
-
table[interface] = nil
|
22
|
-
|
23
|
-
define_method(meth) do |*args|
|
24
|
-
table[interface]
|
25
|
-
end
|
26
|
-
|
27
|
-
Setter.new(table, interface)
|
28
|
-
end
|
29
|
-
|
30
|
-
#
|
31
|
-
class Setter
|
32
|
-
def initialize(table, interface)
|
33
|
-
@table = table
|
34
|
-
@interface = interface
|
35
|
-
end
|
36
|
-
|
37
|
-
def ==(result)
|
38
|
-
@table[@interface] = result
|
39
|
-
end
|
40
|
-
end#class Setter
|
41
|
-
|
42
|
-
# = Stub::Delegator
|
43
|
-
#
|
44
|
-
class Delegator
|
45
|
-
instance_methods(true).each{ |m| protected m unless m.to_s =~ /^__/ }
|
46
|
-
|
47
|
-
def initialize(object, stub_module)
|
48
|
-
@instance_delegate = object
|
49
|
-
extend(stub_module)
|
50
|
-
end
|
51
|
-
|
52
|
-
def method_missing(s, *a, &b)
|
53
|
-
@instance_delegate.__send__(s, *a, &b)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
end#class Stub
|
58
|
-
|
59
|
-
class ::Object
|
60
|
-
|
61
|
-
# Create a new stub.
|
62
|
-
def stub(stub_module=nil)
|
63
|
-
if stub_module
|
64
|
-
Stub::Delegator.new(self, stub_module)
|
65
|
-
else
|
66
|
-
@_stub ||= Stub.new
|
67
|
-
extend(@_stub)
|
68
|
-
@_stub
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# We can't remove the module per-say. So we have to
|
73
|
-
# just neuter it. This is a very weak solution, but
|
74
|
-
# it will suffice for the moment.
|
75
|
-
#--
|
76
|
-
# TODO: Use Carats for #unmix.
|
77
|
-
#++
|
78
|
-
def remove_stub(stub_module=nil)
|
79
|
-
stub_module ||= @_stub
|
80
|
-
obj = self
|
81
|
-
mod = Module.new
|
82
|
-
stub_module.__table__.each do |interface, result|
|
83
|
-
meth = interface[0]
|
84
|
-
mod.module_eval do
|
85
|
-
define_method(meth, &obj.class.instance_method(meth).bind(obj))
|
86
|
-
end
|
87
|
-
end
|
88
|
-
extend(mod)
|
89
|
-
end
|
90
|
-
|
91
|
-
end#class ::Object
|
92
|
-
|
93
|
-
end#module Quarry
|
94
|
-
|
data/lib/qed/expectation.rb
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
module QED
|
2
|
-
|
3
|
-
require 'qed/assertion'
|
4
|
-
|
5
|
-
# = Expectation
|
6
|
-
#
|
7
|
-
# Expectation is an Assertion Functor.
|
8
|
-
#
|
9
|
-
class Expectation
|
10
|
-
|
11
|
-
hide = instance_methods.select{ |m| m.to_s !~ /^__/ }
|
12
|
-
hide.each{ |m| protected m }
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
# New Expectation.
|
17
|
-
#
|
18
|
-
def initialize(delegate, ioc={}) #, backtrace)
|
19
|
-
@delegate = delegate
|
20
|
-
@negate = ioc[:negate]
|
21
|
-
@message = ioc[:message]
|
22
|
-
@backtrace = ioc[:backtrace] || caller #[1..-1]
|
23
|
-
end
|
24
|
-
|
25
|
-
# Converts missing method into an Assertion.
|
26
|
-
#
|
27
|
-
def method_missing(sym, *a, &b)
|
28
|
-
test = @delegate.__send__(sym, *a, &b)
|
29
|
-
|
30
|
-
if (@negate ? test : !test)
|
31
|
-
msg = @message || __msg__(sym, *a, &b)
|
32
|
-
error = Assertion.new(msg)
|
33
|
-
error.set_backtrace(@backtrace)
|
34
|
-
raise error
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Puts together a suitable error message.
|
39
|
-
#
|
40
|
-
def __msg__(m, *a, &b)
|
41
|
-
if @negate
|
42
|
-
"! #{@delegate.inspect} #{m} #{a.collect{|x| x.inspect}.join(',')}"
|
43
|
-
else
|
44
|
-
"#{@delegate.inspect} #{m} #{a.collect{|x| x.inspect}.join(',')}"
|
45
|
-
end
|
46
|
-
#self.class.message(m)[@delegate, *a] )
|
47
|
-
end
|
48
|
-
|
49
|
-
# TODO: Ultimately better messages would be nice ?
|
50
|
-
#
|
51
|
-
#def self.message(op,&block)
|
52
|
-
# @message ||= {}
|
53
|
-
# block ? @message[op.to_sym] = block : @message[op.to_sym]
|
54
|
-
#end
|
55
|
-
#
|
56
|
-
#message(:==){ |*a| "Expected #{a[0].inspect} to be equal to #{a[1].inspect}" }
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|