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
@@ -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
+