testability-driver 0.9.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_composition.rb +1 -1
  2. data/lib/tdriver/base/behaviour/behaviours/object_behaviour_description.rb +11 -7
  3. data/lib/tdriver/base/behaviour/behaviours/object_composition.rb +8 -0
  4. data/lib/tdriver/base/behaviour/factory.rb +229 -209
  5. data/lib/tdriver/base/errors.rb +3 -0
  6. data/lib/tdriver/base/state_object.rb +11 -20
  7. data/lib/tdriver/base/sut/controller.rb +4 -4
  8. data/lib/tdriver/base/sut/factory.rb +205 -170
  9. data/lib/tdriver/base/sut/generic/behaviours/application.rb +256 -174
  10. data/lib/tdriver/base/sut/generic/behaviours/find.rb +17 -11
  11. data/lib/tdriver/base/sut/generic/behaviours/flash_behaviour.rb +57 -66
  12. data/lib/tdriver/base/sut/generic/behaviours/sut.rb +578 -497
  13. data/lib/tdriver/base/sut/generic/behaviours/switchbox_behaviour.rb +41 -15
  14. data/lib/tdriver/base/sut/generic/behaviours/verification.rb +48 -19
  15. data/lib/tdriver/base/sut/generic/commands/fixture.rb +47 -0
  16. data/lib/tdriver/base/sut/generic/commands/key_sequence.rb +25 -13
  17. data/lib/tdriver/base/sut/generic/commands/screen_capture.rb +16 -10
  18. data/lib/tdriver/base/sut/generic/plugin.rb +9 -3
  19. data/lib/tdriver/base/sut/sut.rb +41 -33
  20. data/lib/tdriver/base/test_object/abstract.rb +26 -3
  21. data/lib/tdriver/base/test_object/adapter.rb +399 -0
  22. data/lib/tdriver/base/test_object/behaviours/syncronization.rb +56 -14
  23. data/lib/tdriver/base/test_object/behaviours/test_object.rb +663 -197
  24. data/lib/tdriver/base/test_object/cache.rb +132 -0
  25. data/lib/tdriver/base/test_object/factory.rb +677 -426
  26. data/lib/tdriver/base/test_object/factory_new.rb +202 -0
  27. data/lib/tdriver/base/test_object/identificator.rb +24 -17
  28. data/lib/tdriver/base/test_object/loader.rb +9 -3
  29. data/lib/tdriver/base/test_object/verification.rb +181 -0
  30. data/lib/tdriver/loader.rb +1 -1
  31. data/lib/tdriver/report/report.rb +2 -0
  32. data/lib/tdriver/report/report_api.rb +4 -4
  33. data/lib/tdriver/report/report_creator.rb +29 -3
  34. data/lib/tdriver/report/report_data_presentation.rb +7 -3
  35. data/lib/tdriver/report/report_execution_statistics.rb +80 -21
  36. data/lib/tdriver/report/report_javascript.rb +192 -0
  37. data/lib/tdriver/report/report_test_case_run.rb +22 -0
  38. data/lib/tdriver/report/report_test_run.rb +62 -55
  39. data/lib/tdriver/report/report_writer.rb +57 -56
  40. data/lib/tdriver/tdriver.rb +14 -41
  41. data/lib/tdriver/util/common/error.rb +1 -0
  42. data/lib/tdriver/util/common/exceptions.rb +12 -0
  43. data/lib/tdriver/util/common/file.rb +12 -6
  44. data/lib/tdriver/util/common/gem.rb +2 -1
  45. data/lib/tdriver/util/common/hash.rb +152 -0
  46. data/lib/tdriver/util/common/kernel.rb +49 -34
  47. data/lib/tdriver/util/common/loader.rb +21 -17
  48. data/lib/tdriver/util/common/numeric.rb +39 -0
  49. data/lib/tdriver/util/common/object.rb +115 -0
  50. data/lib/tdriver/util/common/string.rb +55 -2
  51. data/lib/tdriver/util/dbaccess/dbaccess.rb +194 -161
  52. data/lib/tdriver/util/dynamic_attribute_filter.rb +6 -0
  53. data/lib/tdriver/util/hooking.rb +2 -2
  54. data/lib/tdriver/util/loader.rb +2 -2
  55. data/lib/tdriver/util/localisation/localisation.rb +277 -18
  56. data/lib/tdriver/util/logger.rb +142 -13
  57. data/lib/tdriver/util/parameter/parameter_hash.rb +8 -5
  58. data/lib/tdriver/util/parameter/parameter_xml.rb +18 -2
  59. data/lib/tdriver/util/recorder.rb +17 -12
  60. data/lib/tdriver/util/user_data/user_data.rb +3 -2
  61. data/lib/tdriver/util/{video_rec.rb → video_utils.rb} +136 -16
  62. data/lib/tdriver/util/xml/abstraction.rb +7 -0
  63. data/lib/tdriver/util/xml/attribute.rb +32 -0
  64. data/lib/tdriver/util/xml/loader.rb +8 -2
  65. data/lib/tdriver/util/xml/nil_node.rb +95 -0
  66. data/lib/tdriver/util/xml/parsers/nokogiri/abstraction.rb +46 -7
  67. data/lib/tdriver/util/xml/parsers/nokogiri/attribute.rb +19 -9
  68. data/lib/tdriver/util/xml/parsers/nokogiri/document.rb +1 -1
  69. data/lib/tdriver/util/xml/parsers/nokogiri/element.rb +13 -1
  70. data/lib/tdriver/util/xml/parsers/nokogiri/loader.rb +6 -0
  71. data/lib/tdriver/util/xml/parsers/nokogiri/nodeset.rb +27 -15
  72. data/lib/tdriver/util/xml/parsers/nokogiri/text.rb +57 -0
  73. data/lib/tdriver/util/xml/text.rb +32 -0
  74. data/lib/tdriver/util/xml/xml.rb +35 -22
  75. data/lib/tdriver/version.rb +1 -1
  76. data/lib/tdriver-devtools/behaviour/xml/rdoc_behaviour_xml_generator.rb +41 -34
  77. data/lib/tdriver-devtools/doc/generate.rb +31 -6
  78. data/lib/tdriver-devtools/doc/xslt/template.xsl +46 -25
  79. data/lib/tdriver-devtools/tests/feature_tests/example/behaviour_example.rb +100 -0
  80. data/lib/tdriver-devtools/tests/feature_tests/update +1 -1
  81. data/lib/tdriver.rb +0 -3
  82. data/xml/behaviours/generic.xml +1 -1
  83. data/xml/defaults/generic.xml +4 -90
  84. data/xml/templates/generic.xml +33 -25
  85. metadata +21 -29
  86. data/lib/tdriver-devtools/behaviour/xml_generator/example/flick-example.rb +0 -245
  87. data/lib/tdriver-devtools/behaviour/xml_generator/example/sut.rb +0 -964
  88. data/lib/tdriver-devtools/behaviour/xml_generator/generate.rb +0 -68
  89. data/lib/tdriver-devtools/behaviour/xml_generator/lib/custom_rdoc_generator.rb +0 -1865
  90. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.default.template +0 -1
  91. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument.template +0 -3
  92. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.argument_type.template +0 -4
  93. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.exception.template +0 -4
  94. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.arguments.template +0 -4
  95. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.deprecated.template +0 -3
  96. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.exceptions.template +0 -3
  97. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.info.template +0 -1
  98. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.returns.template +0 -3
  99. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.tables.template +0 -3
  100. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.method.template +0 -12
  101. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.returns.template +0 -5
  102. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.item.template +0 -1
  103. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.row.template +0 -2
  104. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.table.template +0 -7
  105. data/lib/tdriver-devtools/behaviour/xml_generator/templates/behaviour.xml.template +0 -14
  106. data/lib/tdriver-devtools/behaviour/xml_generator/update +0 -3
  107. data/lib/tdriver-devtools/tests/feature_tests/example/flick-example.rb +0 -233
  108. data/lib/tdriver-devtools/tests/feature_tests/example/impl.rb +0 -194
