testability-driver 1.0.3 → 1.0.4

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.
Files changed (116) hide show
  1. data/lib/tdriver-devtools/behaviour/xml/rdoc_behaviour_xml_generator.rb +2 -2
  2. data/lib/tdriver-devtools/tdriver-devtools.rb +1 -1
  3. data/lib/tdriver-devtools/tests/feature_tests/lib/custom_rdoc_generator.rb +3 -3
  4. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_composition.rb +6 -1
  5. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_description.rb +5 -3
  6. data/lib/tdriver/base/behaviour/behaviours/object_composition.rb +1 -1
  7. data/lib/tdriver/base/behaviour/factory.rb +225 -225
  8. data/lib/tdriver/base/errors.rb +1 -1
  9. data/lib/tdriver/base/state_object.rb +227 -179
  10. data/lib/tdriver/base/sut/controller.rb +2 -2
  11. data/lib/tdriver/base/sut/factory.rb +190 -182
  12. data/lib/tdriver/base/sut/generic/behaviours/application.rb +69 -25
  13. data/lib/tdriver/base/sut/generic/behaviours/controller.rb +1 -1
  14. data/lib/tdriver/base/sut/generic/behaviours/find.rb +4 -4
  15. data/lib/tdriver/base/sut/generic/behaviours/flash_behaviour.rb +3 -3
  16. data/lib/tdriver/base/sut/generic/behaviours/sut.rb +350 -165
  17. data/lib/tdriver/base/sut/generic/behaviours/switchbox_behaviour.rb +9 -9
  18. data/lib/tdriver/base/sut/generic/behaviours/verification.rb +191 -103
  19. data/lib/tdriver/base/sut/generic/commands/application.rb +1 -1
  20. data/lib/tdriver/base/sut/generic/commands/key_sequence.rb +1 -1
  21. data/lib/tdriver/base/sut/generic/commands/screen_capture.rb +1 -1
  22. data/lib/tdriver/base/sut/generic/plugin.rb +1 -1
  23. data/lib/tdriver/base/sut/sut.rb +5 -1
  24. data/lib/tdriver/base/test_object/abstract.rb +136 -151
  25. data/lib/tdriver/base/test_object/adapter.rb +293 -82
  26. data/lib/tdriver/base/test_object/behaviours/syncronization.rb +20 -17
  27. data/lib/tdriver/base/test_object/behaviours/test_object.rb +159 -532
  28. data/lib/tdriver/base/test_object/cache.rb +1 -1
  29. data/lib/tdriver/base/test_object/factory.rb +254 -605
  30. data/lib/tdriver/base/test_object/identificator.rb +1 -1
  31. data/lib/tdriver/base/test_object/loader.rb +1 -1
  32. data/lib/tdriver/base/test_object/verification.rb +17 -17
  33. data/lib/tdriver/loader.rb +20 -9
  34. data/lib/tdriver/report/report.rb +5 -0
  35. data/lib/tdriver/report/report_creator.rb +2 -2
  36. data/lib/tdriver/report/report_cucumber_listener.rb +4 -4
  37. data/lib/tdriver/report/report_cucumber_reporter.rb +4 -4
  38. data/lib/tdriver/report/report_execution_statistics.rb +22 -22
  39. data/lib/tdriver/report/report_grouping.rb +2 -2
  40. data/lib/tdriver/report/report_javascript.rb +11 -4
  41. data/lib/tdriver/report/report_test_case_run.rb +2 -2
  42. data/lib/tdriver/report/report_test_run.rb +5 -5
  43. data/lib/tdriver/report/report_test_unit.rb +74 -26
  44. data/lib/tdriver/report/report_writer.rb +70 -13
  45. data/lib/tdriver/tdriver.rb +17 -8
  46. data/lib/tdriver/util/common/array.rb +1 -1
  47. data/lib/tdriver/util/common/crc16.rb +1 -1
  48. data/lib/tdriver/util/common/environment.rb +1 -1
  49. data/lib/tdriver/util/common/file.rb +18 -9
  50. data/lib/tdriver/util/common/gem.rb +1 -1
  51. data/lib/tdriver/util/common/hash.rb +21 -0
  52. data/lib/tdriver/util/common/kernel.rb +1 -1
  53. data/lib/tdriver/util/common/loader.rb +5 -2
  54. data/lib/tdriver/util/common/numeric.rb +54 -3
  55. data/lib/tdriver/util/common/retryable.rb +30 -12
  56. data/lib/tdriver/util/common/stackable.rb +185 -0
  57. data/lib/tdriver/util/common/string.rb +21 -5
  58. data/lib/tdriver/util/{dbaccess/dbaccess.rb → database/access.rb} +4 -1
  59. data/lib/tdriver/util/{dbaccess/dbconnection.rb → database/connection.rb} +3 -0
  60. data/lib/tdriver/util/{dbaccess → database}/error.rb +0 -1
  61. data/lib/tdriver/util/{dbaccess → database}/loader.rb +5 -6
  62. data/lib/tdriver/util/{dynamic_attribute_filter.rb → filters/dynamic_attributes.rb} +1 -1
  63. data/lib/tdriver/util/hooking/hooking.rb +477 -0
  64. data/lib/tdriver/util/loader.rb +35 -29
  65. data/lib/tdriver/util/localisation/error.rb +0 -1
  66. data/lib/tdriver/util/localisation/loader.rb +1 -4
  67. data/lib/tdriver/util/localisation/localisation.rb +30 -27
  68. data/lib/tdriver/util/{common.rb → logger/loader.rb} +2 -4
  69. data/lib/tdriver/util/logger/logger.rb +574 -0
  70. data/lib/tdriver/util/operator_data/loader.rb +4 -3
  71. data/lib/tdriver/util/operator_data/operator_data.rb +5 -5
  72. data/lib/tdriver/util/parameter/parameter.rb +7 -1
  73. data/lib/tdriver/util/parameter/parameter_hash.rb +1 -1
  74. data/lib/tdriver/util/parameter/parameter_template.rb +1 -1
  75. data/lib/tdriver/util/parameter/parameter_user_api.rb +28 -20
  76. data/lib/tdriver/util/parameter/parameter_xml.rb +1 -1
  77. data/lib/tdriver/util/plugin/abstract.rb +1 -1
  78. data/lib/tdriver/util/plugin/service.rb +1 -1
  79. data/lib/tdriver/util/{localisation.rb → recorder/loader.rb} +4 -3
  80. data/lib/tdriver/util/recorder/recorder.rb +66 -0
  81. data/lib/tdriver/util/recorder/scripter.rb +258 -0
  82. data/lib/tdriver/util/{stats.rb → statistics/statistics.rb} +7 -8
  83. data/lib/tdriver/util/user_data/error.rb +0 -1
  84. data/lib/tdriver/util/user_data/loader.rb +1 -2
  85. data/lib/tdriver/util/user_data/user_data.rb +6 -6
  86. data/lib/tdriver/util/video/camera.rb +67 -0
  87. data/lib/tdriver/util/video/camera_linux.rb +139 -0
  88. data/lib/tdriver/util/video/camera_windows.rb +174 -0
  89. data/lib/tdriver/util/video/loader.rb +31 -0
  90. data/lib/tdriver/util/video/video_utils.rb +139 -0
  91. data/lib/tdriver/util/xml/abstraction.rb +56 -5
  92. data/lib/tdriver/util/xml/builder.rb +2 -5
  93. data/lib/tdriver/util/{parameter.rb → xml/comment.rb} +10 -2
  94. data/lib/tdriver/util/xml/loader.rb +32 -22
  95. data/lib/tdriver/util/xml/nil_node.rb +2 -2
  96. data/lib/tdriver/util/xml/parsers/loader.rb +0 -1
  97. data/lib/tdriver/util/xml/parsers/nokogiri/abstraction.rb +18 -44
  98. data/lib/tdriver/util/xml/parsers/nokogiri/attribute.rb +9 -13
  99. data/lib/tdriver/util/xml/parsers/nokogiri/builder.rb +9 -3
  100. data/lib/tdriver/util/xml/parsers/nokogiri/comment.rb +39 -0
  101. data/lib/tdriver/util/xml/parsers/nokogiri/document.rb +6 -11
  102. data/lib/tdriver/util/xml/parsers/nokogiri/element.rb +2 -122
  103. data/lib/tdriver/util/xml/parsers/nokogiri/loader.rb +26 -16
  104. data/lib/tdriver/util/xml/parsers/nokogiri/node.rb +203 -0
  105. data/lib/tdriver/util/xml/parsers/nokogiri/nodeset.rb +1 -2
  106. data/lib/tdriver/util/xml/parsers/nokogiri/text.rb +2 -20
  107. data/lib/tdriver/util/xml/xml.rb +52 -20
  108. data/lib/tdriver/verify/verify.rb +238 -81
  109. data/xml/behaviours/generic.xml +12 -10
  110. metadata +156 -180
  111. data/lib/tdriver/base/test_object/factory_new.rb +0 -202
  112. data/lib/tdriver/util/hooking.rb +0 -434
  113. data/lib/tdriver/util/logger.rb +0 -506
  114. data/lib/tdriver/util/recorder.rb +0 -297
  115. data/lib/tdriver/util/video_utils.rb +0 -384
  116. data/lib/tdriver/util/xml/nil_element.rb +0 -89
