2 # -*- coding: utf-8 -*-
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openmano
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
26 Module for testing openmano functionality. It uses openmanoclient.py for invoking openmano
28 __author__
="Pablo Montes, Alfonso Tierno"
29 __date__
="$16-Feb-2017 17:08:16$"
31 version_date
="May 2017"
36 from optparse
import OptionParser
49 global scenario_test_folder
50 global test_image_name
52 global management_network
55 def check_instance_scenario_active(uuid
):
56 instance
= client
.get_instance(uuid
=uuid
)
58 for net
in instance
['nets']:
59 status
= net
['status']
60 if status
!= 'ACTIVE':
61 return (False, status
)
63 for vnf
in instance
['vnfs']:
66 if status
!= 'ACTIVE':
67 return (False, status
)
73 All unittest classes for code based tests must have prefix 'test_' in order to be taken into account for tests
75 class test_tenant_operations(unittest
.TestCase
):
82 logger
.info("{}. {}".format(test_number
, cls
.__name
__))
85 def tearDownClass(cls
):
86 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
89 exec_info
= sys
.exc_info()
90 if exec_info
== (None, None, None):
91 logger
.info(self
.__class
__.test_text
+" -> TEST OK")
93 logger
.warning(self
.__class
__.test_text
+" -> TEST NOK")
94 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
96 for line
in error_trace
:
98 logger
.critical("{}".format(msg
))
100 def test_000_create_RO_tenant(self
):
101 self
.__class
__.tenant_name
= _get_random_string(20)
102 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
103 inspect
.currentframe().f_code
.co_name
)
104 self
.__class
__.test_index
+= 1
105 tenant
= client
.create_tenant(name
=self
.__class
__.tenant_name
, description
=self
.__class
__.tenant_name
)
106 logger
.debug("{}".format(tenant
))
107 self
.assertEqual(tenant
.get('tenant', {}).get('name', ''), self
.__class
__.tenant_name
)
109 def test_010_list_RO_tenant(self
):
110 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
111 inspect
.currentframe().f_code
.co_name
)
112 self
.__class
__.test_index
+= 1
113 tenant
= client
.get_tenant(name
=self
.__class
__.tenant_name
)
114 logger
.debug("{}".format(tenant
))
115 self
.assertEqual(tenant
.get('tenant', {}).get('name', ''), self
.__class
__.tenant_name
)
117 def test_020_delete_RO_tenant(self
):
118 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
119 inspect
.currentframe().f_code
.co_name
)
120 self
.__class
__.test_index
+= 1
121 tenant
= client
.delete_tenant(name
=self
.__class
__.tenant_name
)
122 logger
.debug("{}".format(tenant
))
123 assert('deleted' in tenant
.get('result',""))
125 class test_datacenter_operations(unittest
.TestCase
):
127 datacenter_name
= None
132 logger
.info("{}. {}".format(test_number
, cls
.__name
__))
135 def tearDownClass(cls
):
136 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
139 exec_info
= sys
.exc_info()
140 if exec_info
== (None, None, None):
141 logger
.info(self
.__class
__.test_text
+" -> TEST OK")
143 logger
.warning(self
.__class
__.test_text
+" -> TEST NOK")
144 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
146 for line
in error_trace
:
148 logger
.critical("{}".format(msg
))
150 def test_000_create_datacenter(self
):
151 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
152 inspect
.currentframe().f_code
.co_name
)
153 self
.__class
__.datacenter_name
= _get_random_string(20)
154 self
.__class
__.test_index
+= 1
155 self
.datacenter
= client
.create_datacenter(name
=self
.__class
__.datacenter_name
, vim_url
="http://fakeurl/fake")
156 logger
.debug("{}".format(self
.datacenter
))
157 self
.assertEqual (self
.datacenter
.get('datacenter', {}).get('name',''), self
.__class
__.datacenter_name
)
159 def test_010_list_datacenter(self
):
160 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
161 inspect
.currentframe().f_code
.co_name
)
163 self
.__class
__.test_index
+= 1
164 self
.datacenter
= client
.get_datacenter(all_tenants
=True, name
=self
.__class
__.datacenter_name
)
165 logger
.debug("{}".format(self
.datacenter
))
166 self
.assertEqual (self
.datacenter
.get('datacenter', {}).get('name', ''), self
.__class
__.datacenter_name
)
168 def test_020_attach_datacenter(self
):
169 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
170 inspect
.currentframe().f_code
.co_name
)
172 self
.__class
__.test_index
+= 1
173 self
.datacenter
= client
.attach_datacenter(name
=self
.__class
__.datacenter_name
, vim_tenant_name
='fake')
174 logger
.debug("{}".format(self
.datacenter
))
175 assert ('vim_tenants' in self
.datacenter
.get('datacenter', {}))
177 def test_030_list_attached_datacenter(self
):
178 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
179 inspect
.currentframe().f_code
.co_name
)
181 self
.__class
__.test_index
+= 1
182 self
.datacenter
= client
.get_datacenter(all_tenants
=False, name
=self
.__class
__.datacenter_name
)
183 logger
.debug("{}".format(self
.datacenter
))
184 self
.assertEqual (self
.datacenter
.get('datacenter', {}).get('name', ''), self
.__class
__.datacenter_name
)
186 def test_040_detach_datacenter(self
):
187 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
188 inspect
.currentframe().f_code
.co_name
)
190 self
.__class
__.test_index
+= 1
191 self
.datacenter
= client
.detach_datacenter(name
=self
.__class
__.datacenter_name
)
192 logger
.debug("{}".format(self
.datacenter
))
193 assert ('detached' in self
.datacenter
.get('result', ""))
195 def test_050_delete_datacenter(self
):
196 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
197 inspect
.currentframe().f_code
.co_name
)
199 self
.__class
__.test_index
+= 1
200 self
.datacenter
= client
.delete_datacenter(name
=self
.__class
__.datacenter_name
)
201 logger
.debug("{}".format(self
.datacenter
))
202 assert('deleted' in self
.datacenter
.get('result',""))
204 class test_VIM_network_operations(unittest
.TestCase
):
206 vim_network_name
= None
208 vim_network_uuid
= None
212 logger
.info("{}. {}".format(test_number
, cls
.__name
__))
215 def tearDownClass(cls
):
216 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
219 exec_info
= sys
.exc_info()
220 if exec_info
== (None, None, None):
221 logger
.info(self
.__class
__.test_text
+ " -> TEST OK")
223 logger
.warning(self
.__class
__.test_text
+ " -> TEST NOK")
224 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
226 for line
in error_trace
:
228 logger
.critical("{}".format(msg
))
230 def test_000_create_VIM_network(self
):
231 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
232 inspect
.currentframe().f_code
.co_name
)
233 self
.__class
__.vim_network_name
= _get_random_string(20)
234 self
.__class
__.test_index
+= 1
235 network
= client
.vim_action("create", "networks", name
=self
.__class
__.vim_network_name
)
236 logger
.debug("{}".format(network
))
237 self
.__class
__.vim_network_uuid
= network
["network"]["id"]
238 self
.assertEqual(network
.get('network', {}).get('name', ''), self
.__class
__.vim_network_name
)
240 def test_010_list_VIM_networks(self
):
241 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
242 inspect
.currentframe().f_code
.co_name
)
243 self
.__class
__.test_index
+= 1
244 networks
= client
.vim_action("list", "networks")
245 logger
.debug("{}".format(networks
))
247 def test_020_get_VIM_network_by_uuid(self
):
248 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
249 inspect
.currentframe().f_code
.co_name
)
251 self
.__class
__.test_index
+= 1
252 network
= client
.vim_action("show", "networks", uuid
=self
.__class
__.vim_network_uuid
)
253 logger
.debug("{}".format(network
))
254 self
.assertEqual(network
.get('network', {}).get('name', ''), self
.__class
__.vim_network_name
)
256 def test_030_delete_VIM_network_by_uuid(self
):
257 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
258 inspect
.currentframe().f_code
.co_name
)
260 self
.__class
__.test_index
+= 1
261 network
= client
.vim_action("delete", "networks", uuid
=self
.__class
__.vim_network_uuid
)
262 logger
.debug("{}".format(network
))
263 assert ('deleted' in network
.get('result', ""))
265 class test_VIM_image_operations(unittest
.TestCase
):
271 logger
.info("{}. {}".format(test_number
, cls
.__name
__))
274 def tearDownClass(cls
):
275 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
278 exec_info
= sys
.exc_info()
279 if exec_info
== (None, None, None):
280 logger
.info(self
.__class
__.test_text
+ " -> TEST OK")
282 logger
.warning(self
.__class
__.test_text
+ " -> TEST NOK")
283 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
285 for line
in error_trace
:
287 logger
.critical("{}".format(msg
))
289 def test_000_list_VIM_images(self
):
290 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
291 inspect
.currentframe().f_code
.co_name
)
292 self
.__class
__.test_index
+= 1
293 images
= client
.vim_action("list", "images")
294 logger
.debug("{}".format(images
))
297 The following is a non critical test that will fail most of the times.
298 In case of OpenStack datacenter these tests will only success if RO has access to the admin endpoint
299 This test will only be executed in case it is specifically requested by the user
301 class test_VIM_tenant_operations(unittest
.TestCase
):
303 vim_tenant_name
= None
305 vim_tenant_uuid
= None
309 logger
.info("{}. {}".format(test_number
, cls
.__name
__))
310 logger
.warning("In case of OpenStack datacenter these tests will only success "
311 "if RO has access to the admin endpoint")
314 def tearDownClass(cls
):
315 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
318 exec_info
= sys
.exc_info()
319 if exec_info
== (None, None, None):
320 logger
.info(self
.__class
__.test_text
+ " -> TEST OK")
322 logger
.warning(self
.__class
__.test_text
+ " -> TEST NOK")
323 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
325 for line
in error_trace
:
327 logger
.critical("{}".format(msg
))
329 def test_000_create_VIM_tenant(self
):
330 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
331 inspect
.currentframe().f_code
.co_name
)
332 self
.__class
__.vim_tenant_name
= _get_random_string(20)
333 self
.__class
__.test_index
+= 1
334 tenant
= client
.vim_action("create", "tenants", name
=self
.__class
__.vim_tenant_name
)
335 logger
.debug("{}".format(tenant
))
336 self
.__class
__.vim_tenant_uuid
= tenant
["tenant"]["id"]
337 self
.assertEqual(tenant
.get('tenant', {}).get('name', ''), self
.__class
__.vim_tenant_name
)
339 def test_010_list_VIM_tenants(self
):
340 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
341 inspect
.currentframe().f_code
.co_name
)
342 self
.__class
__.test_index
+= 1
343 tenants
= client
.vim_action("list", "tenants")
344 logger
.debug("{}".format(tenants
))
346 def test_020_get_VIM_tenant_by_uuid(self
):
347 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
348 inspect
.currentframe().f_code
.co_name
)
350 self
.__class
__.test_index
+= 1
351 tenant
= client
.vim_action("show", "tenants", uuid
=self
.__class
__.vim_tenant_uuid
)
352 logger
.debug("{}".format(tenant
))
353 self
.assertEqual(tenant
.get('tenant', {}).get('name', ''), self
.__class
__.vim_tenant_name
)
355 def test_030_delete_VIM_tenant_by_uuid(self
):
356 self
.__class
__.test_text
= "{}.{}. TEST {}".format(test_number
, self
.__class
__.test_index
,
357 inspect
.currentframe().f_code
.co_name
)
359 self
.__class
__.test_index
+= 1
360 tenant
= client
.vim_action("delete", "tenants", uuid
=self
.__class
__.vim_tenant_uuid
)
361 logger
.debug("{}".format(tenant
))
362 assert ('deleted' in tenant
.get('result', ""))
366 The following unittest class does not have the 'test_' on purpose. This test is the one used for the
367 scenario based tests.
369 class descriptor_based_scenario_test(unittest
.TestCase
):
372 scenario_test_path
= None
374 instance_scenario_uuid
= None
380 cls
.to_delete_list
= []
381 cls
.scenario_test_path
= test_directory
+ '/' + scenario_test_folder
382 logger
.info("{}. {} {}".format(test_number
, cls
.__name
__, scenario_test_folder
))
385 def tearDownClass(cls
):
386 globals().__setitem
__('test_number', globals().__getitem
__('test_number') + 1)
389 exec_info
= sys
.exc_info()
390 if exec_info
== (None, None, None):
391 logger
.info(self
.__class
__.test_text
+ " -> TEST OK")
393 logger
.warning(self
.__class
__.test_text
+ " -> TEST NOK")
394 error_trace
= traceback
.format_exception(exec_info
[0], exec_info
[1], exec_info
[2])
396 for line
in error_trace
:
398 logger
.critical("{}".format(msg
))
401 def test_000_load_scenario(self
):
402 self
.__class
__.test_text
= "{}.{}. TEST {} {}".format(test_number
, self
.__class
__.test_index
,
403 inspect
.currentframe().f_code
.co_name
,
404 scenario_test_folder
)
405 self
.__class
__.test_index
+= 1
406 vnfd_files
= glob
.glob(self
.__class
__.scenario_test_path
+'/vnfd_*.yaml')
407 scenario_file
= glob
.glob(self
.__class
__.scenario_test_path
+ '/scenario_*.yaml')
408 if len(vnfd_files
) == 0 or len(scenario_file
) > 1:
409 raise Exception('Test '+scenario_test_folder
+' not valid. It must contain an scenario file and at least one'
413 for vnfd
in vnfd_files
:
414 with
open(vnfd
, 'r') as stream
:
415 vnf_descriptor
= yaml
.load(stream
)
417 vnfc_list
= vnf_descriptor
['vnf']['VNFC']
418 for vnfc
in vnfc_list
:
419 vnfc
['image name'] = test_image_name
420 devices
= vnfc
.get('devices',[])
421 for device
in devices
:
422 if device
['type'] == 'disk' and 'image name' in device
:
423 device
['image name'] = test_image_name
425 logger
.debug("VNF descriptor: {}".format(vnf_descriptor
))
426 vnf
= client
.create_vnf(descriptor
=vnf_descriptor
)
428 self
.__class
__.to_delete_list
.insert(0, {"item": "vnf", "function": client
.delete_vnf
,
429 "params": {"uuid": vnf
['vnf']['uuid']}})
431 #load the scenario definition
432 with
open(scenario_file
[0], 'r') as stream
:
433 scenario_descriptor
= yaml
.load(stream
)
434 networks
= scenario_descriptor
['scenario']['networks']
435 networks
[management_network
] = networks
.pop('mgmt')
436 logger
.debug("Scenario descriptor: {}".format(scenario_descriptor
))
437 scenario
= client
.create_scenario(descriptor
=scenario_descriptor
)
438 logger
.debug(scenario
)
439 self
.__class
__.to_delete_list
.insert(0,{"item": "scenario", "function": client
.delete_scenario
,
440 "params":{"uuid": scenario
['scenario']['uuid']} })
441 self
.__class
__.scenario_uuid
= scenario
['scenario']['uuid']
443 def test_010_instantiate_scenario(self
):
444 self
.__class
__.test_text
= "{}.{}. TEST {} {}".format(test_number
, self
.__class
__.test_index
,
445 inspect
.currentframe().f_code
.co_name
,
446 scenario_test_folder
)
447 self
.__class
__.test_index
+= 1
449 instance
= client
.create_instance(scenario_id
=self
.__class
__.scenario_uuid
, name
=self
.__class
__.test_text
)
450 self
.__class
__.instance_scenario_uuid
= instance
['uuid']
451 logger
.debug(instance
)
452 self
.__class
__.to_delete_list
.insert(0, {"item": "instance", "function": client
.delete_instance
,
453 "params": {"uuid": instance
['uuid']}})
455 def test_020_check_deployent(self
):
456 self
.__class
__.test_text
= "{}.{}. TEST {} {}".format(test_number
, self
.__class
__.test_index
,
457 inspect
.currentframe().f_code
.co_name
,
458 scenario_test_folder
)
459 self
.__class
__.test_index
+= 1
462 raw_input('Scenario has been deployed. Perform manual check and press any key to resume')
465 keep_waiting
= timeout
466 instance_active
= False
468 result
= check_instance_scenario_active(self
.__class
__.instance_scenario_uuid
)
471 elif 'ERROR' in result
[1]:
472 msg
= 'Got error while waiting for the instance to get active: '+result
[1]
476 if keep_waiting
>= 5:
479 elif keep_waiting
> 0:
480 time
.sleep(keep_waiting
)
483 msg
= 'Timeout reached while waiting instance scenario to get active'
487 def test_030_clean_deployment(self
):
488 self
.__class
__.test_text
= "{}.{}. TEST {} {}".format(test_number
, self
.__class
__.test_index
,
489 inspect
.currentframe().f_code
.co_name
,
490 scenario_test_folder
)
491 self
.__class
__.test_index
+= 1
492 #At the moment if you delete an scenario right after creating it, in openstack datacenters
493 #sometimes scenario ports get orphaned. This sleep is just a dirty workaround
495 for item
in self
.__class
__.to_delete_list
:
496 response
= item
["function"](**item
["params"])
497 logger
.debug(response
)
499 def _get_random_string(maxLength
):
500 '''generates a string with random characters string.letters and string.digits
501 with a random length up to maxLength characters. If maxLength is <15 it will be changed automatically to 15
505 minLength
= min_string
- len(prefix
)
506 if maxLength
< min_string
: maxLength
= min_string
507 maxLength
-= len(prefix
)
508 length
= random
.randint(minLength
,maxLength
)
509 return 'testing_'+"".join([random
.choice(string
.letters
+string
.digits
) for i
in xrange(length
)])
511 if __name__
=="__main__":
512 sys
.path
.append(os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))) + "/osm_ro")
513 import openmanoclient
515 parser
= OptionParser()
518 parser
.add_option('-d', '--datacenter', dest
='datacenter_name', help='MANDATORY, Set the datacenter name to test')
519 parser
.add_option("-i", '--image-name', dest
='image-name', help='MANDATORY. Image name of an Ubuntu 16.04 image '
520 'that will be used for testing available in the '
522 parser
.add_option("-n", '--mgmt-net-name', dest
='mgmt-net', help='MANDATORY. Set the vim management network to use')
523 parser
.add_option("-t", '--tenant', dest
='tenant_name', help='MANDATORY. Set the tenant name to test')
526 parser
.add_option('--debug', help='Set logs to debug level', dest
='debug', action
="store_true", default
=False)
527 parser
.add_option('--failfast', help='Stop when a test fails rather than execute all tests',
528 dest
='failfast', action
="store_true", default
=False)
529 parser
.add_option('--failed', help='Set logs to show only failed tests. --debug disables this option',
530 dest
='failed', action
="store_true", default
=False)
531 default_logger_file
= os
.path
.dirname(__file__
)+'/'+os
.path
.splitext(os
.path
.basename(__file__
))[0]+'.log'
532 parser
.add_option('--list-tests', help='List all available tests', dest
='list-tests', action
="store_true",
534 parser
.add_option('--logger_file', dest
='logger_file', help='Set the logger file. By default '+default_logger_file
,
535 default
=default_logger_file
)
536 parser
.add_option('-m', '--manual-check', help='Pause execution once deployed to allow manual checking of the '
537 'deployed instance scenario',
538 dest
='manual', action
="store_true", default
=False)
539 parser
.add_option('--timeout', help='Specify the instantiation timeout in seconds. By default 300',
540 dest
='timeout', type='int', default
=300)
541 parser
.add_option('--test', '--tests', help='Specify the tests to run', dest
='tests', default
=None)
542 parser
.add_option('-u', '--url', dest
='endpoint_url', help='Set the openmano server url. By default '
543 'http://localhost:9090/openmano',
544 default
='http://localhost:9090/openmano')
545 parser
.add_option("-v",'--version', help='Show current version', dest
='version', action
="store_true", default
=False)
547 (options
, args
) = parser
.parse_args()
549 # default logger level is INFO. Options --debug and --failed override this, being --debug prioritary
550 logger_level
= 'INFO'
551 if options
.__dict
__['debug']:
552 logger_level
= 'DEBUG'
553 elif options
.__dict
__['failed']:
554 logger_level
= 'WARNING'
555 logger_name
= os
.path
.basename(__file__
)
556 logger
= logging
.getLogger(logger_name
)
557 logger
.setLevel(logger_level
)
558 failfast
= options
.__dict
__['failfast']
560 # Configure a logging handler to store in a logging file
561 fileHandler
= logging
.FileHandler(options
.__dict
__['logger_file'])
562 formatter_fileHandler
= logging
.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
563 fileHandler
.setFormatter(formatter_fileHandler
)
564 logger
.addHandler(fileHandler
)
566 # Configure a handler to print to stdout
567 consoleHandler
= logging
.StreamHandler(sys
.stdout
)
568 formatter_consoleHandler
= logging
.Formatter('%(message)s')
569 consoleHandler
.setFormatter(formatter_consoleHandler
)
570 logger
.addHandler(consoleHandler
)
572 logger
.debug('Program started with the following arguments: ' + str(options
.__dict
__))
574 # If version is required print it and exit
575 if options
.__dict
__['version']:
576 logger
.info("{}".format((sys
.argv
[0], __version__
+" version", version_date
)))
577 logger
.info("(c) Copyright Telefonica")
580 test_directory
= os
.path
.dirname(__file__
) + "/RO_tests"
581 test_directory_content
= os
.listdir(test_directory
)
582 clsmembers
= inspect
.getmembers(sys
.modules
[__name__
], inspect
.isclass
)
584 # If only want to obtain a tests list print it and exit
585 if options
.__dict
__['list-tests']:
587 for cls
in clsmembers
:
588 if cls
[0].startswith('test_'):
589 tests_names
.append(cls
[0])
591 msg
= "The code based tests are:\n\t" + ', '.join(sorted(tests_names
)) + \
592 "\nThe descriptor based tests are:\n\t" + ', '.join(sorted(test_directory_content
)) + \
593 "\nNOTE: The test test_VIM_tenant_operations will fail in case the used datacenter is type OpenStack " \
594 "unless RO has access to the admin endpoint. Therefore this test is excluded by default"
599 # Make sure required arguments are present
600 required
= "tenant_name datacenter_name image-name mgmt-net".split()
603 if options
.__dict
__[r
] is None:
604 print ("ERROR: parameter "+r
+" is required")
610 # set test image name and management network
611 test_image_name
= options
.__dict
__['image-name']
612 management_network
= options
.__dict
__['mgmt-net']
613 manual
= options
.__dict
__['manual']
614 timeout
= options
.__dict
__['timeout']
616 # Create the list of tests to be run
617 descriptor_based_tests
= []
618 code_based_tests
= []
619 if options
.__dict
__['tests'] is not None:
620 tests
= sorted(options
.__dict
__['tests'].split(','))
622 matches_code_based_tests
= [item
for item
in clsmembers
if item
[0] == test
]
623 if test
in test_directory_content
:
624 descriptor_based_tests
.append(test
)
625 elif len(matches_code_based_tests
) > 0:
626 code_based_tests
.append(matches_code_based_tests
[0][1])
628 logger
.critical("Test {} is not among the possible ones".format(test
))
632 descriptor_based_tests
= test_directory_content
633 for cls
in clsmembers
:
634 # We exclude 'test_VIM_tenant_operations' unless it is specifically requested by the user
635 if cls
[0].startswith('test_') and cls
[0] != 'test_VIM_tenant_operations':
636 code_based_tests
.append(cls
[1])
638 logger
.debug("descriptor_based_tests to be executed: {}".format(descriptor_based_tests
))
639 logger
.debug("code_based_tests to be executed: {}".format(code_based_tests
))
641 # import openmanoclient from relative path
642 client
= openmanoclient
.openmanoclient(
643 endpoint_url
=options
.__dict
__['endpoint_url'],
644 tenant_name
=options
.__dict
__['tenant_name'],
645 datacenter_name
=options
.__dict
__['datacenter_name'],
646 debug
=options
.__dict
__['debug'], logger
=logger_name
)
648 # TextTestRunner stream is set to /dev/null in order to avoid the method to directly print the result of tests.
649 # This is handled in the tests using logging.
650 stream
= open('/dev/null', 'w')
655 # Run code based tests
656 basic_tests_suite
= unittest
.TestSuite()
657 for test
in code_based_tests
:
658 basic_tests_suite
.addTest(unittest
.makeSuite(test
))
659 result
= unittest
.TextTestRunner(stream
=stream
, failfast
=failfast
).run(basic_tests_suite
)
660 executed
+= result
.testsRun
661 failed
+= len(result
.failures
) + len(result
.errors
)
662 if failfast
and failed
:
664 if len(result
.failures
) > 0:
665 logger
.debug("failures : {}".format(result
.failures
))
666 if len(result
.errors
) > 0:
667 logger
.debug("errors : {}".format(result
.errors
))
669 # Additionally to the previous tests, scenario based tests will be executed.
670 # This scenario based tests are defined as directories inside the directory defined in 'test_directory'
671 for test
in descriptor_based_tests
:
672 scenario_test_folder
= test
673 test_suite
= unittest
.TestSuite()
674 test_suite
.addTest(unittest
.makeSuite(descriptor_based_scenario_test
))
675 result
= unittest
.TextTestRunner(stream
=stream
, failfast
=False).run(test_suite
)
676 executed
+= result
.testsRun
677 failed
+= len(result
.failures
) + len(result
.errors
)
678 if failfast
and failed
:
680 if len(result
.failures
) > 0:
681 logger
.debug("failures : {}".format(result
.failures
))
682 if len(result
.errors
) > 0:
683 logger
.debug("errors : {}".format(result
.errors
))
686 logger
.warning("Total number of tests: {}; Total number of failures/errors: {}".format(executed
, failed
))
687 sys
.exit(1 if failed
else 0)