quarry 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/CHANGES +6 -0
  2. data/COPYING +344 -0
  3. data/MANIFEST +151 -0
  4. data/METADATA +22 -0
  5. data/NEWS +8 -0
  6. data/README +75 -0
  7. data/VERSION +1 -0
  8. data/bin/rubybreak +3 -0
  9. data/bin/xact-ruby +6 -0
  10. data/demo/spec/demo_check.rb +21 -0
  11. data/demo/spec/demo_outline.rb +25 -0
  12. data/demo/test/demo_run.rb +21 -0
  13. data/doc/manual.html2 +1416 -0
  14. data/doc/rdoc/classes/Assertion.html +101 -0
  15. data/doc/rdoc/classes/Assertion/False.html +132 -0
  16. data/doc/rdoc/classes/Assertion/True.html +137 -0
  17. data/doc/rdoc/classes/Kernel.html +86 -0
  18. data/doc/rdoc/classes/Method.html +137 -0
  19. data/doc/rdoc/classes/Module.html +165 -0
  20. data/doc/rdoc/classes/Object.html +154 -0
  21. data/doc/rdoc/classes/Quarry.html +177 -0
  22. data/doc/rdoc/classes/Quarry/Design.html +170 -0
  23. data/doc/rdoc/classes/Quarry/Design/Specification.html +265 -0
  24. data/doc/rdoc/classes/Quarry/Design/Specification/Context.html +174 -0
  25. data/doc/rdoc/classes/Quarry/MethodProbe.html +267 -0
  26. data/doc/rdoc/classes/Quarry/Mock.html +89 -0
  27. data/doc/rdoc/classes/Quarry/Mock/Object.html +276 -0
  28. data/doc/rdoc/created.rid +1 -0
  29. data/doc/rdoc/files/CHANGES.html +100 -0
  30. data/doc/rdoc/files/COPYING.html +457 -0
  31. data/doc/rdoc/files/MANIFEST.html +630 -0
  32. data/doc/rdoc/files/METADATA.html +92 -0
  33. data/doc/rdoc/files/NEWS.html +99 -0
  34. data/doc/rdoc/files/README.html +171 -0
  35. data/doc/rdoc/files/VERSION.html +96 -0
  36. data/doc/rdoc/files/bin/rubybreak.html +96 -0
  37. data/doc/rdoc/files/bin/xact-ruby.html +92 -0
  38. data/doc/rdoc/files/lib/quarry/assert/must_rb.html +96 -0
  39. data/doc/rdoc/files/lib/quarry/assert/should_rb.html +96 -0
  40. data/doc/rdoc/files/lib/quarry/assertion_rb.html +96 -0
  41. data/doc/rdoc/files/lib/quarry/breakout_rb.html +144 -0
  42. data/doc/rdoc/files/lib/quarry/design/spec_rb.html +100 -0
  43. data/doc/rdoc/files/lib/quarry/document_rb.html +92 -0
  44. data/doc/rdoc/files/lib/quarry/loadmonitor_rb.html +92 -0
  45. data/doc/rdoc/files/lib/quarry/methodprobe_rb.html +111 -0
  46. data/doc/rdoc/files/lib/quarry/mock/object_rb.html +123 -0
  47. data/doc/rdoc/files/lib/quarry/mockery_rb.html +115 -0
  48. data/doc/rdoc/fr_class_index.html +60 -0
  49. data/doc/rdoc/fr_file_index.html +65 -0
  50. data/doc/rdoc/fr_method_index.html +77 -0
  51. data/doc/rdoc/index.html +26 -0
  52. data/doc/rdoc/rdoc-style.css +175 -0
  53. data/doc/ri/Assertion/False/assert-i.yaml +10 -0
  54. data/doc/ri/Assertion/False/cdesc-False.yaml +19 -0
  55. data/doc/ri/Assertion/False/message-i.yaml +10 -0
  56. data/doc/ri/Assertion/True/assert-i.yaml +11 -0
  57. data/doc/ri/Assertion/True/cdesc-True.yaml +24 -0
  58. data/doc/ri/Assertion/True/message-c.yaml +11 -0
  59. data/doc/ri/Assertion/True/message-i.yaml +11 -0
  60. data/doc/ri/Assertion/True/method_missing-i.yaml +11 -0
  61. data/doc/ri/Assertion/True/new-c.yaml +11 -0
  62. data/doc/ri/Assertion/cdesc-Assertion.yaml +17 -0
  63. data/doc/ri/Kernel/cdesc-Kernel.yaml +15 -0
  64. data/doc/ri/Method/cdesc-Method.yaml +18 -0
  65. data/doc/ri/Method/migration-i.yaml +12 -0
  66. data/doc/ri/Method/signature-i.yaml +12 -0
  67. data/doc/ri/Module/cdesc-Module.yaml +21 -0
  68. data/doc/ri/Module/doc-i.yaml +16 -0
  69. data/doc/ri/Module/method_added-i.yaml +10 -0
  70. data/doc/ri/Object/assert%21-i.yaml +14 -0
  71. data/doc/ri/Object/assert-i.yaml +14 -0
  72. data/doc/ri/Object/cdesc-Object.yaml +20 -0
  73. data/doc/ri/Quarry/Design/Specification/Context/after-i.yaml +10 -0
  74. data/doc/ri/Quarry/Design/Specification/Context/before-i.yaml +10 -0
  75. data/doc/ri/Quarry/Design/Specification/Context/cdesc-Context.yaml +24 -0
  76. data/doc/ri/Quarry/Design/Specification/Context/method_missing-i.yaml +10 -0
  77. data/doc/ri/Quarry/Design/Specification/Context/specifications-i.yaml +10 -0
  78. data/doc/ri/Quarry/Design/Specification/cdesc-Specification.yaml +44 -0
  79. data/doc/ri/Quarry/Design/Specification/check-i.yaml +12 -0
  80. data/doc/ri/Quarry/Design/Specification/new-c.yaml +12 -0
  81. data/doc/ri/Quarry/Design/Specification/outline-i.yaml +12 -0
  82. data/doc/ri/Quarry/Design/cdesc-Design.yaml +22 -0
  83. data/doc/ri/Quarry/Design/check-c.yaml +12 -0
  84. data/doc/ri/Quarry/Design/outline-c.yaml +10 -0
  85. data/doc/ri/Quarry/Design/specification-c.yaml +10 -0
  86. data/doc/ri/Quarry/Design/specifications-c.yaml +10 -0
  87. data/doc/ri/Quarry/MethodProbe/cdesc-MethodProbe.yaml +46 -0
  88. data/doc/ri/Quarry/MethodProbe/duckcall-c.yaml +10 -0
  89. data/doc/ri/Quarry/MethodProbe/initialize_copy-i.yaml +10 -0
  90. data/doc/ri/Quarry/MethodProbe/method_missing-i.yaml +10 -0
  91. data/doc/ri/Quarry/MethodProbe/new-c.yaml +10 -0
  92. data/doc/ri/Quarry/Mock/Object/cdesc-Object.yaml +52 -0
  93. data/doc/ri/Quarry/Mock/Object/echo-c.yaml +12 -0
  94. data/doc/ri/Quarry/Mock/Object/keys-c.yaml +12 -0
  95. data/doc/ri/Quarry/Mock/Object/mock-c.yaml +12 -0
  96. data/doc/ri/Quarry/Mock/Object/mocks-c.yaml +10 -0
  97. data/doc/ri/Quarry/Mock/Object/spin-c.yaml +12 -0
  98. data/doc/ri/Quarry/Mock/cdesc-Mock.yaml +15 -0
  99. data/doc/ri/Quarry/Mockery-i.yaml +12 -0
  100. data/doc/ri/Quarry/cdesc-Quarry.yaml +17 -0
  101. data/doc/ri/created.rid +1 -0
  102. data/lib/quarry/assert/must.rb +8 -0
  103. data/lib/quarry/assert/should.rb +9 -0
  104. data/lib/quarry/assertion.rb +95 -0
  105. data/lib/quarry/breakout.rb +45 -0
  106. data/lib/quarry/design/spec.rb +197 -0
  107. data/lib/quarry/document.rb +35 -0
  108. data/lib/quarry/loadmonitor.rb +14 -0
  109. data/lib/quarry/methodprobe.rb +216 -0
  110. data/lib/quarry/mock/object.rb +169 -0
  111. data/lib/quarry/mockery.rb +85 -0
  112. 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,14 @@
1
+ BEGIN {
2
+ module Kernel
3
+ h = Hash.new
4
+ define_method(:requiree) do
5
+ h
6
+ end
7
+
8
+ r = method :require
9
+ define_method(:require) do |a|
10
+ r.call a
11
+ h[a] = caller
12
+ end
13
+ end
14
+ }
@@ -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
+