@@ -53,7 +53,7 @@ module MobyBase
53
53
  end
54
54
 
55
55
  # enable hooking for performance measurement & debug logging
56
- MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
56
+ TDriver::Hooking.hook_methods( self ) if defined?( TDriver::Hooking )
57
57
 
58
58
  end
59
59
 
@@ -17,245 +17,293 @@
17
17
  ##
18
18
  ############################################################################
19
19
 
20
-
21
20
  module MobyBase
22
21
 
23
- # Static representation of the state of a TestObject or SUT.
24
- # StateObject are not refreshed or synchronize etc.
25
- class StateObject
22
+ # Static representation of the state of a TestObject or SUT.
23
+ # StateObject are not refreshed or synchronize etc.
24
+ class StateObject
26
25
 
27
- #include MobyBehaviour::TestObjectComposition
28
- include MobyBehaviour::ObjectComposition
26
+ include MobyBehaviour::ObjectComposition
29
27
 
30
- # The test object factory is needed for populating child object accessor methods
31
- #@test_object_factory
28
+ # The test object factory is needed for populating child object accessor methods
29
+ #@test_object_factory
32
30
 
33
- # == description
34
- # attr_accessor
35
- #
36
- # == returns
37
- # Test Object
38
- # description: test object that was used as parent when this object was created. Can also be of type SUT if sut was the parent (ie. application objects)
39
- # example: "@sut"
40
- attr_accessor :parent
31
+ # == description
32
+ # attr_accessor
33
+ #
34
+ # == returns
35
+ # Test Object
36
+ # description: test object that was used as parent when this object was created. Can also be of type SUT if sut was the parent (ie. application objects)
37
+ # example: "@sut"
38
+ attr_accessor :parent
41
39
 