@@ -1,3 +1,4 @@
1
+ ############################################################################
1
2
  ##
2
3
  ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3
4
  ## All rights reserved.
@@ -60,7 +61,9 @@ module MobyBase
60
61
  # === raises
61
62
  # nothing
62
63
  def eql?( other_test_object )
64
+
63
65
  self == other_test_object
66
+
64
67
  end
65
68
 
66
69
  # Function to verify is DATA of two TestObjects are the same,
@@ -85,7 +88,10 @@ module MobyBase
85
88
  #return true
86
89
 
87
90
  # optimized version
88
- other_test_object.instance_of?( MobyBase::TestObject ) && ( @type == other_test_object.type ) && ( @id == other_test_object.id ) && (@name == other_test_object.name )
91
+ other_test_object.instance_of?( MobyBase::TestObject ) &&
92
+ ( @type == other_test_object.type ) &&
93
+ ( @id == other_test_object.id ) &&
94
+ ( @name == other_test_object.name )
89
95
 
90
96
  end
91
97
 
@@ -97,6 +103,7 @@ module MobyBase
97
103
  # Fixnum:: hash number representing current TestObject
98
104
  def hash
99
105
 
106
+
100
107
  #result = 17
101
108
  #result = result * 37 + self.id.to_i
102
109
  #result = result * 37 + type.hash
