testability-driver 0.9.2 → 1.0.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.
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
@@ -0,0 +1,132 @@
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
+ # TODO: document me
21
+ module TDriver
22
+
23
+ # TODO: document me
24
+ class TestObjectCache
25
+
26
+ # TODO: document me
27
+ def initialize()
28
+
29
+ @objects = {}
30
+
31
+ end
32
+
33
+ # TODO: document me
34
+ def each_object( &block )
35
+
36
+ @objects.each_value{ | object | yield( object ) }
37
+
38
+ end
39
+
40
+ # TODO: document me
41
+ def objects
42
+
43
+ @objects
44
+
45
+ end
46
+
47
+ # TODO: document me
48
+ def has_object?( test_object )
49
+
50
+ if test_object.kind_of?( Numeric )
51
+
52
+ @objects.has_key?( test_object )
53
+
54
+ else
55
+
56
+ @objects.has_key?( test_object.hash )
57
+
58
+ end
59
+
60
+
61
+ end
62
+
63
+ # TODO: document me
64
+ def object_keys
65
+
66
+ @objects.keys
67
+
68
+ end
69
+
70
+ # TODO: document me
71
+ def object_values
72
+
73
+ @objects.values
74
+
75
+ end
76
+
77
+ # TODO: document me
78
+ def []( value )
79
+
80
+ if value.kind_of?( Numeric )
81
+
82
+ @objects.fetch( value ){ raise ArgumentError, "Test object (#{ value }) not found from cache" }
83
+
84
+ else
85
+
86
+ @objects.fetch( value.hash ){ raise ArgumentError, "Test object (#{ value.hash }) not found from cache" }
87
+
88
+ end
89
+
90
+ end
91
+
92
+ # TODO: document me
93
+ def add_object( test_object )
94
+
95
+ test_object_hash = test_object.hash
96
+
97
+ if @objects.has_key?( test_object_hash )
98
+ warn( "Warning: Test object (#{ test_object_hash }) already exists in cache" )
99
+ end
100
+
101
+ @objects[ test_object_hash ] = test_object
102
+
103
+ test_object
104
+
105
+ end
106
+
107
+ # TODO: document me
108
+ def remove_object( test_object )
109
+
110
+ test_object_hash = test_object.hash
111
+
112
+ raise ArgumentError, "Test object (#{ value.hash }) not found from cache" unless @objects.has_key?( test_object_hash )
113
+
114
+ @objects.delete( test_object_hash )
115
+
116
+ self
117
+
118
+ end
119
+
120
+ # TODO: document me
121
+ def remove_objects
122
+
123
+ @objects.clear
124
+
125
+ end
126
+
127
+ # enable hooking for performance measurement & debug logging
128
+ MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
129
+
130
+ end # TestObjectCache
131
+
132
+ end # TDriver
@@ -16,603 +16,854 @@
16
16
  ## of this file.
17
17
  ##
18
18
  ############################################################################
19
+ module TDriver
19
20
 
20
- module MobyBase
21
-
22
- # class to represent TestObjectFactory.
23
- #
24
- # when a SUT asks for factory to create test objects, it shall give reference to the SUT so that
25
- # factory can make a call back for SUT object dump (in xml)
26
21
  class TestObjectFactory
27
22
 
28
- include Singleton
23
+ attr_reader :test_object_adapter, :timeout, :retry_interval
24
+
25
+ # TODO: move to test object adapter
26
+ # TODO: This method should be in application test object
27
+ def get_layout_direction( sut )
29
28
 
30
- attr_reader :timeout
29
+ sut.xml_data.at_xpath('*//object[@type="application"]/attributes/attribute[@name="layoutDirection"]/value/text()').to_s || 'LeftToRight'
31
30
 
32
- # TODO: Document me (TestObjectFactory::check_verify_always_reporting_settings)
33
- def check_verify_always_reporting_settings()
34
- @reporter_attached = MobyUtil::Parameter[ :report_attach_continuous_verification_to_reporter, 'false' ]
31
+ end
35
32
 
36
- @rcv_raise_errors = MobyUtil::Parameter[ :report_continuous_verification_raise_errors, 'true' ]
33
+ def initialize( options )
37
34
 
38
- @rcv_fail_test_case = MobyUtil::Parameter[ :report_continuous_verification_fail_test_case_on_error, 'true' ]
35
+ @test_object_adapter = options[ :test_object_adapter ]
39
36
 
40
- @rvc_capture_screen = MobyUtil::Parameter[ :report_continuous_verification_capture_screen_on_error, 'true' ]
37
+ @timeout = options[ :timeout ] || MobyUtil::Parameter[ :application_synchronization_timeout, "20" ].to_i
38
+
39
+ @retry_interval = options[ :retry_interval ] || MobyUtil::Parameter[ :application_synchronization_retry_interval, "1" ].to_i
40
+
41
41
  end
42
42
 
43
- # TODO: Document me (TestObjectFactory::restore_verify_always_reporting_settings)
44
- def restore_global_verify_always_reporting_settings()
45
- @reporter_attached = @global_reporter_attached
43
+ # Function to set timeout for TestObjectFactory
44
+ # This should be used only in unit testing, otherwise should not be used
45
+ # sets timeout used in identifying TestObjects to new timeout
46
+ #
47
+ # == params
48
+ # new_timeout:: Fixnum which defines the new timeout
49
+ # == raises
50
+ # ArgumentError:: if parameter is not kind of Fixnum
51
+ def timeout=( value )
46
52
 
47
- @rcv_raise_errors = @rcv_global_raise_errors
53
+ value.check_type( Numeric, "Wrong argument type $1 for timeout value (expected $2)" )
48
54
 
49
- @rcv_fail_test_case = @rcv_global_fail_test_case
55
+ @timeout = value
50
56
 
51
- @rvc_capture_screen = @rvc_global_capture_screen
52
57
  end
53
58
 
54
- # TODO: Document me (TestObjectFactory::initialize)
55
- def initialize
59
+ def retry_interval=( value )
56
60
 
57
- # TODO maybe set elsewhere used for defaults
58
- # TODO: Remove from here, to be initialized by the environment.
61
+ value.check_type( Numeric, "Wrong argument type $1 for timeout retry interval value (expected $2)" )
59
62
 
60
- reset_timeout
63
+ @retry_interval = value
61
64
 
62
- @global_reporter_attached = MobyUtil::Parameter[ :report_attach_continuous_verification_to_reporter, 'false' ]
65
+ end
63
66
 
64
- @rcv_global_raise_errors = MobyUtil::Parameter[ :report_continuous_verification_raise_errors, 'true' ]
67
+ # TODO: document me
68
+ def get_test_objects( rules )
65
69
 
66
- @rcv_global_fail_test_case = MobyUtil::Parameter[ :report_continuous_verification_fail_test_case_on_error, 'true' ]
70
+ # store rules hash to variable
71
+ object_attributes_hash = rules[ :object_attributes_hash ].clone
67
72
 
