murano-deployment/murano-ci/scripts/generate_html_report.py

175 lines
5.2 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.
#
from __future__ import with_statement
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"]
LOG_PATH = os.path.join(os.environ.get("STACK_HOME"), "log")
ERRORS = {
'murano-engine.log': parse_log_file(os.path.join(LOG_PATH, "murano-engine.log")),
'murano-api.log': parse_log_file(os.path.join(LOG_PATH, "murano-api.log")),
}
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 = '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=os.path.exists(
os.path.join(os.environ.get('WORKSPACE'), 'artifacts/coverage')
),
errors=ERRORS
))