42
- # Creates a new StateObject from XML source data.
43
- #
44
- # === params
45
- # xml_source:: MobyUtil::XML::Element or String. Contains the root element of this state.
46
- # parent:: TestObject, SUT or StateObject. Parent of this state object. Must be of type TestObjectComposition.
47
- # === returns
48
- # StateObject:: New StateObject
49
- def initialize( xml_source, parent = nil )
40
+ # TODO: document me
41
+ attr_reader :type, :name, :id
50
42
 
51
- xml_element = nil
43
+ # Creates a new StateObject from XML source data.
44
+ #
45
+ # === params
46
+ # xml_source:: MobyUtil::XML::Element or String. Contains the root element of this state.
47
+ # parent:: TestObject, SUT or StateObject. Parent of this state object. Must be of type TestObjectComposition.
48
+ # === returns
49
+ # StateObject:: New StateObject
50
+ def initialize( xml_source, parent = nil )
52
51
 
53
- if xml_source.kind_of?( MobyUtil::XML::Element )
52
+ xml_element = nil
54
53
 
55
- xml_element = xml_source
54
+ if xml_source.kind_of?( MobyUtil::XML::Element )
56
55
 
57
- elsif xml_source.kind_of?( String )
56
+ xml_element = xml_source
58
57
 
59
- xml_element = MobyUtil::XML.parse_string(xml_source).root
58
+ elsif xml_source.kind_of?( String )
60
59
 