68
- @rvc_global_capture_screen = MobyUtil::Parameter[ :report_continuous_verification_capture_screen_on_error, 'true' ]
73
+ # remove test object identification directives for object identification attributes hash (e.g. :__index, :__multiple_objects etc.)
74
+ identification_directives = rules[ :identification_directives ]
75
+
76
+ #object_attributes_hash.strip_dynamic_attributes!
69
77
 
70
- @test_object_cache = {}
78
+ # get parent object
79
+ parent = rules[ :parent ]
80
+
81
+ # retrieve sut object
82
+ sut = parent.kind_of?( MobyBase::SUT ) ? parent : parent.sut
71
83
 
72
- @inside_verify = false
84
+ # create application refresh attributes hash
85
+ if object_attributes_hash[ :type ] == 'application'
73
86
 
74
- end
87
+ # collect :name, :id and :applicationUid from object_attributes_hash if found
88
+ refresh_arguments = object_attributes_hash.collect_keys( :name, :id, :applicationUid )
75
89
 
76
- #TODO: Team TE review @ Wheels
77
- # Function to set timeout for TestObjectFactory
78
- # This should be used only in unit testing, otherwise should not be used
79
- # sets timeout used in identifying TestObjects to new timeout
80
- #
81
- # == params
82
- # new_timeout:: Fixnum which defines the new timeout
83
- # == raises
84
- # ArgumentError:: if parameter is not kind of Fixnum
85
- def timeout=( value )
90
+ else
91
+
92
+ if parent.kind_of?( MobyBase::TestObject )
86
93
 
87
- Kernel::raise ArgumentError.new( "Value for timeout should be of numeric. It was %s" % [ value.class ] ) unless value.kind_of?( Numeric )
94
+ # get current application for test object
95
+ refresh_arguments = { :id => parent.get_application_id }
88
96
 
89
- @timeout = value
97
+ elsif parent.kind_of?( MobyBase::SUT )
98
+
99
+ # get current application for sut
100
+ refresh_arguments = { :id => sut.current_application_id }
90
101
 
91
- end
102
+ end
103
+
104
+ end
105
+
106
+ # set default values
107
+ identification_directives.default_values(
108
+
109
+ # associated sut
110
+ :__sut => sut,
111
+
112
+ # new child objects parent object
113
+ :__parent => parent,
114
+
115
+ # get timeout from rules hash or TestObjectFactory
116
+ :__timeout => @timeout,
117
+
118
+ # get retry interval from rules hash or TestObjectFactory
119
+ :__retry_interval => @retry_interval,
120
+
121
+ # determine that are we going to retrieve multiple test objects or just one
122
+ :__multiple_objects => false,
123
+
124
+ # determine that should all child objects childrens be retrieved
125
+ :__find_all_children => true,
126
+
127
+ # determine that did user give index value
128
+ :__index_given => identification_directives.has_key?( :__index ),
129
+
130
+ # determine index of test object to be retrieved
131
+ :__index => 0,
132
+
133
+ :__refresh_arguments => refresh_arguments,
134
+
135
+ # make search params
136
+ :__search_params => get_parent_params( parent ).push( make_object_search_params( object_attributes_hash ) ),
137
+
138
+ :__xy_sorting => false,
139
+
140
+ # test object identificator to be used
141
+ :__test_object_identificator => MobyBase::TestObjectIdentificator.new( object_attributes_hash )
142
+
143
+ )
144
+
145
+ identification_directives[ :__index ].check_type( Fixnum, "Wrong value type $1 for :__index test object identification directive (expected $2)" )
146
+
147
+ # add object identification attribute keys to dynamic attributes white list
148
+ MobyUtil::DynamicAttributeFilter.instance.add_attributes( object_attributes_hash.keys )
149
+
150
+ child_objects = identify_object( object_attributes_hash, identification_directives, rules ).collect{ | test_object_xml |
151
+
152
+ # create new test object
153
+ make_test_object(
154
+
155
+ # sut object to t_o
156
+ :sut => identification_directives[ :__sut ],
157
+
158
+ # parent object to t_o
159
+ :parent => identification_directives[ :__parent ],
160
+
161
+ # t_o xml
162
+ :xml_object => test_object_xml,
163
+
164
+ # test object factory
165
+ :test_object_factory => self,
166
+
167
+ :object_attributes_hash => object_attributes_hash
168
+
169
+ )
170
+
171
+ }
172
+
173
+ # return test object(s); either one or multiple objects
174
+ identification_directives[ :__multiple_objects ] ? child_objects : child_objects.first
92
175
 
93
- #TODO: Team TE review @ Engine
94
- # Function to reset timeout to default
95
- # This is needed, as TOFactory is singleton.
96
- # == params
97
- # --
98
- # == returns
99
- # --
100
- # == raises
101
- # --
102
- def reset_timeout()
176
+ end
103
177
 
