quarry 0.3.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/CHANGES +6 -0
- data/COPYING +344 -0
- data/MANIFEST +151 -0
- data/METADATA +22 -0
- data/NEWS +8 -0
- data/README +75 -0
- data/VERSION +1 -0
- data/bin/rubybreak +3 -0
- data/bin/xact-ruby +6 -0
- data/demo/spec/demo_check.rb +21 -0
- data/demo/spec/demo_outline.rb +25 -0
- data/demo/test/demo_run.rb +21 -0
- data/doc/manual.html2 +1416 -0
- data/doc/rdoc/classes/Assertion.html +101 -0
- data/doc/rdoc/classes/Assertion/False.html +132 -0
- data/doc/rdoc/classes/Assertion/True.html +137 -0
- data/doc/rdoc/classes/Kernel.html +86 -0
- data/doc/rdoc/classes/Method.html +137 -0
- data/doc/rdoc/classes/Module.html +165 -0
- data/doc/rdoc/classes/Object.html +154 -0
- data/doc/rdoc/classes/Quarry.html +177 -0
- data/doc/rdoc/classes/Quarry/Design.html +170 -0
- data/doc/rdoc/classes/Quarry/Design/Specification.html +265 -0
- data/doc/rdoc/classes/Quarry/Design/Specification/Context.html +174 -0
- data/doc/rdoc/classes/Quarry/MethodProbe.html +267 -0
- data/doc/rdoc/classes/Quarry/Mock.html +89 -0
- data/doc/rdoc/classes/Quarry/Mock/Object.html +276 -0
- data/doc/rdoc/created.rid +1 -0
- data/doc/rdoc/files/CHANGES.html +100 -0
- data/doc/rdoc/files/COPYING.html +457 -0
- data/doc/rdoc/files/MANIFEST.html +630 -0
- data/doc/rdoc/files/METADATA.html +92 -0
- data/doc/rdoc/files/NEWS.html +99 -0
- data/doc/rdoc/files/README.html +171 -0
- data/doc/rdoc/files/VERSION.html +96 -0
- data/doc/rdoc/files/bin/rubybreak.html +96 -0
- data/doc/rdoc/files/bin/xact-ruby.html +92 -0
- data/doc/rdoc/files/lib/quarry/assert/must_rb.html +96 -0
- data/doc/rdoc/files/lib/quarry/assert/should_rb.html +96 -0
- data/doc/rdoc/files/lib/quarry/assertion_rb.html +96 -0
- data/doc/rdoc/files/lib/quarry/breakout_rb.html +144 -0
- data/doc/rdoc/files/lib/quarry/design/spec_rb.html +100 -0
- data/doc/rdoc/files/lib/quarry/document_rb.html +92 -0
- data/doc/rdoc/files/lib/quarry/loadmonitor_rb.html +92 -0
- data/doc/rdoc/files/lib/quarry/methodprobe_rb.html +111 -0
- data/doc/rdoc/files/lib/quarry/mock/object_rb.html +123 -0
- data/doc/rdoc/files/lib/quarry/mockery_rb.html +115 -0
- data/doc/rdoc/fr_class_index.html +60 -0
- data/doc/rdoc/fr_file_index.html +65 -0
- data/doc/rdoc/fr_method_index.html +77 -0
- data/doc/rdoc/index.html +26 -0
- data/doc/rdoc/rdoc-style.css +175 -0
- data/doc/ri/Assertion/False/assert-i.yaml +10 -0
- data/doc/ri/Assertion/False/cdesc-False.yaml +19 -0
- data/doc/ri/Assertion/False/message-i.yaml +10 -0
- data/doc/ri/Assertion/True/assert-i.yaml +11 -0
- data/doc/ri/Assertion/True/cdesc-True.yaml +24 -0
- data/doc/ri/Assertion/True/message-c.yaml +11 -0
- data/doc/ri/Assertion/True/message-i.yaml +11 -0
- data/doc/ri/Assertion/True/method_missing-i.yaml +11 -0
- data/doc/ri/Assertion/True/new-c.yaml +11 -0
- data/doc/ri/Assertion/cdesc-Assertion.yaml +17 -0
- data/doc/ri/Kernel/cdesc-Kernel.yaml +15 -0
- data/doc/ri/Method/cdesc-Method.yaml +18 -0
- data/doc/ri/Method/migration-i.yaml +12 -0
- data/doc/ri/Method/signature-i.yaml +12 -0
- data/doc/ri/Module/cdesc-Module.yaml +21 -0
- data/doc/ri/Module/doc-i.yaml +16 -0
- data/doc/ri/Module/method_added-i.yaml +10 -0
- data/doc/ri/Object/assert%21-i.yaml +14 -0
- data/doc/ri/Object/assert-i.yaml +14 -0
- data/doc/ri/Object/cdesc-Object.yaml +20 -0
- data/doc/ri/Quarry/Design/Specification/Context/after-i.yaml +10 -0
- data/doc/ri/Quarry/Design/Specification/Context/before-i.yaml +10 -0
- data/doc/ri/Quarry/Design/Specification/Context/cdesc-Context.yaml +24 -0
- data/doc/ri/Quarry/Design/Specification/Context/method_missing-i.yaml +10 -0
- data/doc/ri/Quarry/Design/Specification/Context/specifications-i.yaml +10 -0
- data/doc/ri/Quarry/Design/Specification/cdesc-Specification.yaml +44 -0
- data/doc/ri/Quarry/Design/Specification/check-i.yaml +12 -0
- data/doc/ri/Quarry/Design/Specification/new-c.yaml +12 -0
- data/doc/ri/Quarry/Design/Specification/outline-i.yaml +12 -0
- data/doc/ri/Quarry/Design/cdesc-Design.yaml +22 -0
- data/doc/ri/Quarry/Design/check-c.yaml +12 -0
- data/doc/ri/Quarry/Design/outline-c.yaml +10 -0
- data/doc/ri/Quarry/Design/specification-c.yaml +10 -0
- data/doc/ri/Quarry/Design/specifications-c.yaml +10 -0
- data/doc/ri/Quarry/MethodProbe/cdesc-MethodProbe.yaml +46 -0
- data/doc/ri/Quarry/MethodProbe/duckcall-c.yaml +10 -0
- data/doc/ri/Quarry/MethodProbe/initialize_copy-i.yaml +10 -0
- data/doc/ri/Quarry/MethodProbe/method_missing-i.yaml +10 -0
- data/doc/ri/Quarry/MethodProbe/new-c.yaml +10 -0
- data/doc/ri/Quarry/Mock/Object/cdesc-Object.yaml +52 -0
- data/doc/ri/Quarry/Mock/Object/echo-c.yaml +12 -0
- data/doc/ri/Quarry/Mock/Object/keys-c.yaml +12 -0
- data/doc/ri/Quarry/Mock/Object/mock-c.yaml +12 -0
- data/doc/ri/Quarry/Mock/Object/mocks-c.yaml +10 -0
- data/doc/ri/Quarry/Mock/Object/spin-c.yaml +12 -0
- data/doc/ri/Quarry/Mock/cdesc-Mock.yaml +15 -0
- data/doc/ri/Quarry/Mockery-i.yaml +12 -0
- data/doc/ri/Quarry/cdesc-Quarry.yaml +17 -0
- data/doc/ri/created.rid +1 -0
- data/lib/quarry/assert/must.rb +8 -0
- data/lib/quarry/assert/should.rb +9 -0
- data/lib/quarry/assertion.rb +95 -0
- data/lib/quarry/breakout.rb +45 -0
- data/lib/quarry/design/spec.rb +197 -0
- data/lib/quarry/document.rb +35 -0
- data/lib/quarry/loadmonitor.rb +14 -0
- data/lib/quarry/methodprobe.rb +216 -0
- data/lib/quarry/mock/object.rb +169 -0
- data/lib/quarry/mockery.rb +85 -0
- metadata +214 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
$_doc = []
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Module
|
|
5
|
+
|
|
6
|
+
attr :docs
|
|
7
|
+
|
|
8
|
+
# The idea here is to have dynamic docs.
|
|
9
|
+
#
|
|
10
|
+
# doc "X does such and such"
|
|
11
|
+
# doc "it is very powerful"
|
|
12
|
+
# class X
|
|
13
|
+
# doc "f does such and such"
|
|
14
|
+
# doc "it is where the power lies"
|
|
15
|
+
# def f
|
|
16
|
+
# ...
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# One of the great things about doc, is that
|
|
21
|
+
# it can be used to "inherit" documentation.
|
|
22
|
+
|
|
23
|
+
def doc(str)
|
|
24
|
+
$_doc << string
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def method_added(meth)
|
|
28
|
+
@docs ||= {}
|
|
29
|
+
@docs[self, meth] << $_doc
|
|
30
|
+
$_doc.clear
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# = methodprobe.rb
|
|
2
|
+
#
|
|
3
|
+
# == Copyright (c) 2004 Thomas Sawyer
|
|
4
|
+
#
|
|
5
|
+
# Ruby License
|
|
6
|
+
#
|
|
7
|
+
# This module is free software. You may use, modify, and/or redistribute this
|
|
8
|
+
# software under the same terms as Ruby.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
12
|
+
# FOR A PARTICULAR PURPOSE.
|
|
13
|
+
#
|
|
14
|
+
# == Author(s)
|
|
15
|
+
#
|
|
16
|
+
# * Thomas Sawyer
|
|
17
|
+
|
|
18
|
+
# Author:: Thomas Sawyer
|
|
19
|
+
# Copyright:: Copyright (c) 2006 Thomas Sawyer
|
|
20
|
+
# License:: Ruby License
|
|
21
|
+
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
module Quarry
|
|
25
|
+
|
|
26
|
+
# = Method Probe
|
|
27
|
+
#
|
|
28
|
+
# Method::Probe (aka DuckHunter) is a decoy object which is dropped into
|
|
29
|
+
# methods which records the calls made against it --hence a method probe.
|
|
30
|
+
# Of course, it is not perfect --an inescapable matter it seems for any
|
|
31
|
+
# internal probe. There are a couple of issues related to conditionals.
|
|
32
|
+
# Since the method test for a certain condition against the decoy, how
|
|
33
|
+
# is the decoy to respond? Thus ceratin paths in the code may never get
|
|
34
|
+
# exceuted and thus go unmapped. If Ruby had better conditional reflection
|
|
35
|
+
# (i.e. if 'if', 'case', 'unless', 'when', etc. were true methods) then
|
|
36
|
+
# this could be fixed by making the Probe reentrant, mapping out variant
|
|
37
|
+
# true/false/nil replies. The likely insurmountable problem though is the
|
|
38
|
+
# Halting problem. A probe can cause some methods to complete execution.
|
|
39
|
+
# It's pretty rare, but it can happen and little can be done about it (I think).
|
|
40
|
+
#
|
|
41
|
+
# Note, the alternative to this kind of probe is a program that examines, rather
|
|
42
|
+
# then executes, the code. This would circumvent the above problems, but run
|
|
43
|
+
# into difficulties with dynamic evals. It would also be more complicated,
|
|
44
|
+
# but might prove a better means in the future.
|
|
45
|
+
#
|
|
46
|
+
# This script is provided for experimetnal purposes. Please inform the author
|
|
47
|
+
# if you find ways to improve it or put it to an interesting use.
|
|
48
|
+
#
|
|
49
|
+
# == Synopsis
|
|
50
|
+
#
|
|
51
|
+
# require 'methodprobe'
|
|
52
|
+
#
|
|
53
|
+
# def amethod(x)
|
|
54
|
+
# x + 1
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# p method(:amethod).signiture
|
|
58
|
+
# p method(:amethod).signiture(:class)
|
|
59
|
+
# p method(:amethod).signiture(:pretty)
|
|
60
|
+
#
|
|
61
|
+
# produces
|
|
62
|
+
#
|
|
63
|
+
# [["+"]]
|
|
64
|
+
# [{"+"=>[["Fixnum"]]}]
|
|
65
|
+
# [["+( Fixnum )"]]
|
|
66
|
+
#
|
|
67
|
+
|
|
68
|
+
class MethodProbe
|
|
69
|
+
|
|
70
|
+
def MethodProbe.duckcall
|
|
71
|
+
begin
|
|
72
|
+
yield
|
|
73
|
+
rescue TypeError => e
|
|
74
|
+
self.send(e.message)
|
|
75
|
+
retry
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
attr_reader :ducks, :decoys
|
|
80
|
+
|
|
81
|
+
def initialize
|
|
82
|
+
@ducks, @decoys = {}, {}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def initialize_copy(from)
|
|
86
|
+
initialize
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def method_missing(aSym, *args)
|
|
90
|
+
aSymStr = aSym.to_s
|
|
91
|
+
|
|
92
|
+
# This will happen the first time
|
|
93
|
+
@ducks[aSymStr] ||= [] #unless @ducks[aSymStr]
|
|
94
|
+
@ducks[aSymStr] << args.collect { |a| "#{a.class}" }
|
|
95
|
+
|
|
96
|
+
decoy = self.dup
|
|
97
|
+
|
|
98
|
+
@decoys[aSymStr] ||= [] #unless @decoys[aSymStr]
|
|
99
|
+
@decoys[aSymStr] << decoy
|
|
100
|
+
|
|
101
|
+
# build proxy?
|
|
102
|
+
#begin
|
|
103
|
+
# d = <<-HERE
|
|
104
|
+
# def self.#{aSymStr}(*args)
|
|
105
|
+
# # This will happen the subsequent times
|
|
106
|
+
# @ducks["#{aSymStr}"] << args.collect { |a| #{'"#{a.class}"'} }
|
|
107
|
+
# @ducks["#{aSymStr}"].uniq!
|
|
108
|
+
# decoy = self.dup
|
|
109
|
+
# @decoys["#{aSymStr}"] = [] unless @decoys["#{aSymStr}"]
|
|
110
|
+
# @decoys["#{aSymStr}"] << decoy
|
|
111
|
+
# decoy
|
|
112
|
+
# end
|
|
113
|
+
# HERE
|
|
114
|
+
# instance_eval d
|
|
115
|
+
#rescue SyntaxError
|
|
116
|
+
# puts "This error may be avoidable by returning the failing duck type as the error message."
|
|
117
|
+
# raise
|
|
118
|
+
#end
|
|
119
|
+
|
|
120
|
+
decoy
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end # class MethodProbe
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class Method
|
|
129
|
+
|
|
130
|
+
# Outputs migration information.
|
|
131
|
+
def migration
|
|
132
|
+
parameters = []; argc = self.arity
|
|
133
|
+
if argc > 0
|
|
134
|
+
argc.times { parameters << MethodProbe.new }
|
|
135
|
+
Probe.duckcall { self.call(*parameters) }
|
|
136
|
+
elsif argc < 0
|
|
137
|
+
raise "(NYI) method takes unlimited arguments"
|
|
138
|
+
end
|
|
139
|
+
return parameters
|
|
140
|
+
end
|
|
141
|
+
private :migration
|
|
142
|
+
|
|
143
|
+
# Outputs signiture information.
|
|
144
|
+
def signature(detail=nil)
|
|
145
|
+
ds = []
|
|
146
|
+
case detail
|
|
147
|
+
when :complete, :all, :full
|
|
148
|
+
ds = migration
|
|
149
|
+
when :class, :with_class
|
|
150
|
+
migration.each { |dh| ds << dh.ducks }
|
|
151
|
+
when :pp, :pretty, :prettyprint, :pretty_print
|
|
152
|
+
migration.each do |dh|
|
|
153
|
+
responders = []
|
|
154
|
+
dh.ducks.each do |responder, argss|
|
|
155
|
+
argss.each { |args| responders << "#{responder}( #{args.join(',')} )" }
|
|
156
|
+
end
|
|
157
|
+
ds << responders
|
|
158
|
+
end
|
|
159
|
+
else
|
|
160
|
+
migration.each { |dh| ds << dh.ducks.keys }
|
|
161
|
+
end
|
|
162
|
+
return ds
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
# _____ _
|
|
171
|
+
# |_ _|__ ___| |_
|
|
172
|
+
# | |/ _ \/ __| __|
|
|
173
|
+
# | | __/\__ \ |_
|
|
174
|
+
# |_|\___||___/\__|
|
|
175
|
+
#
|
|
176
|
+
|
|
177
|
+
=begin testing
|
|
178
|
+
|
|
179
|
+
require 'test/unit'
|
|
180
|
+
|
|
181
|
+
# " I am a Duck Hunter ! "
|
|
182
|
+
|
|
183
|
+
class TC_MethodProbe < Test::Unit::TestCase
|
|
184
|
+
|
|
185
|
+
# fixture
|
|
186
|
+
def amethod(x)
|
|
187
|
+
x + 1
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_signiture_default
|
|
191
|
+
assert_nothing_raised {
|
|
192
|
+
method(:amethod).signature
|
|
193
|
+
}
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def test_signiture_with_class
|
|
197
|
+
assert_nothing_raised {
|
|
198
|
+
method(:amethod).signature(:class)
|
|
199
|
+
}
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def test_signiture_pp
|
|
203
|
+
assert_nothing_raised {
|
|
204
|
+
method(:amethod).signature(:pp)
|
|
205
|
+
}
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test_signiture_all
|
|
209
|
+
assert_nothing_raised {
|
|
210
|
+
method(:amethod).signature(:complete)
|
|
211
|
+
}
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
=end
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# = mock.rb
|
|
2
|
+
#
|
|
3
|
+
# == Copyright (c) 2005 Thomas Sawyer, Michael Granger
|
|
4
|
+
#
|
|
5
|
+
# Ruby License
|
|
6
|
+
#
|
|
7
|
+
# This module is free software. You may use, modify, and/or redistribute this
|
|
8
|
+
# software under the same terms as Ruby.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
12
|
+
# FOR A PARTICULAR PURPOSE.
|
|
13
|
+
#
|
|
14
|
+
# == Special Thanks
|
|
15
|
+
#
|
|
16
|
+
# Thanks goes to Michael Granger for Test::Unit::Mock on which
|
|
17
|
+
# this library is partially based.
|
|
18
|
+
#
|
|
19
|
+
# == Author(s)
|
|
20
|
+
#
|
|
21
|
+
# * Thomas Sawyer
|
|
22
|
+
# * Michael Granger
|
|
23
|
+
|
|
24
|
+
require 'ostruct'
|
|
25
|
+
|
|
26
|
+
module Quarry
|
|
27
|
+
|
|
28
|
+
module Mock
|
|
29
|
+
|
|
30
|
+
# = Mock Object
|
|
31
|
+
#
|
|
32
|
+
# A straightfoward mocking facility. Typically used in test cases.
|
|
33
|
+
# The Mock class offers a few constructors for quickly building
|
|
34
|
+
# mockups.
|
|
35
|
+
#
|
|
36
|
+
# mock - Returns a static reponse.
|
|
37
|
+
# echo - Returns the arguments passed-in.
|
|
38
|
+
# spin - Returns a rotation of responses.
|
|
39
|
+
# keys - Returns an index of responses.
|
|
40
|
+
#
|
|
41
|
+
# Mock classes can be built from sratch or partially framed
|
|
42
|
+
# against other classes.
|
|
43
|
+
#
|
|
44
|
+
# === Usage
|
|
45
|
+
#
|
|
46
|
+
# class ContextMock < Mock
|
|
47
|
+
# mock :response_headers, {}
|
|
48
|
+
# spin :host_url, ['http://www.nitrohq.com','http://www.rubyforge.com']
|
|
49
|
+
# end
|
|
50
|
+
#
|
|
51
|
+
# ctx = ContextMock.new
|
|
52
|
+
# ctx.response_headers['location'] = url
|
|
53
|
+
# ctx.host_url #=> "http://www.nitrohq.com"
|
|
54
|
+
# ctx.host_url #=> "http://www.rubyforge.com"
|
|
55
|
+
#
|
|
56
|
+
# Or
|
|
57
|
+
#
|
|
58
|
+
# class ContextMock < Mock(Context)
|
|
59
|
+
# ...
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
class Object < OpenStruct
|
|
63
|
+
|
|
64
|
+
# include these?
|
|
65
|
+
#include Test::Unit::Assertions
|
|
66
|
+
|
|
67
|
+
# Certain methods are not mocked:
|
|
68
|
+
# inspect (tricky)
|
|
69
|
+
# class (delegated)
|
|
70
|
+
# kind_of? (delegated)
|
|
71
|
+
# is_a? (delegated)
|
|
72
|
+
# instance_of? (delegated)
|
|
73
|
+
# method (works as-is)
|
|
74
|
+
# send (works as-is)
|
|
75
|
+
# respond_to? (works as-is)
|
|
76
|
+
# hash (no way to mock)
|
|
77
|
+
#
|
|
78
|
+
# __id__, __call__, etc. (not meant to be mocked, ever!)
|
|
79
|
+
#
|
|
80
|
+
|
|
81
|
+
UnmockedMethods = %r{^(
|
|
82
|
+
|inspect
|
|
83
|
+
|kind_of\?|is_a\?|instance_of\?|class
|
|
84
|
+
|method|send|respond_to\?
|
|
85
|
+
|hash
|
|
86
|
+
|__
|
|
87
|
+
)}x
|
|
88
|
+
|
|
89
|
+
class << self
|
|
90
|
+
|
|
91
|
+
attr :mocked_class
|
|
92
|
+
|
|
93
|
+
def mocks
|
|
94
|
+
self.methods(false)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# Mock a static repsonse.
|
|
98
|
+
def mock( sym, val )
|
|
99
|
+
define_method( sym ) { |*args| val }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Responds with input.
|
|
103
|
+
def echo( sym )
|
|
104
|
+
define_method( sym ) { |*args| args }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Reponds with a rotation of reponses.
|
|
108
|
+
def spin( sym, arr )
|
|
109
|
+
define_method( sym ) { |*args| arr.push(arr.shift) ; arr[-1] }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Responds according to a mapping of input parameters.
|
|
113
|
+
def keys( sym, hsh )
|
|
114
|
+
define_method( sym ) { |*args| hsh[args] }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Delegate methods: #class, instance_of?, kind_of?, and is_a?
|
|
120
|
+
|
|
121
|
+
alias :__class :class
|
|
122
|
+
|
|
123
|
+
def class # :nodoc:
|
|
124
|
+
return __class.mocked_class
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def instance_of?( klass ) # :nodoc:
|
|
128
|
+
self.class == klass
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def kind_of?( klass ) # :nodoc:
|
|
132
|
+
self.class <= klass
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
alias_method :is_a?, :kind_of?
|
|
136
|
+
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# TODO
|
|
145
|
+
|
|
146
|
+
=begin #test
|
|
147
|
+
|
|
148
|
+
class MyMock < Mock::Object
|
|
149
|
+
mock :m, 10
|
|
150
|
+
echo :e
|
|
151
|
+
spin :s, [1,2,3]
|
|
152
|
+
keys :i, { [:foo] => 'Hello', [:boo] => 'Frog' }
|
|
153
|
+
|
|
154
|
+
def a(k) k+1 end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
my = MyMock.new
|
|
158
|
+
|
|
159
|
+
p my.m
|
|
160
|
+
p my.e('hi')
|
|
161
|
+
p my.s
|
|
162
|
+
p my.s
|
|
163
|
+
p my.s
|
|
164
|
+
p my.i(:foo)
|
|
165
|
+
p my.i(:boo)
|
|
166
|
+
p my.a(1)
|
|
167
|
+
|
|
168
|
+
=end
|
|
169
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# = mock.rb
|
|
2
|
+
#
|
|
3
|
+
# == Copyright (c) 2005 George Moschovitis
|
|
4
|
+
#
|
|
5
|
+
# Ruby License
|
|
6
|
+
#
|
|
7
|
+
# This module is free software. You may use, modify, and/or redistribute this
|
|
8
|
+
# software under the same terms as Ruby.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
12
|
+
# FOR A PARTICULAR PURPOSE.
|
|
13
|
+
#
|
|
14
|
+
# == Author(s)
|
|
15
|
+
#
|
|
16
|
+
# * George Moschovitis
|
|
17
|
+
|
|
18
|
+
require 'ostruct'
|
|
19
|
+
|
|
20
|
+
module Quarry
|
|
21
|
+
|
|
22
|
+
# Factory method for creating semi-functional mock object classes given the
|
|
23
|
+
# class which is to be mocked. It looks like a constant for purposes
|
|
24
|
+
# of syntactic sugar.
|
|
25
|
+
def Mockery( realclass )
|
|
26
|
+
|
|
27
|
+
mockclass = Class.new( Mock )
|
|
28
|
+
|
|
29
|
+
mockclass.instance_eval do @mocked_class = realclass end
|
|
30
|
+
|
|
31
|
+
# Provide an accessor to class instance var that holds the class
|
|
32
|
+
# object we're faking
|
|
33
|
+
class << mockclass
|
|
34
|
+
# The actual class being mocked
|
|
35
|
+
attr_reader :mocked_class
|
|
36
|
+
|
|
37
|
+
# Propagate the mocked class ivar to derivatives so it can be
|
|
38
|
+
# called like:
|
|
39
|
+
# class MockFoo < Mock( RealClass )
|
|
40
|
+
def inherited( subclass )
|
|
41
|
+
mc = self.mockedClass
|
|
42
|
+
subclass.instance_eval do @mocked_class = mc end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Build method definitions for all the mocked class's instance
|
|
47
|
+
# methods, as well as those given to it by its superclasses, since
|
|
48
|
+
# we're not really inheriting from it.
|
|
49
|
+
imethods = realclass.instance_methods(true).collect do |name|
|
|
50
|
+
next if name =~ ::Mock::UnmockedMethods
|
|
51
|
+
|
|
52
|
+
# Figure out the argument list
|
|
53
|
+
arity = realclass.instance_method( name ).arity
|
|
54
|
+
optargs = false
|
|
55
|
+
|
|
56
|
+
if arity < 0
|
|
57
|
+
optargs = true
|
|
58
|
+
arity = (arity+1).abs
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
args = []
|
|
62
|
+
arity.times do |n| args << "arg#{n+1}" end
|
|
63
|
+
args << "*optargs" if optargs
|
|
64
|
+
|
|
65
|
+
# Build a method definition. Some methods need special
|
|
66
|
+
# declarations.
|
|
67
|
+
argsj = args.join(',')
|
|
68
|
+
case name.intern
|
|
69
|
+
when :initialize
|
|
70
|
+
"def initialize(#{argsj}) ; super ; end"
|
|
71
|
+
else
|
|
72
|
+
"def #{name}(#{argsj}) ; self.send(#{name},#{argsj}) ; end"
|
|
73
|
+
#"def %s( %s ) ; self.__mockRegisterCall(%s) ; end" %
|
|
74
|
+
# [ name, argstr, [":#{name}", *args].join(',') ]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Now add the instance methods to the mockclass class
|
|
79
|
+
mockclass.class_eval imethods.join( "\n" )
|
|
80
|
+
|
|
81
|
+
return mockclass
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
|