61
- else
60
+ xml_element = MobyUtil::XML.parse_string(xml_source).root
62
61
 
63
- Kernel::raise ArgumentError.new("The XML source must be a String or MobyUtil::XML::Element, it was of type '#{ xml_source.class.to_s }'.")
62
+ else
64
63
 
65
- end
64
+ Kernel::raise ArgumentError, "The XML source must be a String or MobyUtil::XML::Element, it was of type '#{ xml_source.class.to_s }'"
66
65
 
67
- #@parent = nil
68
- #add_parent( parent ) unless parent.nil?
69
- #@parent = parent unless parent.nil?
66
+ end
70
67
 
71
68
  @parent = parent
72
69
 
73
- self.xml_data= xml_element
70
+ method(:xml_data=).call( xml_element )
74
71
 
75
72
  @child_object_cache = TDriver::TestObjectCache.new
76
73
 
77
- # Create accessor methods for any child state objects.
74
+ # Create accessor methods for any child state objects.
78
75
  TDriver::TestObjectAdapter.create_child_accessors!( xml_element, self )
79
76
 
80
- end
81
-
82
- # Tries to use the missing method id as a child object type and find an object based on it
83
- def method_missing( method_id, *method_arguments )
84
-
85
- hash_rule = method_arguments.first
86
-
87
- hash_rule = Hash.new unless hash_rule.kind_of? Hash
88
-
89
- hash_rule[ :type ] = method_id
90
-
91
- begin
92
-
93
- return child( hash_rule )
94
-
95
- rescue MobyBase::TestObjectNotFoundError, MobyBase::TestObjectNotVisibleError
96
-
97
- hash_rule.delete(:type)
98
-
99
- raise MobyBase::TestObjectNotFoundError.new(
100
- "The state object with id: \"#{ self.id.to_s }\", type: \"#{ self.type.to_s }\" and name: \"#{ self.name.to_s }\" has no child object of type \"#{ method_id.inspect.to_s }\"" <<
101
- ( hash_rule.empty? ? "" : " attributes: #{ hash_rule.inspect },"))
102
- end
103
-
104
- end
105
-
106
-
107
- # Check to StateObject objects for equality (ie. contents, not if they are the same object).
108
- # === param
109
- # other_state_object:: StateObject this object is compared to.
110
- # === returns
111
- # true:: other_state_object is equal to this StateObject.
112
- # false:: other_state_object is not equal to this StateObject.
113
- def eql? (other_state_object)
114
- self == other_state_object
115
- end
77
+ end
78
+
79
+ # Tries to use the missing method id as a child object type and find an object based on it
80
+ def method_missing( method_id, *method_arguments )
81
+
82
+ rules_hash = method_arguments.first
83
+
84
+ rules_hash = Hash.new unless rules_hash.kind_of? Hash
85
+
86
+ rules_hash[ :type ] = method_id
87
+
88
+ begin
89
+
90
+ return child( rules_hash )
91
+
92
+ rescue MobyBase::TestObjectNotFoundError, MobyBase::TestObjectNotVisibleError
93
+
94
+ rules_hash_clone = rules_hash.clone
95
+
96
+ rules_hash_clone.delete( :type )
97
+
98
+ # string representation of used rule hash
99
+ search_attributes_string = rules_hash_clone.collect{ | key, value | ":#{ key } => #{ value.inspect }" }.join( ', ')
100
+
101
+ # construct literal representation of object identifiers
102
+ object_attributes = []
103
+ object_attributes << "id: #{ @id }" if @id
104
+ object_attributes << "type: #{ @type.inspect }" if @type
105
+ object_attributes << "name: #{ @name.inspect }" if @name
106
+
107
+ if search_attributes_string.empty?
108
+
109
+ # do not show any attribute details if none given
110
+ search_attributes_string = ""
111
+
112
+ else
113
+
114
+ # show used attributes
115
+ search_attributes_string = " (attributes #{ search_attributes_string })"
116
+
117
+ end
118
+
119
+ # raise exception
120
+ Kernel::raise MobyBase::TestObjectNotFoundError.new(
121
+ "The state object (#{ object_attributes.join(", ") }) has no child object with type or behaviour method with name #{ method_id.to_s.inspect }#{ search_attributes_string }"
122
+ )
123
+
124
+ end
125
+
126
+ end
127
+
128
+ # Verifies that another StateObject contains the same data as this object.
129
+ # type, id and name must match.
130
+ #
131
+ # == param
132
+ # other_state_object:: StateObject that this object is compared to.
133
+ # == returns
134
+ # true:: The other StateObject contains the same data as this one.
135
+ # false:: The other StateObject does notcontain the same data as this one.
136
+ # == raises
137
+ # nothing
138
+ def ==( test_object )
139
+
140
+ # optimized version
141
+ test_object.instance_of?( MobyBase::StateObject ) && ( @type == test_object.type ) && ( @id == test_object.id ) && ( @name == test_object.name )
142
+
143
+ end
144
+
145
+ # Check to StateObject objects for equality (ie. contents, not if they are the same object).
146
+ # === param
147
+ # other_state_object:: StateObject this object is compared to.
148
+ # === returns
149
+ # true:: other_state_object is equal to this StateObject.
150
+ # false:: other_state_object is not equal to this StateObject.
151
+ def eql? (other_state_object)
116
152
 