104
- @timeout = MobyUtil::Parameter[ :application_synchronization_timeout, "20" ].to_i
178
+ # TODO: document me
179
+ def identify_object( object_attributes_hash, identification_directives, rules )
180
+
181
+ MobyUtil::Retryable.until(
105
182
 
106
- @_retry_interval = MobyUtil::Parameter[ :application_synchronization_retry_interval, "1" ].to_i
183
+ # maximum time used for retrying, if timeout exceeds pass last raised exception
184
+ :timeout => identification_directives[ :__timeout ],
107
185
 
108
- end
186
+ # interval used before retrying
187
+ :interval => identification_directives[ :__retry_interval ],
109
188
 
110
- #TODO: update documetation
111
- # Function to make a test object.
112
- # Queries from the sut an xml dump which is used to generate TestObjects.
113
- # Once XML dump is retrieved, a TestObject is identified by the TestObjectIdentificator.
114
- # TestObject is populated with data and activated.
115
- # The behaviour is added, as described in BehaviourGenerator#apply_behaviour
116
- # Lastly the created TestObject instance is associated to the SUT and vice versa.
117
- #
118
- # TODO: proper synchronization
119
- #
120
- # == params
121
- # sut:: SUT object with which the new test object is to be associated
122
- # test_object_identificator:: TestObjectIdentificator which is used to identify the required test object from the xml data
123
- # == returns
124
- # TestObject new, initialized and ready to use test object with associated data and behaviours
125
- # == raises, as defined in TestObjectIdentificator
126
- # ArgumentError:: if test_object_identificator is not of type LibXML::XML::Node,
127
- # MultipleTestObjectsIdentifiedError:: if multiple TestObjects can be identified using the test_object_identificator
128
- # TestObjectNotFoundError:: if no TestObjects are identified using the test_object_identificator
129
- def make( sut, test_object_identificator )
189
+ # following exceptions are allowed; Retry until timeout exceeds or other exception type is raised
190
+ :exception => [ MobyBase::TestObjectNotFoundError, MobyBase::MultipleTestObjectsIdentifiedError ]
130
191
 
131
- test_object = make_test_object(
132
- self,
133
- sut,
134
- sut,
135
- _make_xml( sut, test_object_identificator )
136
- )
192
+ ){
137
193
 
138
- sut.add_child( test_object )
194
+ # refresh sut
195
+ identification_directives[ :__sut ].refresh( identification_directives[ :__refresh_arguments ], identification_directives[ :__search_params ] )
139
196
 
140
- test_object
197
+ matches, rule = identification_directives[ :__test_object_identificator ].find_objects(
198
+ identification_directives[ :__parent ].xml_data,
199
+ identification_directives[ :__find_all_children ]
200
+ )
141
201
 
142
- end
202
+ # raise exception if no matching object(s) found
203
+ raise MobyBase::TestObjectNotFoundError.new(
204
+
205
+ "Cannot find object with rule:\n%s" % rules[ :object_attributes_hash ].inspect
143
206
 
144
- # Function for dynamically creating methods for accessing child objects of a test object
145
- # == params
146
- # test_object:: test_object where access methods should be added
147
- # == returns
148
- # test_object:: test_object with added access methods
149
- def create_child_accessors!( test_object )
207
+ ) if matches.empty?
150
208
 
151
- created_accessors = []
209
+ # raise exception if multiple matches found and only one expected
210
+ if ( !identification_directives[ :__multiple_objects ] ) && ( matches.count > 1 && !identification_directives[ :__index_given ] )
152
211
 
153
- test_object.xml_data.xpath( 'objects/object' ).each{ | objectElement |
212
+ # raise exception (with list of paths to all matching objects) if multiple objects flag is false and more than one match found
213
+ raise MobyBase::MultipleTestObjectsIdentifiedError.new(
214
+
215
+ "Multiple test objects found with rule: %s\nMatching objects:\n%s\n" % [
216
+ rules[ :object_attributes_hash ].inspect,
217
+ list_matching_test_objects( matches ).each_with_index.collect{ | object, object_index | "%3s) %s" % [ object_index + 1, object ] }.join( "\n" )
218
+ ]
219
+ )
220
+
221
+ end
154
222
 
155
- objectElement.attribute( "type" ).tap{ | objType |
223
+ # sort matches
224
+ if identification_directives[ :__xy_sorting ] == true
225
+
226
+ # sort elements
227
+ identification_directives[ :__test_object_identificator ].sort_elements_by_xy_layout!(
156
228
 
157
- unless created_accessors.include?( objType ) || objType.empty? then
229
+ matches,
158
230
 
159
- test_object.instance_eval(
231
+ get_layout_direction( identification_directives[ :__sut ] )
232
+
233
+ )
160
234
 
161
- "def %s( rules={} ); raise TypeError, 'parameter <rules> should be hash' unless rules.kind_of?( Hash ); rules[:type] = :%s; child( rules ); end;" % [ objType, objType ]
235
+ end
162
236
 
237
+ # return result
238
+ if identification_directives[ :__multiple_objects ] && !identification_directives[ :__index_given ]
163
239
 
164
- )
240
+ # return multiple test objects
241
+ matches.to_a
165
242
 
166
- created_accessors << objType
243
+ else
167
244
 
168
- end
245
+ # return only one test object
246
+ [ matches[ identification_directives[ :__index ] ] ]
169
247
 
170
- }
171
-
172
- }
173
-
174
- end
175
-
176
-
177
- def verify_ui_dump( sut )
178
-
179
- return if @inside_verify
180
-
181
- begin
182
- @inside_verify = true
248
+ end
183
249
 
184
- logging_enabled = MobyUtil::Logger.instance.enabled
250
+ }
251
+
252
+ end
185
253
 
186
- sut.verify_blocks.each do | verify |
187
- check_verify_always_reporting_settings()
188
- begin
254
+ def make_test_object( rules )
189
255
 
190
- MobyUtil::Logger.instance.enabled = false
256
+ # get test object factory object from hash
257
+ test_object_factory = rules[ :test_object_factory ]
258
+
259
+ # get sut object from hash
260
+ sut = rules[ :sut ]
261
+
262
+ # get parent object from hash
263
+ parent = rules[ :parent]
264
+
265
+ xml_object = rules[ :xml_object ]
191
266
 
192
- begin
193
- result = verify.block.call( sut )
194
-
195
- rescue Exception => e
196
-
197
- if @rcv_raise_errors=='true' || @reporter_attached=='false'
198
- raise MobyBase::ContinuousVerificationError.new(
199
- "Verification failed as an exception was thrown when the verification block was executed. %s\nDetails: %s\nNested exception:\n%s" % [ verify.source, ( verify.message || "none" ), e.inspect ]
200
- )
201
- elsif @reporter_attached=='true' && @rcv_raise_errors=='false'
202
- TDriverReportAPI::tdriver_report_set_test_case_status('failed') if @rcv_fail_test_case=='true'
203
- if @rvc_capture_screen=='true'
204
- TDriverReportAPI::tdriver_capture_state
205
- else
206
- TDriverReportAPI::tdriver_capture_state(false)
207
- end
208
- TDriverReportAPI::tdriver_report_log("Verification failed as an exception was thrown when the verification block was executed. %s\nDetails: %s\nNested exception:\n%s" % [ verify.source, ( verify.message || "none" ), e.inspect ])
209
- TDriverReportAPI::tdriver_report_log("<hr />")
210
- MobyUtil::Logger.instance.enabled = logging_enabled
211
- MobyUtil::Logger.instance.log "behaviour" , "FAIL;Verification #{verify.message.nil? ? '' : '\"' << verify.message << '\" '}failed:#{e.to_s}.\n#{verify.timeout.nil? ? '' : ' using timeout ' + verify.timeout.to_s}.;#{sut.id.to_s+';sut'};{};verify_always;" << verify.expected.to_s
212
- end
213
- end
214
-
215
- unless result == verify.expected
267
+ if xml_object.kind_of?( MobyUtil::XML::Element )
216
268
 
217
- if @rcv_raise_errors=='true' || @reporter_attached=='false'
218
- raise MobyBase::ContinuousVerificationError.new(
219
- "Verification failed. %s\nDetails: %s\nThe block did not return %s. It returned: %s" % [ verify.source, ( verify.message || "none" ), verify.expected.inspect, result.inspect ]
220
- )
221
- elsif @reporter_attached=='true' && @rcv_raise_errors=='false'
222
- TDriverReportAPI::tdriver_report_set_test_case_status('failed') if @rcv_fail_test_case=='true'
223
- if @rvc_capture_screen=='true'
224
- TDriverReportAPI::tdriver_capture_state
225
- else
226
- TDriverReportAPI::tdriver_capture_state(false)
227
- end
228
- TDriverReportAPI::tdriver_report_log("Verification failed. %s\nDetails: %s\nThe block did not return %s. It returned: %s " % [ verify.source, ( verify.message || "none" ), verify.expected.inspect, result.inspect])
229
- TDriverReportAPI::tdriver_report_log("<hr />")
230
- MobyUtil::Logger.instance.enabled = logging_enabled
231
- MobyUtil::Logger.instance.log "behaviour" , "FAIL;Verification #{verify.message.nil? ? '' : '\"' << verify.message << '\" '}failed:#{e.to_s}.\n#{verify.timeout.nil? ? '' : ' using timeout ' + verify.timeout.to_s}.;#{sut.id.to_s+';sut'};{};verify_always;" << verify.expected.to_s
232
- end
233
- end
269
+ # retrieve test object id from xml
270
+ object_id = xml_object.attribute( 'id' ).to_i
234
271
 
