Files
murano-dashboard/functional_tests/generate_html_report.py
Hervé Beraud ffa6f6d449 Stop to use the __future__ module.
The __future__ module [1] was used in this context to ensure compatibility
between python 2 and python 3.

We previously dropped the support of python 2.7 [2] and now we only support
python 3 so we don't need to continue to use this module and the imports
listed below.

Imports commonly used and their related PEPs:
- `division` is related to PEP 238 [3]
- `print_function` is related to PEP 3105 [4]
- `unicode_literals` is related to PEP 3112 [5]
- `with_statement` is related to PEP 343 [6]
- `absolute_import` is related to PEP 328 [7]

[1] https://docs.python.org/3/library/__future__.html
[2] https://governance.openstack.org/tc/goals/selected/ussuri/drop-py27.html
[3] https://www.python.org/dev/peps/pep-0238
[4] https://www.python.org/dev/peps/pep-3105
[5] https://www.python.org/dev/peps/pep-3112
[6] https://www.python.org/dev/peps/pep-0343
[7] https://www.python.org/dev/peps/pep-0328

Change-Id: I8c157362068ea229df9e9ec39d9f56d9ad4836fe
2020-06-02 20:26:48 +02:00

163 lines
4.9 KiB
Python

#!/usr/bin/python
# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
import jinja2
import lxml.etree as et
import uuid
import sys
import os
import re
if not __name__ == "__main__":
sys.exit(1)
if not len(sys.argv) >= 3:
sys.exit(1)
if not os.path.exists(sys.argv[1]):
sys.exit(1)
LOG_LINE_PATTERN = "^(?P<date>20[0-9]{2}\-[0-9]{2}\-[0-9]{2}) (?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]+) (?P<pid>[0-9]+) (?P<level>[A-Z]+) (?P<package>.*?) \[\-\](?P<log>.*?)$"
def get_attr(element, attr):
return element.attrib[attr] if attr in element.attrib.keys() else None
def parse_log_file(log_file_path):
LOG_RECORDS = []
LAST_LOG_ENTRY = None
with open(log_file_path, 'r') as log_file:
for line in log_file.readlines():
match = re.match(LOG_LINE_PATTERN, line, re.S)
if match:
LAST_LOG_ENTRY = {
'date': match.group('date'),
'time': match.group('time'),
'pid': match.group('pid'),
'level': match.group('level'),
'package': match.group('package'),
'log': match.group('log')
}
LOG_RECORDS.append(LAST_LOG_ENTRY)
elif LAST_LOG_ENTRY is not None:
LAST_LOG_ENTRY['log'] += line
return [log_record for log_record in LOG_RECORDS if log_record['level'] == "ERROR"]
STATS = {
'total': 0,
'success': 0,
'skip': 0,
'error': 0,
'failure': 0,
}
REPORT = {}
et.set_default_parser(et.XMLParser(huge_tree=True))
tree = et.parse(sys.argv[1])
root = tree.getroot()
STATS['total'] = int(root.attrib['tests'])
STATS['failure'] = int(root.attrib['failures'])
STATS['error'] = int(root.attrib['errors'])
STATS['skip'] = int(root.attrib['skip'])
STATS['unsuccess'] = STATS['failure'] + STATS['error'] + STATS['skip']
STATS['success'] = STATS['total'] - STATS['unsuccess']
for case in root:
class_name = case.attrib['classname']
screenshot_file = 'logs/artifacts/screenshots/%s.png' % case.attrib['name']
screenshot_path = os.path.join(
os.environ.get('WORKSPACE'),
screenshot_file
)
test = {
'name': case.attrib['name'],
'time': case.attrib['time'],
'result': 'success',
'exc_type': None,
'exc_message': None,
'traceback': None,
'output': case.text,
'uuid': str(uuid.uuid1()),
'screenshot': None
}
for child in case:
test['exc_type'] = get_attr(child, 'type')
test['exc_message'] = get_attr(child, 'message')
test['traceback'] = child.text
if child.tag == 'error':
test['result'] = 'error'
if os.path.exists(screenshot_path):
test['screenshot'] = screenshot_file
elif child.tag == 'failure':
test['result'] = 'failure'
if os.path.exists(screenshot_path):
test['screenshot'] = screenshot_file
elif child.tag == 'skipped':
test['result'] = 'skip'
if class_name not in REPORT.keys():
REPORT[class_name] = {
'tests': [],
'stats': {
'total': 0,
'failure': 0,
'error': 0,
'skip': 0,
'success': 0,
},
'result': 'success',
'uuid': str(uuid.uuid1()),
}
REPORT[class_name]['tests'].append(test)
REPORT[class_name]['stats']['total'] += 1
REPORT[class_name]['stats'][test['result']] += 1
TOTAL = REPORT[class_name]['stats']['total']
for class_name in REPORT.keys():
if REPORT[class_name]['stats']['failure'] > 0:
REPORT[class_name]['result'] = 'failure'
elif REPORT[class_name]['stats']['error'] > 0:
REPORT[class_name]['result'] = 'failure'
elif REPORT[class_name]['stats']['skip'] == TOTAL:
REPORT[class_name]['result'] = 'skip'
else:
REPORT[class_name]['result'] = 'success'
jinja = jinja2.Environment(
loader=jinja2.FileSystemLoader(os.path.join(
os.path.dirname(__file__), 'templates')
)
)
with open(sys.argv[2], 'w') as report_file:
report_file.write(jinja.get_template(
os.path.basename('report.template')
).render(
report=REPORT,
stats=STATS,
coverage=False,
))