153
+ self == other_state_object
117
154
 
118
- # Verifies that another StateObject contains the same data as this object.
119
- # type, id and name must match.
120
- #
121
- # == param
122
- # other_state_object:: StateObject that this object is compared to.
123
- # == returns
124
- # true:: The other StateObject contains the same data as this one.
125
- # false:: The other StateObject does notcontain the same data as this one.
126
- # == raises
127
- # nothing
128
- def == (other_state_object)
129
- return false unless other_state_object.instance_of?( MobyBase::StateObject )
130
- return false unless self.type == other_state_object.type
131
- return false unless self.id == other_state_object.id
132
- return false unless self.name == other_state_object.name
133
- return true
134
- end
155
+ end
135
156
 
136
157
 
137
- # Function to return type of the state object
138
- # === returns
139
- # type:: String value of the type
140
- def type()
141
- @type
142
- end
158
+ # Sets the XML content of this state object. Also sets identification attributes based
159
+ # on the contents of the XML.
160
+ #
161
+ # === params
162
+ # xml_object:: MobyUtil::XML::Element. State as XML.
163
+ def xml_data=( xml_object )
164
+
165
+ @_xml_data = xml_object
166
+
167
+ unused_xpath, @name, @type, @id = TDriver::TestObjectAdapter.get_test_object_identifiers( xml_object )
168
+
169
+ end
170
+
143
171
 
144
- # Function to return name of the state object
145
- # === returns
146
- # name String value of the name
147
- def name()
148
- @name
149
- end
172
+ # Returns a XML element representing this state object.
173
+ #
174
+ # === returns
175
+ # MobyUtil::XML::Element:: XML representation of this state object
176
+ def xml_data
150
177
 