272
+ # retrieve test object name from xml
273
+ object_name = xml_object.attribute( 'name' ).to_s
235
274
 
236
- rescue Exception => e
275
+ # retrieve test object type from xml
276
+ object_type = xml_object.attribute( 'type' ).to_s
237
277
 
238
- MobyUtil::Logger.instance.enabled = logging_enabled
278
+ # retrieve test object type from xml
279
+ env = ( xml_object.attribute( 'env' ) || MobyUtil::Parameter[ sut.id ][ :env ] ).to_s
239
280
 
240
- MobyUtil::Logger.instance.log "behaviour" , "FAIL;Verification #{verify.message.nil? ? '' : '\"' << verify.message << '\" '}failed:#{e.to_s}.\n#{verify.timeout.nil? ? '' : ' using timeout ' + verify.timeout.to_s}.;#{sut.id.to_s+';sut'};{};verify_always;" << verify.expected.to_s
281
+ else
282
+
283
+ # defaults - refactor this
284
+ object_type = ""
285
+
286
+ object_name = ""
287
+
288
+ object_id = 0
241
289
 
242
- @inside_verify = false
243
-
244
- Kernel::raise e
245
- end
290
+ env = MobyUtil::Parameter[ sut.id ][ :env ].to_s
246
291
 
247
- # Do NOT report PASS cases, like other verify blocks do. This would clog the log with useless info.
248
- restore_global_verify_always_reporting_settings()
249
- end
292
+ end
293
+
294
+ # calculate object cache hash key
295
+ hash_key = ( ( ( 17 * 37 + object_id ) * 37 + object_type.hash ) * 37 + object_name.hash )
250
296
 
251
- ensure
252
- MobyUtil::Logger.instance.enabled = logging_enabled
253
- @inside_verify = false
297
+ # (DO NOT!!) remove object type from object attributes hash_rule
298
+ #rules[ :object_attributes_hash ].delete( :type )
254
299
 
255
- end
256
- end
300
+ # get reference to parent objects child objects cache
301
+ parent_cache = rules[ :parent ].instance_variable_get( :@child_object_cache )
257
302
 
258
- # Function for making a child test object (a test object that is not directly a accessible from the sut)
259
- # Creates accessors for children of the new object, applies any behaviours applicable for its type.
260
- # Does not associate child object to parent / vice versa - leaves that to the client.
261
- #
262
- # == params
263
- # parent_test_object:: TestObject thas is the parent of the child object being created
264
- # test_object_identificator:: TestObjectIdentificator which is used to identify the child object from the xml data
265
- # == returns
266
- # TestObject:: new child test object, could be eql? to an existing TO
267
- # == raises
268
- # == raises, as defined in TestObjectIdentificator
269
- # ArgumentError:: if test_object_identificator is not of type LibXML::XML::Node,
270
- # MultipleTestObjectsIdentifiedError:: if multiple TestObjects can be identified using the test_object_identificator
271
- # TestObjectNotFoundError:: The TestObject cannot be found or the parent object is no longer visible on the SUT
272
- def make_child_objects( rules )
303
+ # get cached test object from parents child objects cache if found; if not found from cache pass newly created object as is
304
+ if parent_cache.has_object?( hash_key )
273
305
 
274
- # make array of matching child test objects
275
- get_test_objects( rules ).collect{ | test_object_xml |
306
+ # get test object from cache
307
+ test_object = parent_cache[ hash_key ]
276
308
 
277
- make_test_object(
309
+ test_object.xml_data = xml_object
278
310
 
279
- self, # test object factory
280
- rules[ :sut ], # sut object to t_o
281
- rules[ :parent ], # parent object to t_o
282
- test_object_xml # t_o xml
311
+ else
312
+
313
+ test_object = MobyBase::TestObject.new( test_object_factory, sut, parent, xml_object )
283
314
 
284
- )
315
+ # apply behaviours to test object
316
+ test_object.extend( MobyBehaviour::ObjectBehaviourComposition )
285
317
 
286
- }
287
-
288
- end
318
+ # apply behaviours to test object
319
+ test_object.apply_behaviour!(
320
+ :object_type => [ '*', object_type ],
321
+ #:sut_type => [ '*', sut.ui_type ],
322
+ :input_type => [ '*', sut.input.to_s ],
323
+ :env => [ '*', *env.split(";") ],
324
+ :version => [ '*', sut.ui_version ]
325
+ )
289
326
 
290
- def make_object_search_params(creation_attributes)
291
- object_search_params = {}
292
- if creation_attributes[:type] != 'application'
293
- object_search_params.merge!(creation_attributes)
294
- object_search_params[:className] = object_search_params.delete(:type) if creation_attributes.has_key?(:type)
295
- object_search_params[:objectName] = object_search_params.delete(:name) if creation_attributes.has_key?(:name)
296
- end
297
- object_search_params
298
- end
299
-
300
- def get_parent_params(test_object)
301
- search_params = []
302
- if test_object.type != 'application' and test_object.type != 'sut'
303
- search_params.concat(get_parent_params(test_object.parent)) if test_object.parent
304
- search_params.concat([{:className => test_object.type, :tasId => test_object.id}]) if test_object
305
- end
306
- search_params
307
- end
327
+ # create child accessors
328
+ TDriver::TestObjectAdapter.create_child_accessors!( xml_object, test_object )
308
329
 
309
- private
330
+ # set given parent in rules hash as parent object to new child test object
331
+ test_object.instance_variable_set( :@parent, parent )
310
332
 
311
- # TODO: This method should be in application test object
312
- def get_layout_direction( sut )
333
+ # add created test object to parents child objects cache
334
+ parent_cache.add_object( test_object )
335
+
336
+ end
313
337
 
314
- sut.xml_data.xpath('*//object[@type="application"]/attributes/attribute[@name="layoutDirection"]/value/text()').first.content || 'LeftToRight'
338
+ # update test objects creation attributes (either cached object or just newly created child object)
339
+ test_object.instance_variable_set( :@creation_attributes, rules[ :object_attributes_hash ].clone )
340
+
341
+ # do not make test object verifications if we are operating on the
342
+ # base sut itself (allow run to pass)
343
+ unless parent.kind_of?( MobyBase::SUT )
315
344
 
316
- end
345
+ TDriver::TestObjectVerification.verify_ui_dump( sut ) unless sut.verify_blocks.empty?
317
346
 
318
- # TODO: Documentation
319
- def get_test_objects( rules )
347
+ end
320
348
 
321
- # get parent object
322
- parent = rules[ :parent ]
349
+ test_object
323
350
 
324
- # determine which application to refresh when identifying desired object(s)
325
- refresh_arguments = rules.fetch( :application, {} )
351
+ end
326
352
 