@@ -104,7 +111,9 @@ module MobyBase
104
111
  #return result
105
112
 
106
113
  # optimized version
107
- ( ( ( 17 * 37 + @id.to_i ) * 37 + @type.hash ) * 37 + @name.hash )
114
+ #( ( ( 17 * 37 + @id.to_i ) * 37 + @type.hash ) * 37 + @name.hash )
115
+
116
+ TDriver::TestObjectAdapter.test_object_hash( @id.to_i, @type, @name )
108
117
 
109
118
  end
110
119
 
@@ -153,6 +162,13 @@ module MobyBase
153
162
 
154
163
  end
155
164
 
165
+ # TODO: document me
166
+ def inspect
167
+
168
+ "#<#{ self.class }:0x#{ ( "%x" % ( self.object_id.to_i << 1 ) )[ 3 .. -1 ] } @id=\"#{ @id }\" @name=\"#{ @name }\" @parent=#{ @parent.inspect } @sut=#{ @sut.inspect } @type=\"#{ @type }\" @x_path=\"#{ @x_path }\">"
169
+
170
+ end
171
+
156
172
  # Returns a XML node representing this test object.
157
173
  #
158
174
  # === returns
@@ -165,7 +181,14 @@ module MobyBase
165
181
 
166
182
  #Kernel::raise MobyBase::TestObjectNotFoundError.new( "The test object with id: \"#{ @id.to_s }\", type: \"#{ @type.to_s }\" and name: \"#{ @name.to_s }\" does not exist on sut \"#{ @sut.id.to_s }\" anymore" ) if ( elements = @sut.xml_data.xpath( @x_path ) ).size.zero?
167
183
 
168
- Kernel::raise MobyBase::TestObjectNotFoundError.new( 'The test object (id: "%s", type: "%s", name: "%s") does not exist on sut (%s) anymore' % [ @id, @type, @name, @sut.id ] ) if ( elements = @sut.xml_data.xpath( @x_path ) ).size.zero?
184
+ elements = @sut.xml_data.xpath( @x_path )
185
+
186
+ Kernel::raise MobyBase::TestObjectNotFoundError.new(
187
+
188
+ #'The test object (id: "%s", type: "%s", name: "%s") does not exist on sut (%s) anymore' % [ @id, @type, @name, @sut.id ]
189
+ "The test object (id: #{ @id.inspect }, type: #{ @type.inspect }, name: #{ @name.inspect }) does not exist on sut (#{ @sut.id.inspect }) anymore"
190
+
191
+ ) if elements.size.zero?
169
192
 
170
193
  elements.first
171
194
 
