python解析Robot 3.1 (Python 2.7.16 on win32)

46 阅读1分钟
  • robot==20071211
  • robotframework==3.1.2
# parse_output_xml_rf31.py —— 专为 Robot Framework 3.1 output.xml
from robot.api import ExecutionResult
import json
import os

def parse_output_xml(xml_path, output_json_path):
    result = ExecutionResult(xml_path)
    output_data = {
        "suite": extract_suite(result.suite),
        "statistics": extract_statistics(result.statistics),
        "errors": extract_errors(result.errors)
    }
    with open(output_json_path, 'w', encoding='utf-8') as f:
        json.dump(output_data, f, indent=2, ensure_ascii=False, default=str)
    print("✅ RF 3.1 output.xml 解析完成: %s" % os.path.abspath(output_json_path))

def extract_suite(suite):
    return {
        "name": suite.name,
        "doc": suite.doc,
        "source": getattr(suite, 'source', None),
        "start_time": suite.starttime,
        "end_time": suite.endtime,
        "elapsed_time": str(suite.elapsedtime),
        "status": suite.status,
        "message": suite.message,
        "metadata": dict(suite.metadata) if hasattr(suite, 'metadata') else {},
        "tests": [extract_test(test) for test in suite.tests],
        "suites": [extract_suite(s) for s in suite.suites],
        "keywords": extract_keywords(suite.keywords)  # ← RF 3.1 用 .keywords
    }

def extract_test(test):
    return {
        "name": test.name,
        "doc": test.doc,
        "tags": list(test.tags),
        "start_time": test.starttime,
        "end_time": test.endtime,
        "elapsed_time": str(test.elapsedtime),
        "status": test.status,
        "message": test.message,
        "keywords": extract_keywords(test.keywords)  # ← RF 3.1 用 .keywords
    }

def extract_keywords(keywords):
    if not hasattr(keywords, '__iter__'):
        return []
    kw_list = []
    for kw in keywords:
        kw_data = {
            "name": kw.name,
            "type": getattr(kw, 'type', 'KEYWORD'),
            "status": kw.status,
            "start_time": kw.starttime,
            "end_time": kw.endtime,
            "elapsed_time": str(kw.elapsedtime),
            "message": kw.message,
            "args": list(kw.args) if hasattr(kw, 'args') else [],
            "assign": list(kw.assign) if hasattr(kw, 'assign') else [],
            "keywords": extract_keywords(kw.keywords)  # ← 递归
        }
        kw_list.append(kw_data)
    return kw_list

def extract_statistics(statistics):
    stats = {"total": {}, "tags": {}, "suites": {}}
    if hasattr(statistics, 'total'):
        try:
            crit = statistics.total.critical
            alls = statistics.total.all
            stats["total"] = {
                "critical": {"passed": crit.passed, "failed": crit.failed, "total": crit.total},
                "all": {"passed": alls.passed, "failed": alls.failed, "total": alls.total}
            }
        except AttributeError:
            stats["total"] = {
                "all": {
                    "passed": getattr(statistics.total, 'passed', 0),
                    "failed": getattr(statistics.total, 'failed', 0),
                    "total": getattr(statistics.total, 'total', 0)
                }
            }
    if hasattr(statistics, 'tags'):
        stats["tags"] = {
            tag.name: {"passed": tag.passed, "failed": tag.failed, "total": tag.total}
            for tag in statistics.tags
        }
    return stats

def extract_errors(errors):
    return [{"timestamp": msg.timestamp, "level": msg.level, "message": msg.message} for msg in errors.messages]

if __name__ == '__main__':
    path = '/home/automan/script/my_script/output.xml'
    parse_output_xml(path, 'parsed_output_context.json')