327
- # get associated sut object
328
- sut = rules.fetch( :sut )
353
+ def make_object_search_params( creation_attributes )
329
354
 
330
- # determine that are we going to retrieve multiple test objects
331
- multiple_objects = rules.fetch( :multiple_objects, false )
355
+ if creation_attributes[ :type ] != 'application'
356
+
357
+ object_search_params = creation_attributes.clone
332
358
 
333
- # determine that should all child objects childrens be retrieved
334
- find_all_children = rules.fetch( :find_all_children, true )
359
+ object_search_params[ :className ] = object_search_params.delete( :type ) if creation_attributes.has_key?( :type )
360
+ object_search_params[ :objectName ] = object_search_params.delete( :name ) if creation_attributes.has_key?( :name )
335
361
 
336
- # creation attributes for test object
337
- creation_attributes = rules.fetch( :attributes )
362
+ object_search_params
338
363
 
339
- # dynamic attributes for test object
340
- #dynamic_attributes = rules.fetch( :dynamic_attributes )
341
- dynamic_attributes = rules.fetch( :dynamic_attributes, {} )
364
+ else
365
+
366
+ {}
367
+
368
+ end
342
369
 
343
- # sorting is disabled by default
344
- sorting = MobyUtil::KernelHelper.to_boolean( dynamic_attributes[ :__xy_sorting ], false )
370
+ end
345
371
 
346
- # determine that did user give index value
347
- index_given = dynamic_attributes.has_key?( :__index )
372
+ def get_parent_params( test_object )
373
+
374
+ unless [ 'application', 'sut' ].include?( test_object.type )
375
+
376
+ search_params.concat( get_parent_params( test_object.parent ) ) if test_object.parent
377
+ search_params.concat( [ { :className => test_object.type, :tasId => test_object.id } ] ) #if test_object
378
+
379
+ search_params
380
+
381
+ else
382
+
383
+ []
384
+
385
+ end
348
386
 
349
- # index for test object, default is 0 (first) if not defined by caller
350
- index = dynamic_attributes.fetch( :__index, 0 ).to_i
387
+ end
351
388
 
352
- # create test object identificator object with given creation attributes
353
- test_object_identificator = MobyBase::TestObjectIdentificator.new( creation_attributes )
389
+ private
354
390
 
355
- MobyUtil::Retryable.until(
391
+ def list_matching_test_objects( matches )
356
392
 
357
- # maximum time used for retrying, if timeout exceeds pass last raised exception
358
- :timeout => ( rules[ :timeout ] || @timeout ),
393
+ matches.collect{ | object |
394
+
395
+ path = [ object.attribute("type") ]
359
396
 
360
- # interval used before retrying
361
- :interval => ( rules[ :interval ] || @_retry_interval ),
397
+ while object.attribute("type") != 'application' do
398
+
399
+ # object/objects/object/../..
400
+ object = object.parent.parent
401
+
402
+ path << object.attribute("type")
403
+
404
+ end
362
405
 
363
- # following exceptions are allowed; Retry until timeout exceeds or other exception type is raised
364
- :exception => [ MobyBase::TestObjectNotFoundError, MobyBase::MultipleTestObjectsIdentifiedError ] ) {
406
+ path.reverse.join(".")
407
+
408
+ }.sort
409
+
410
+ end
411
+
412
+ end # TestObjectFactory
365
413
 
366
- #make search params
367
- object_search_params = make_object_search_params(creation_attributes)
368
- search_params = get_parent_params(parent)
369
- search_params.push(object_search_params)
414
+ end # TDriver
370
415
 
371
- # refresh sut ui state
372
- sut.refresh( refresh_arguments, search_params )
373
416
 
374
- # identify test objects from xml
375
- matches, rule = test_object_identificator.find_objects( parent.xml_data, find_all_children )
376
417
 
377
- # raise exception if multiple objects flag is false and more than one match found
378
- raise MobyBase::MultipleTestObjectsIdentifiedError.new( "Multiple test objects found with rule:\n%s" % creation_attributes.merge( dynamic_attributes ).inspect ) if ( !multiple_objects ) && ( matches.count > 1 && !index_given )
379
418
 
380
- # raise exception if no matching object(s) found
381
- raise MobyBase::TestObjectNotFoundError.new( "Cannot find object with rule:\n%s" % creation_attributes.merge( dynamic_attributes ).inspect ) if matches.empty?
382
419
 
383
- # sort elements
384
- test_object_identificator.sort_elements_by_xy_layout!( matches, get_layout_direction( sut ) ) if sorting
385
420
 
386
- # return result
387
- multiple_objects && !index_given ? matches.to_a : [ matches[ index ] ]
388
421
 
389
422
 
390
- }
391
423
 
392
- end
393
424
 
394
- # Function to get the xml element for a test object
395
- # TODO: Remove TestObjectFactory::makeXML function & refactor the 'user' of this function!
396
- def _make_xml( sut, test_object_identificator )
397
425
 
398
- attributes = test_object_identificator.get_identification_rules
399
-
400
- refresh_args = nil
401
- if attributes[ :type ] == 'application'
402
- refresh_args = { :name => attributes[ :name ], :id => attributes[ :id ], :applicationUid => attributes[ :applicationUid ] }
403
- else
404
- refresh_args = { :id => sut.current_application_id }
405
- end
406
426
 
407
- MobyUtil::Retryable.until(
408
-
409
- :timeout => @timeout, :interval => @_retry_interval, :exception => MobyBase::TestObjectNotFoundError ) {
410
-
411
- sut.refresh( refresh_args, [attributes.clone] ); test_object_identificator.find_object_data( sut.xml_data )
412
427
 
413
- }
414
428
 
415
- end
416
429
 
417
- def make_test_object( test_object_factory, sut, parent, xml_object )
418
-
419
- # retrieve test object type from xml
420
- object_type = xml_object.kind_of?( MobyUtil::XML::Element ) ? xml_object.attribute( 'type' ) : nil
421
-
422
- # if !@test_object_cache.has_key?( object_type )
423
430
 
424
- test_object = MobyBase::TestObject.new( test_object_factory, sut, parent, xml_object )
425
431
 
426
- # apply behaviours to test object
427
- test_object.extend( MobyBehaviour::ObjectBehaviourComposition )
428
432
 
429
- # apply behaviours to test object
430
- test_object.apply_behaviour!(
431
- :object_type => [ '*', object_type ],
432
- :sut_type => [ '*', sut.ui_type ],
433
- :input_type => [ '*', sut.input.to_s ],
434
- :version => [ '*', sut.ui_version ]
435
- )
436
- =begin
437
- Removed object cache usage
438
- # now test object has all required behaviours, store it to cache
439
- @test_object_cache[ object_type ] = test_object.clone
433
+ module MobyBase
440
434
 
441
- else
435
+ # class to represent TestObjectFactory.
436
+ #
437
+ # when a SUT asks for factory to create test objects, it shall give reference to the SUT so that
438
+ # factory can make a call back for SUT object dump (in xml)
439
+ class TestObjectFactory
442
440
 