151
- # Function to return id of the state object
152
- # === returns
153
- # id String value of the id
154
- def id()
155
- @object_id
156
- end
178
+ @_xml_data
157
179
 
158
- # Sets the XML content of this state object. Also sets identification attributes based
159
- # on the contents of the XML.
160
- #
161
- # === params
162
- # xml_object:: MobyUtil::XML::Element. State as XML.
163
- def xml_data=( xml_object )
164
- @_xml_data = xml_object
165
- @name = xml_object.attribute( 'name' )
166
- @type = xml_object.attribute( 'type' )
167
- @object_id = xml_object.attribute( 'id' )
168
- end
180
+ end
169
181
 
170
- # Returns a XML element representing this state object.
171
- #
172
- # === returns
173
- # MobyUtil::XML::Element:: XML representation of this state object
174
- def xml_data()
182
+ # Function provides access to parameters of the state object
183
+ # === params
184
+ # name:: String defining the name of the attribute to get
185
+ # === returns
186
+ # String:: Value of the attribute as a string
187
+ # === raises
188
+ # ArgumentError:: name is not a String.
189
+ # AttributeNotFoundError:: if the requested attribute can not be found in the xml data of the object
190
+ def attribute( name )
175
191
 
176
- @_xml_data
192
+ # check argument variable type
193
+ name.check_type( String, "wrong argument type $1 for attribute name (expected $2)" )
194
+
195
+ begin
196
+
197
+ # retrieve attribute(s) from test object; never access ui state xml data directly from behaviour implementation
198
+ TDriver::TestObjectAdapter.test_object_attribute( @_xml_data, name.to_s )
199
+
200
+ rescue MobyBase::AttributeNotFoundError
201
+
202
+ raise MobyBase::AttributeNotFoundError, "Could not find attribute '#{ name.to_s }' for state object of type '#{ type.to_s }'"
203
+
204
+ end
205
+
206
+ end
177
207
 
178
- end
208
+ def get_cached_test_object!( object )
179
209
 
180
- # Function provides access to parameters of the state object
181
- # === params
182
- # name:: String defining the name of the attribute to get
183
- # === returns
184
- # String:: Value of the attribute as a string
185
- # === raises
186
- # ArgumentError:: name is not a String.
187
- # AttributeNotFoundError:: if the requested attribute can not be found in the xml data of the object
188
- def attribute( name )
210
+ if @child_object_cache.has_object?( object )
189
211
 
190
- # store xml_data to temp. variable
191
- _xml_data = @_xml_data
212
+ object = @child_object_cache[ object ]
192
213
 
193
- Kernel::raise ArgumentError.new( "Wrong argument type %s for attribute argument (expected String)" % name.class ) unless name.class == String
214
+ true
194
215
 
195
- Kernel::raise MobyBase::AttributeNotFoundError.new("Could not find attribute '#{ name.to_s }' for state object of type '#{ type.to_s }'.") if (
196
- elements = _xml_data.xpath(
197
- "attributes/attribute[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='#{ name.to_s.downcase }']"
198
- )
199
- ).size == 0
216
+ else
200
217
 
201
- elements.first.content.strip
218
+ false
202
219
 
203
- end
220
+ end
204
221
 
205
- def get_cached_test_object!( object )
222
+ end
206
223
 
207
- if @child_object_cache.has_object?( object )
224
+ # Creates a state object for a child object of this state object
225
+ # Associates child object as current object's child.
226
+ # and associates self as child object's parent.
227
+ #
228
+ # NOTE:
229
+ # Subsequent calls to #child always returns reference to same child
230
+ # === params
231
+ # attributes:: Hash object holding information for identifying which child to create, eg. :type => :slider
232
+ # === returns
233
+ # StateObject:: new child state object or reference to existing child
234
+ def child( attributes )
208
235
 