@@ -0,0 +1,399 @@
1
+ ############################################################################
2
+ ##
3
+ ## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4
+ ## All rights reserved.
5
+ ## Contact: Nokia Corporation (testabilitydriver@nokia.com)
6
+ ##
7
+ ## This file is part of Testability Driver.
8
+ ##
9
+ ## If you have questions regarding the use of this file, please contact
10
+ ## Nokia at testabilitydriver@nokia.com .
11
+ ##
12
+ ## This library is free software; you can redistribute it and/or
13
+ ## modify it under the terms of the GNU Lesser General Public
14
+ ## License version 2.1 as published by the Free Software Foundation
15
+ ## and appearing in the file LICENSE.LGPL included in the packaging
16
+ ## of this file.
17
+ ##
18
+ ############################################################################
19
+
20
+ module TDriver
21
+
22
+ class TestObjectAdapter
23
+
24
+ # private methods and variables
25
+ class << self
26
+
27
+ private
28
+
29
+ # special cases: allow partial match when value of type and attribute name matches
30
+ @@partial_match_allowed = [ 'list_item', 'text' ], ['application', 'fullname' ]
31
+
32
+ def xpath_attributes( attributes, element_attributes, object_type )
33
+
34
+ attributes = attributes.collect{ | key, values |
35
+
36
+ values = ( values.kind_of?( Array ) ? values : [ values ] ).collect{ | value |
37
+
38
+ # concatenate string if it contains single and double quotes, otherwise return as is
39
+ value = xpath_literal_string( value )
40
+
41
+ if @@partial_match_allowed.include?( [ object_type, key ] )
42
+
43
+ # partial match allowed
44
+ value = "[contains(.,#{ value })]"
45
+
46
+ else
47
+
48
+ # exact match required
49
+ value = "=#{ value }"
50
+
51
+ end
52
+
53
+ if element_attributes
54
+
55
+ prefix = "@#{key}#{value} or "
56
+
57
+ else
58
+
59
+ prefix = ""
60
+
61
+ end
62
+
63
+ "#{ prefix }attributes/attribute[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='#{key}' and .#{value}]"
64
+
65
+ }.join( " or " )
66
+
67
+ }
68
+
69
+ result = attributes.join(' and ')
70
+
71
+ if result.empty?
72
+
73
+ result = nil
74
+
75
+ else
76
+
77
+ result = "(#{ result })" if element_attributes
78
+
79
+ end
80
+
81
+ result
82
+
83
+ end
84
+
85
+
86
+ end
87
+
88
+ # TODO: document me
89
+ def self.xpath_to_object( rules, find_all_children )
90
+
91
+ # convert hash keys to downcased string
92
+ rules = Hash[ rules.collect{ | key, value | [ key.to_s.downcase, value ] } ]
93
+
94
+ test_object_identification_attributes_array = []
95
+
96
+ # store and remove object element attributes from hash
97
+ object_element_attributes = rules.delete_keys!( "name", "type", "parent", "id" )
98
+
99
+ # TODO: change "any" to "*"
100
+ # children method may request test objects of any type
101
+ if object_element_attributes[ "type" ] == 'any'
102
+
103
+ # test object with any name, type, parent and id is allowed
104
+ test_object_identification_attributes_array << '@*'
105
+
106
+ else
107
+
108
+ # required attributes
109
+ test_object_identification_attributes_array << xpath_attributes( object_element_attributes, true, object_element_attributes[ "type" ] )
110
+
111
+ end
112
+
113
+ # additional attributes, eg. :text, :x, :y etc.
114
+ test_object_identification_attributes_array << xpath_attributes( rules, false, object_element_attributes[ "type" ] )
115
+
116
+ # join required and additional attribute strings
117
+ test_object_identification_attributes = test_object_identification_attributes_array.compact.join(" and ")
118
+
119
+ find_all_children ? "*//object[#{ test_object_identification_attributes }]" : "objects[1]/object[#{ test_object_identification_attributes }]"
120
+
121
+ end
122
+
123
+ # TODO: document me
124
+ def self.xpath_literal_string( string )
125
+
126
+ # make sure that argument is type of string
127
+ string = string.to_s
128
+
129
+ # does not contain no single quotes
130
+ if not string.include?("'")
131
+
132
+ result = "'#{ string }'"
133
+
134
+ # does not contain no double quotes
135
+ elsif not string.include?('"')
136
+
137
+ result = "\"#{ string }\""
138
+
139
+ # contains single and double quotes
140
+ else
141
+
142
+ # open new item
143
+ result = ["'"]
144
+
145
+ # iterate through each character
146
+ string.each_char{ | char |
147
+
148
+ case char
149
+
150
+ # encapsulate single quotes with double quotes
151
+ when "'"
152
+
153
+ # close current item
154
+ result.last << char
155
+
156
+ # add encapsulated single quote
157
+ result << "\"'\""
158
+
159
+ # open new item
160
+ result << char
161
+
162
+ else
163
+
164
+ # any other character will appended as is
165
+ result.last << char
166
+
167
+ end
168
+
169
+ }
170
+
171
+ # close last sentence
172
+ result.last << "'"
173
+
174
+ # create concat clause for xpath
175
+ result = "concat(#{ result.join(',') })"
176
+
177
+ end
178
+
179
+ result
180
+
181
+ end
182
+
183
+ # TODO: document me
184
+ def self.get_objects( source_data, rules, find_all_children )
185
+
186
+ rule = xpath_to_object( rules, find_all_children )
187
+
188
+ [
189
+ # perform xpath to source xml data
190
+ source_data.xpath( rule ),
191
+ rule
192
+ ]
193
+
194
+ end
195
+
196
+ def self.test_object_hash( object_id, object_type, object_name )
197
+
198
+ ( ( ( 17 * 37 + object_id ) * 37 + object_type.hash ) * 37 + object_name.hash )
199
+
200
+ end
201
+
202
+ # Sort XML nodeset of test objects with layout direction
203
+ def self.sort_elements( nodeset, layout_direction = "LeftToRight" )
204
+
205
+ attribute_pattern = "./attributes/attribute[@name='%s']/value/text()"
206
+
207
+ # collect only nodes that has x_absolute and y_absolute attributes
208
+ nodeset.collect!{ | node |
209
+
210
+ #node unless node.at_xpath( attribute_pattern % 'x_absolute' ).to_s.empty? || node.at_xpath( attribute_pattern % 'y_absolute' ).to_s.empty?
211
+ node unless node.at_xpath( attribute_pattern % 'x_absolute' ).nil? || node.at_xpath( attribute_pattern % 'y_absolute' ).nil?
212
+
213
+ }.compact!.sort!{ | element_a, element_b |
214
+
215
+ element_a_x = element_a.at_xpath( attribute_pattern % 'x_absolute' ).content.to_i
216
+ element_a_y = element_a.at_xpath( attribute_pattern % 'y_absolute' ).content.to_i
217
+
218
+ element_b_x = element_b.at_xpath( attribute_pattern % 'x_absolute' ).content.to_i
219
+ element_b_y = element_b.at_xpath( attribute_pattern % 'y_absolute' ).content.to_i
220
+
221
+ case layout_direction
222
+
223
+ when "LeftToRight"
224
+
225
+ ( element_a_y == element_b_y ) ? ( element_a_x <=> element_b_x ) : ( element_a_y <=> element_b_y )
226
+
227
+ when "RightToLeft"
228
+
229
+ ( element_a_y == element_b_y ) ? ( element_b_x <=> element_a_x ) : ( element_a_y <=> element_b_y )
230
+
231
+ else
232
+
233
+ Kernel::raise ArgumentError.new( "Unsupported layout direction #{ layout_direction.inspect }" )
234
+
235
+ end
236
+
237
+ }
238
+
239
+ end
240
+
241
+ def self.parent_test_object_element( test_object )
242
+
243
+ # retrieve parent of current xml element; objects/object/objects/object/../..
244
+ test_object.xml_data.parent.parent
245
+
246
+ end
247
+
248
+ # TODO: document me
249
+ def self.test_object_element_attributes( source_data )
250
+
251
+ Hash[
252
+ source_data.attributes.collect{ | key, value |
253
+ [ key.to_s, value.to_s ]
254
+ }
255
+ ]
256
+
257
+ end
258
+
259
+ # TODO: document me
260
+ def self.test_object_element_attribute( source_data, name, &block )
261
+
262
+ result = source_data.attribute( name )
263
+
264
+ unless result
265
+
266
+ if block_given?
267
+
268
+ yield
269
+
270
+ else
271
+
272
+ # raise exception if no such attribute found
273
+ Kernel::raise MobyBase::AttributeNotFoundError.new(
274
+
275
+ "Could not find test object element attribute #{ attribute_name.inspect }"
276
+
277
+ )
278
+
279
+ end
280
+
281
+ else
282
+
283
+ result
284
+
285
+ end
286
+
287
+ end
288
+
289
+ # TODO: document me
290
+ def self.test_object_attribute( source_data, attribute_name, &block )
291
+
292
+ # TODO: consider using at_xpath and adding /value/text() to query string; however "downside" is that if multiple matches found only first value will be returned as result
293
+
294
+ # retrieve attribute(s) from xml
295
+ nodeset = source_data.xpath(
296
+
297
+ "attributes/attribute[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='#{ attribute_name.downcase }']" # /value/text()"
298
+
299
+ )
300
+
301
+ # if no attributes found call optional code block or raise exception
302
+ if nodeset.empty?
303
+
304
+ if block_given?
305
+
306
+ # pass return value of block as result
307
+ yield
308
+
309
+ else
310
+
311
+ # raise exception if no such attribute found
312
+ Kernel::raise MobyBase::AttributeNotFoundError.new(
313
+
314
+ "Could not find attribute #{ attribute_name.inspect }" # for test object of type #{ type.to_s }"
315
+
316
+ )
317
+
318
+ end
319
+
320
+ else
321
+
322
+ # attribute(s) found
323
+ # Need to disable this for now
324
+ # Kernel::raise MobyBase::MultipleAttributesFoundError.new( "Multiple attributes found with name '%s'" % name ) if nodeset.count > 1
325
+
326
+ # return found attribute
327
+ nodeset.first.content.strip
328
+
329
+ end
330
+
331
+ end
332
+
333
+ # TODO: document me
334
+ def self.test_object_attributes( source_data )
335
+
336
+ # return hash of test object attributes
337
+ Hash[
338
+
339
+ # iterate each attribute and collect name and value
340
+ source_data.xpath( 'attributes/attribute' ).collect{ | test_object |
341
+
342
+ [ test_object.attribute( 'name' ), test_object.at_xpath( 'value/text()' ).to_s ]
343
+
344
+ }
345
+
346
+ ]
347
+
348
+ end
349
+
350
+ # TODO: document me
351
+ def self.application_layout_direction( sut )
352
+
353
+ # temporary fix until testobject will be associated to parent application object
354
+ unless MobyUtil::DynamicAttributeFilter.instance.has_attribute?( 'layoutDirection' )
355
+
356
+ # temporary fix: add 'layoutDirection' to dynamic attributes filtering whitelist...
357
+ MobyUtil::DynamicAttributeFilter.instance.add_attribute( 'layoutDirection' )
358
+
359
+ # temporary fix: ... and refresh sut to retrieve updated xml data
360
+ sut.refresh
361
+
362
+ end
363
+
364
+ # TODO: parent application test object should be passed to get_test_objects; TestObjectAdapter#test_object_attribute( @app.xml_data, 'layoutDirection')
365
+ ( sut.xml_data.at_xpath('*//object[@type="application"]/attributes/attribute[@name="layoutDirection"]/value/text()').content || 'LeftToRight' ).to_s
366
+
367
+ end
368
+
369
+ # TODO: document me
370
+ def self.create_child_accessors!( source_data, test_object )
371
+
372
+ # iterate through each child object type attribute and create accessor method
373
+ source_data.xpath( 'objects/object/@type' ).each{ | object_type |
374
+
375
+ next if object_type.nil?
376
+
377
+ # convert attribute node value to string
378
+ object_type = object_type.content
379
+
380
+ # skip if child accessor is already created
381
+ next if test_object.respond_to?( object_type )
382
+
383
+ # create child accessor method to test object unless already exists
384
+ test_object.instance_eval(
385
+
386
+ "def #{object_type}(rules={}); raise TypeError,'parameter <rules> should be hash' unless rules.kind_of?(Hash); rules[:type]=:#{object_type}; child(rules); end;"
387
+
388
+ ) unless object_type.empty?
389
+
390
+ }
391
+
392
+ end
393
+
394
+ # enable hooking for performance measurement & debug logging
395
+ MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
396
+
397
+ end # TestObjectAdapter
398
+
399
+ end # TDriver