441
+ include Singleton
443
442
 
444
- # retreieve test object with behaviours from cache and clone it
445
- ( test_object = @test_object_cache[ object_type ].clone ).instance_exec{
443
+ attr_reader :timeout
446
444
 
447
- @test_object_factory = test_object_factory
448
- @sut = sut
449
- @parent = parent
450
- self.xml_data = xml_object
445
+ # TODO: Document me (TestObjectFactory::initialize)
446
+ def initialize
451
447
 
452
- }
448
+ # get timeout from parameters, use default value if parameter not found
449
+ @timeout = MobyUtil::Parameter[ :application_synchronization_timeout, "20" ].to_i
453
450
 
454
- end
455
- =end
456
- create_child_accessors!( test_object )
451
+ # get timeout retry interval from parameters, use default value if parameter not found
452
+ @_retry_interval = MobyUtil::Parameter[ :application_synchronization_retry_interval, "1" ].to_i
457
453
 
458
- # do not make test object verifications if we are operating on the
459
- # base sut itself (allow run to pass)
460
- unless parent.kind_of?( MobyBase::SUT )
454
+ end
461
455
 
462
- verify_ui_dump( sut ) unless sut.verify_blocks.empty?
456
+ #TODO: Team TE review @ Wheels
457
+ # Function to set timeout for TestObjectFactory
458
+ # This should be used only in unit testing, otherwise should not be used
459
+ # sets timeout used in identifying TestObjects to new timeout
460
+ #
461
+ # == params
462
+ # new_timeout:: Fixnum which defines the new timeout
463
+ # == raises
464
+ # ArgumentError:: if parameter is not kind of Fixnum
465
+ def timeout=( value )
463
466
 
467
+ value.check_type( Numeric, "Wrong argument type $1 for timeout value (expected $2)" )
468
+
469
+ @timeout = value
470
+
471
+ end
472
+
473
+ # TODO: document me
474
+ def identify_object( object_attributes_hash, identification_directives, rules )
475
+
476
+ MobyUtil::Retryable.until(
477
+
478
+ # maximum time used for retrying, if timeout exceeds pass last raised exception
479
+ :timeout => identification_directives[ :__timeout ],
480
+
481
+ # interval used before retrying
482
+ :interval => identification_directives[ :__retry_interval ],
483
+
484
+ # following exceptions are allowed; Retry until timeout exceeds or other exception type is raised
485
+ :exception => [ MobyBase::TestObjectNotFoundError, MobyBase::MultipleTestObjectsIdentifiedError ]
486
+
487
+ ){
488
+
489
+ # refresh sut
490
+ identification_directives[ :__sut ].refresh( identification_directives[ :__refresh_arguments ], identification_directives[ :__search_params ] )
491
+
492
+ matches, rule = identification_directives[ :__test_object_identificator ].find_objects(
493
+ identification_directives[ :__parent ].xml_data,
494
+ identification_directives[ :__find_all_children ]
495
+ )
496
+
497
+ # raise exception if no matching object(s) found
498
+ raise MobyBase::TestObjectNotFoundError.new(
499
+
500
+ "Cannot find object with rule:\n%s" % rules[ :object_attributes_hash ].inspect
501
+
502
+ ) if matches.empty?
503
+
504
+ # raise exception if multiple matches found and only one expected
505
+ if ( !identification_directives[ :__multiple_objects ] ) && ( matches.count > 1 && !identification_directives[ :__index_given ] )
506
+
507
+ # raise exception (with list of paths to all matching objects) if multiple objects flag is false and more than one match found
508
+ raise MobyBase::MultipleTestObjectsIdentifiedError.new(
509
+
510
+ "Multiple test objects found with rule: %s\nMatching objects:\n%s\n" % [
511
+ rules[ :object_attributes_hash ].inspect,
512
+ list_matching_test_objects( matches ).each_with_index.collect{ | object, object_index | "%3s) %s" % [ object_index + 1, object ] }.join( "\n" )
513
+ ]
514
+ )
515
+
516
+ end
517
+
518
+ # sort matches
519
+ if identification_directives[ :__xy_sorting ] == true
520
+
521
+ # sort elements
522
+ TDriver::TestObjectAdapter.sort_elements(
523
+ matches,
524
+ TDriver::TestObjectAdapter.application_layout_direction( identification_directives[ :__sut ] )
525
+ )
526
+
527
+ end
528
+
529
+ # return result
530
+ if identification_directives[ :__multiple_objects ] && !identification_directives[ :__index_given ]
531
+
532
+ # return multiple test objects
533
+ matches.to_a
534
+
535
+ else
536
+
537
+ # return only one test object
538
+ [ matches[ identification_directives[ :__index ] ] ]
539
+
540
+ end
541
+
542
+ }
543
+
544
+ end
545
+
546
+ # TODO: document me
547
+ def get_test_objects( rules )
548
+
549
+ # store rules hash to variable
550
+ object_attributes_hash = rules[ :object_attributes_hash ].clone
551
+
552
+ # remove test object identification directives for object identification attributes hash (e.g. :__index, :__multiple_objects etc.)
553
+ identification_directives = rules[ :identification_directives ]
554
+
555
+ # verify given identification directives, only documented end-user directives is checked
556
+ identification_directives.each{ | key, value |
557
+
558
+ case key
559
+
560
+ # Fixnum
561
+ when :__index, :__timeout, :__logging
562
+ value.check_type( Fixnum, "Wrong variable type $1 for #{ key.inspect } test object identification directive (expected $2)" )
563
+
564
+ # TrueClass, FalseClass
565
+ when :__xy_sorting
566
+ value.check_type( [ TrueClass, FalseClass ], "Wrong variable type $1 for #{ key.inspect } test object identification directive (expected $2)" )
567
+
568
+ end
569
+
570
+ }
571
+
572
+ # get parent object
573
+ parent = rules[ :parent ]
574
+
575
+ # retrieve sut object
576
+ sut = parent.kind_of?( MobyBase::SUT ) ? parent : parent.sut
577
+
578
+ # create application refresh attributes hash
579
+ if object_attributes_hash[ :type ] == 'application'
580
+
581
+ # collect :name, :id and :applicationUid from object_attributes_hash if found
582
+ refresh_arguments = object_attributes_hash.collect_keys( :name, :id, :applicationUid )
583
+
584
+ else
585
+
586
+ if parent.kind_of?( MobyBase::TestObject )
587
+
588
+ # get current application for test object
589
+ refresh_arguments = { :id => parent.get_application_id }
590
+
591
+ elsif parent.kind_of?( MobyBase::SUT )
592
+
593
+ # get current application for sut
594
+ refresh_arguments = { :id => sut.current_application_id }
595
+
596
+ end
597
+
464
598
  end