209
- object = @child_object_cache[ object ]
236
+ get_objects( attributes, false )
210
237
 
211
- true
238
+ end
212
239
 
213
- else
240
+ # TODO: document me
241
+ def children( attributes )
214
242
 
215
- false
243
+ get_objects( attributes, true )
244
+
245
+ end
246
+
247
+ # TODO: document me
248
+ def inspect
216
249
 
217
- end
250
+ "#<#{ self.class }:0x#{ ( "%x" % ( self.object_id.to_i << 1 ) )[ 3 .. -1 ] } @id=#{ @id.inspect } @type=\"#{ @type }\" @name=\"#{ @name }\">"
218
251
 
219
- end
252
+ end
220
253
 
221
- # Creates a state object for a child object of this state object
222
- # Associates child object as current object's child.
223
- # and associates self as child object's parent.
224
- #
225
- # NOTE:
226
- # Subsequent calls to #child always returns reference to same child
227
- # === params
228
- # attributes:: Hash object holding information for identifying which child to create, eg. :type => :slider
229
- # === returns
230
- # StateObject:: new child state object or reference to existing child
231
- def child( attributes )
254
+ private
255
+
256
+ def get_objects( attributes, multiple_objects )
257
+
258
+ rules = attributes.clone
232
259
 
233
- identified_object_xml = MobyBase::TestObjectIdentificator.new( attributes ).find_object_data( @_xml_data )
260
+ # strip dynamic attributes from rules hash
261
+ dynamic_attributes = rules.strip_dynamic_attributes!
234
262
 
235
- child_object = StateObject.new( identified_object_xml, self )
263
+ # retrieve application object from sut.xml_data
264
+ matches, unused_rule = TDriver::TestObjectAdapter.get_objects( @_xml_data, rules, true )
236
265
 
237
- # use cached test object if once already retrieved
238
- get_cached_test_object!( child_object ).tap{ | found_in_cache |
266
+ if matches.count == 0
239
267
 
240
- # add child to objects cache
241
- @child_object_cache.add_object( child_object ) unless found_in_cache
268
+ # raise exception if no matches found
269
+ raise MobyBase::TestObjectNotFoundError
242
270
 
243
- }
271
+ elsif matches.count > 1 and multiple_objects == false and dynamic_attributes.has_key?( :__index ) == false
244
272
 
245
- child_object
273
+ # raise exception if multiple maches found
274
+ raise MobyBase::MultipleTestObjectsIdentifiedError, "Multiple objects found with attributes #{ attributes.inspect }"
246
275
 
247
- end
276
+ end
248
277
 
249
- def inspect
278
+ # fetch matches, use index if given
279
+ matches = [ matches[ dynamic_attributes[ :__index ] || 0 ] ] unless multiple_objects
280
+
281
+ # create state objects
282
+ matches = matches.collect{ | object_xml |
283
+
284
+ result = StateObject.new( object_xml, self )
285
+
286
+ # use cached state object if once already retrieved
287
+ get_cached_test_object!( result ).tap{ | found_in_cache |
250
288
 
251
- "#{ self.to_s }\nName: #{ self.name.to_s } Type: #{ self.type.to_s } Id: #{ self.id.to_s }"
289
+ # add child to objects cache
290
+ @child_object_cache.add_object( result ) unless found_in_cache
252
291
 
253
- end
292
+ }
293
+
294
+ # pass result object to array
295
+ result
296
+
297
+ }
254
298
 
255
- # enable hooking for performance measurement & debug logging
256
- MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
299
+ # return results
300
+ multiple_objects ? matches : matches.first
301
+
302
+ end
257
303
 
304
+ # enable hooking for performance measurement & debug logging
305
+ TDriver::Hooking.hook_methods( self ) if defined?( TDriver::Hooking )
258
306
 
259
- end # StateObject
307
+ end # StateObject
260
308
 
261
309
  end # MobyBase