599
+
600
+ # set default values
601
+ identification_directives.default_values(
602
+
603
+ # associated sut
604
+ :__sut => sut,
605
+
606
+ # new child objects parent object
607
+ :__parent => parent,
608
+
609
+ # get timeout from rules hash or TestObjectFactory
610
+ :__timeout => @timeout,
611
+
612
+ # get retry interval from rules hash or TestObjectFactory
613
+ :__retry_interval => @_retry_interval,
614
+
615
+ # determine that are we going to retrieve multiple test objects or just one
616
+ :__multiple_objects => false,
617
+
618
+ # determine that should all child objects childrens be retrieved
619
+ :__find_all_children => true,
620
+
621
+ # determine that did user give index value
622
+ :__index_given => identification_directives.has_key?( :__index ),
623
+
624
+ # determine index of test object to be retrieved
625
+ :__index => 0,
626
+
627
+ :__refresh_arguments => refresh_arguments,
628
+
629
+ # make search params
630
+ :__search_params => get_parent_params( parent ).push( make_object_search_params( object_attributes_hash ) ),
631
+
632
+ # test object identificator to be used
633
+ :__test_object_identificator => MobyBase::TestObjectIdentificator.new( object_attributes_hash )
634
+
635
+ )
636
+
637
+ # add object identification attribute keys to dynamic attributes white list
638
+ MobyUtil::DynamicAttributeFilter.instance.add_attributes( object_attributes_hash.keys )
639
+
640
+ child_objects = identify_object( object_attributes_hash, identification_directives, rules ).collect{ | test_object_xml |
641
+
642
+ # create new test object
643
+ make_test_object(
644
+
645
+ # sut object to t_o
646
+ :sut => identification_directives[ :__sut ],
647
+
648
+ # parent object to t_o
649
+ :parent => identification_directives[ :__parent ],
650
+
651
+ # t_o xml
652
+ :xml_object => test_object_xml,
653
+
654
+ # test object factory
655
+ :test_object_factory => self,
656
+
657
+ :object_attributes_hash => object_attributes_hash
658
+
659
+ )
660
+
661
+ }
662
+
663
+ # return test object(s); either one or multiple objects
664
+ identification_directives[ :__multiple_objects ] ? child_objects : child_objects.first
465
665
 
466
- test_object
666
+ end
467
667
 
468
- end
668
+ def make_object_search_params( creation_attributes )
469
669
 
470
- public # deprecated methods
670
+ if creation_attributes[ :type ] != 'application'
671
+
672
+ object_search_params = creation_attributes.clone
471
673
 
472
- # Function for making a child test object (a test object that is not directly a accessible from the sut)
473
- # Creates accessors for children of the new object, applies any behaviours applicable for its type.
474
- # Does not associate child object to parent / vice versa - leaves that to the client.
475
- #
476
- # == params
477
- # parent_test_object:: TestObject thas is the parent of the child object being created
478
- # test_object_identificator:: TestObjectIdentificator which is used to identify the child object from the xml data
479
- # == returns
480
- # TestObject:: new child test object, could be eql? to an existing TO
481
- # == raises
482
- # == raises, as defined in TestObjectIdentificator
483
- # ArgumentError:: if test_object_identificator is not of type LibXML::XML::Node,
484
- # MultipleTestObjectsIdentifiedError:: if multiple TestObjects can be identified using the test_object_identificator
485
- # TestObjectNotFoundError:: The TestObject cannot be found or the parent object is no longer visible on the SUT
486
- def make_child( parent_test_object, test_object_identificator )
674
+ object_search_params[ :className ] = object_search_params.delete( :type ) if creation_attributes.has_key?( :type )
675
+ object_search_params[ :objectName ] = object_search_params.delete( :name ) if creation_attributes.has_key?( :name )
487
676
 
488
- identified_object_xml = nil
489
-
490
- layout_direction = nil
677
+ object_search_params
491
678
 
492
- MobyUtil::Retryable.until(
493
- :timeout => @timeout,
494
- :interval => @_retry_interval,
495
- :exception => [ MobyBase::TestObjectNotFoundError, MobyBase::MultipleTestObjectsIdentifiedError ] ) {
496
-
497
- parent_test_object.refresh( :id => parent_test_object.get_application_id )
679
+ else
680
+
681
+ {}
682
+
683
+ end
498
684
 
499
- if test_object_identificator.dynamic_attributes.include?( :__xy_sorting )
685
+ end
500
686
 
501
- begin
687
+ def get_parent_params( test_object )
688
+
689
+ unless [ 'application', 'sut' ].include?( test_object.type )
690
+
691
+ search_params = []
692
+
693
+ search_params.concat( get_parent_params( test_object.parent ) ) if test_object.parent
694
+ search_params.concat( [ :className => test_object.type, :tasId => test_object.id ] ) #if test_object
695
+
696
+ search_params
697
+
698
+ else
699
+
700
+ []
701
+
702
+ end
502
703
 
503
- layout_direction = parent_test_object.sut.application( :id => parent_test_object.get_application_id ).attribute("layoutDirection")
704
+ end
705
+
706
+ private
504
707
 
505
- rescue MobyBase::AttributeNotFoundError
708
+ def list_matching_test_objects( matches )
506
709
 
507
- layout_direction = nil
710
+ matches.collect{ | object |
711
+
712
+ path = [ object.attribute( 'type' ) ]
508
713
 
509
- end
510
-
511
- end
714
+ while object.attribute( 'type' ) != 'application' do
715
+
716
+ # object/objects/object/../..
717
+ object = object.parent.parent
718
+
719
+ path << object.attribute( 'type' )
720
+
721
+ end
512
722
 
513
- identified_object_xml = test_object_identificator.find_object_data( parent_test_object.xml_data, layout_direction )
723
+ path.reverse.join( '.' )
724
+
725
+ }.sort
726
+
727
+ end
514
728
 
515
- }
729
+ # TODO: parent application test object should be passed to get_test_objects
730
+ def get_layout_direction( sut )
516
731
 
732
+ sut.xml_data.at_xpath('*//object[@type="application"]/attributes/attribute[@name="layoutDirection"]/value/text()').to_s || 'LeftToRight'
517
733
 
518
- make_test_object(
519
- self,
520
- parent_test_object.sut,
521
- parent_test_object,
522
- identified_object_xml
523
- )
734
+ end
524
735
 
525
- end
736
+ def make_test_object( rules )
526
737
 
738
+ # get test object factory object from hash
739
+ test_object_factory = rules[ :test_object_factory ]
740
+
741
+ # get sut object from hash
742
+ sut = rules[ :sut ]
743
+
744
+ # get parent object from hash
745
+ parent = rules[ :parent]
746
+
747
+ xml_object = rules[ :xml_object ]
527
748
 
528
- # Same as def make_child, but creates an array of test objects
529
- # == params
530
- # parent_test_object:: TestObject thas is the parent of the child object being created
531
- # test_object_identificator:: TestObjectIdentificator which is used to identify the child object from the xml data
532
- #find_all_children:: Boolean specifying whether all children under the test node or just immediate children should be retreived.
533
- # == returns
534
- # An array of Test Objects.
535
- # == raises
536
- # == raises, as defined in TestObjectIdentificator
537
- # ArgumentError:: if test_object_identificator is not of type LibXML::XML::Node,
538
- # TestObjectNotFoundError:: The TestObject cannot be found or the parent object is no longer visible on the SUT
539
- def make_multiple_children( parent_test_object, test_object_identificator, find_all_children)
749
+ # retrieve attributes
750
+ #TDriver::TestObjectAdapter.fetch_attributes( xml_object, [ 'id', 'name', 'type', 'env' ], false )
540
751
 
541
- identified_object_xml = Array.new
752
+ if xml_object.kind_of?( MobyUtil::XML::Element )
542
753
 
543
- ret_array = Array.new
754
+ # retrieve test object id from xml
755
+ object_id = TDriver::TestObjectAdapter.test_object_element_attribute( xml_object, 'id' ){ nil }.to_i
544
756
 
545
- layout_direction = nil
757
+ # retrieve test object name from xml
758
+ object_name = TDriver::TestObjectAdapter.test_object_element_attribute( xml_object, 'name' ){ nil }.to_s
546
759
 
547
- begin
760
+ # retrieve test object type from xml
761
+ object_type = TDriver::TestObjectAdapter.test_object_element_attribute( xml_object, 'type' ){ nil }.to_s
548
762
 
549
- MobyUtil::Retryable.until(
550
- :timeout => @timeout,
551
- :interval => @_retry_interval,
552
- :exception => [ MobyBase::TestObjectNotFoundError ] ) {
763
+ # retrieve test object type from xml
764
+ env = TDriver::TestObjectAdapter.test_object_element_attribute( xml_object, 'env' ){ MobyUtil::Parameter[ sut.id ][ :env ] }.to_s
765
+
766
+ else
767
+
768
+ # defaults - refactor this
769
+ object_type = ""
770
+
771
+ object_name = ""
772
+
773
+ object_id = 0
553
774
 
554
- parent_test_object.refresh( :id => parent_test_object.get_application_id )
775
+ env = MobyUtil::Parameter[ sut.id ][ :env ].to_s
555
776
 
556
- if test_object_identificator.dynamic_attributes.include?( :__xy_sorting )
777
+ end
557
778
 
558
- begin
779
+ # calculate object cache hash key
780
+ hash_key = TDriver::TestObjectAdapter.test_object_hash( object_id, object_type, object_name )
781
+
782
+ # get reference to parent objects child objects cache
783
+ parent_cache = rules[ :parent ].instance_variable_get( :@child_object_cache )
559
784
 
560
- layout_direction = parent_test_object.sut.application( :id => parent_test_object.get_application_id ).attribute("layoutDirection")
785
+ # get cached test object from parents child objects cache if found; if not found from cache pass newly created object as is
786
+ if parent_cache.has_object?( hash_key )
561
787
 
562
- rescue MobyBase::AttributeNotFoundError
788
+ # get test object from cache
789
+ test_object = parent_cache[ hash_key ]
563
790
 
564
- layout_direction = nil
791
+ # store xml_object to test object
792
+ test_object.xml_data = xml_object
565
793
 
566
- end
794
+ else
795
+
796
+ # create test object
797
+ test_object = MobyBase::TestObject.new( test_object_factory, sut, parent, xml_object )
567
798
 
568
- end
799
+ # apply behaviours to test object
800
+ test_object.extend( MobyBehaviour::ObjectBehaviourComposition )
569
801
 
570
- identified_object_xml = test_object_identificator.find_multiple_object_data( parent_test_object.xml_data, find_all_children, layout_direction )
802
+ # apply behaviours to test object
803
+ test_object.apply_behaviour!(
804
+ :object_type => [ '*', object_type ],
805
+ #:sut_type => [ '*', sut.ui_type ],
806
+ :input_type => [ '*', sut.input.to_s ],
807
+ :env => [ '*', *env.split(";") ],
808
+ :version => [ '*', sut.ui_version ]
809
+ )
571
810
 
572
- }
811
+ # create child accessors
812
+ TDriver::TestObjectAdapter.create_child_accessors!( xml_object, test_object )
573
813
 
574
- rescue MobyBase::TestObjectNotFoundError
814
+ # set given parent in rules hash as parent object to new child test object
815
+ test_object.instance_variable_set( :@parent, parent )
575
816
 
576
- Kernel::raise MobyBase::TestObjectNotFoundError.new(
577
- "The parent test object was no available on the SUT.\n" <<
578
- "Expected object type: '#{ parent_test_object.type }' id: '#{ parent_test_object.id }'"
579
- )
817
+ # add created test object to parents child objects cache
818
+ parent_cache.add_object( test_object )
580
819
 
581
820
  end
582
821
 
583
- identified_object_xml.each do |child_xml|
822
+ # NOTE: Do not remove object_type from object attributes hash_rule due to it is used in find_objects service!
823
+ #rules[ :object_attributes_hash ].delete( :type )
584
824
 
585
- ret_array << make_test_object( self, parent_test_object.sut, parent_test_object, child_xml )
825
+ # update test objects creation attributes (either cached object or just newly created child object)
826
+ test_object.instance_variable_set( :@creation_attributes, rules[ :object_attributes_hash ] )
827
+
828
+ # do not make test object verifications if we are operating on the sut itself (allow run to pass)
829
+ unless parent.kind_of?( MobyBase::SUT )
586
830
 
587
- end
831
+ # verify ui state if any verifycation blocks given
832
+ TDriver::TestObjectVerification.verify_ui_dump( sut ) unless sut.verify_blocks.empty?
588
833
 
589
- ret_array
834
+ end
590
835
 
591
- end
836
+ # return test object
837
+ test_object
592
838
 
593
- def set_timeout( new_timeout )
839
+ end
594
840
 
595
- warn( "Deprecated method: use timeout=(value) instead of TestObjectFactory#set_timeout( value )" )
841
+ public # deprecated methods
596
842
 
597
- self.timeout = new_timeout
843
+ def set_timeout( new_timeout )
598
844
 
599
- end
845
+ warn( "Deprecated method: use timeout=(value) instead of TestObjectFactory#set_timeout( value )" )
600
846
 
601
- # Function gets the timeout used in TestObjectFactory
602
- #
603
- # === returns
604
- # Numeric:: Timeout
605
- def get_timeout
847
+ self.timeout = new_timeout
606
848
 
607
- warn( "Deprecated method: use timeout instead of TestObjectFactory#get_timeout" )
849
+ end
608
850
 
609
- @timeout
851
+ # Function gets the timeout used in TestObjectFactory
852
+ #
853
+ # === returns
854
+ # Numeric:: Timeout
855
+ def get_timeout
610
856
 
611
- end
857
+ warn( "Deprecated method: use timeout instead of TestObjectFactory#get_timeout" )
612
858
 
613
- # enable hooking for performance measurement & debug logging
614
- MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
859
+ @timeout
860
+
861
+ end
862
+
863
+ # enable hoo./base/test_object/factory.rb:king for performance measurement & debug logging
864
+ MobyUtil::Hooking.instance.hook_methods( self ) if defined?( MobyUtil::Hooking )
615
865
 
616
866
  end # TestObjectFactory
617
867
 
618
868
  end # MobyBase
869
+