RobotFramework测试用例的自行解析

RobotFramework框架提供了很多有用的开放API供我们使用,具体可以参考RobotFramework官方网站开放API

其中,下面的类和方法是比较常用的:

  • logger module for test libraries’ logging purposes.
  • deco module with decorators test libraries can utilize.
  • TestCaseFile, TestDataDirectory, and ResourceFile classes for parsing test data files and directories. In addition, a convenience factory method TestData() creates either TestCaseFileor TestDataDirectory objects based on the input.
  • TestSuite class for creating executable test suites programmatically and TestSuiteBuilderclass for creating such suites based on existing test data on the file system.
  • SuiteVisitor abstract class for processing testdata before execution. This can be used as a base for implementing a pre-run modifier that is taken into use with --prerunmodifiercommandline option.
  • ExecutionResult() factory method for reading execution results from XML output files andResultVisitor abstract class to ease further processing the results. ResultVisitor can also be used as a base for pre-Rebot modifier that is taken into use with --prerebotmodifiercommandline option.
  • ResultWriter class for writing reports, logs, XML outputs, and XUnit files. Can write results based on XML outputs on the file system, as well as based on the result objects returned by the ExecutionResult() or an executed TestSuite.

下面是一个根据RobotFramework测试运行结果的XML文件解析RobotFramework测试用例数据的示例代码:

from xml.etree import ElementTree as xet
import numpy as np
import pandas as pd
import pylab
import os
from datetime import datetime
import matplotlib
matplotlib.use("Agg")

from matplotlib import pyplot as plt

if os.name == 'posix':
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
if os.name == 'nt':
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False
plt.rcParams['savefig.dpi'] = 200
plt.rcParams['figure.dpi'] = 200


def plot_pie(sizes, labels, title, explode, file_name_to_save):

    fig, ax = plt.subplots()
    ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%', shadow=False, startangle=0)
    ax.axis('equal')
    plt.title(title, fontsize=20, fontweight='bold')
    plt.legend()
    plt.savefig(file_name_to_save, dpi=200)


def plot_bar(cat1, cat2, labels, xlabel, ylabel, title, max_y, filename, width=0.35):
    cat1 = cat1
    cat2 = cat2
    labels = labels
    x = np.arange(len(cat1))
    plt.bar(x, height=cat1, width=width, alpha=0.8, color="green", label="Passed")
    plt.bar(x, height=cat2, width=width, color="red", label="Failed", bottom=cat1)

    plt.ylim(0, max_y)

    plt.ylabel(xlabel)
    plt.xlabel(ylabel)

    plt.xticks(x, labels)
    pylab.xticks(rotation=45)

    plt.title(title)
    plt.legend()
    plt.savefig(filename, dpi=200)


def parse_rfoutput_total(root):
    for sub_child in root:
        if sub_child.text == "Critical Tests":
            labels = "Passed", "Failed"
            sizes = [sub_child.attrib['pass'], sub_child.attrib['fail']]
            explode = (0, 0.2)
            title = "Critical Tests Execute Result"
            filename = "./statistics/Critical_Tests_info.png"
            plot_pie(sizes, labels=labels, title=title, explode=explode, file_name_to_save=filename)

        if sub_child.text == "All Tests":
            labels = "Passed", "Failed"
            sizes = [sub_child.attrib['pass'], sub_child.attrib['fail']]
            explode = (0, 0.2)
            title = "All Tests Execute Result"
            filename = "./statistics/All_Tests_info.png"
            plot_pie(sizes, labels=labels, title=title, explode=explode, file_name_to_save=filename)


def parse_statistics_by_suite(root):
    labels = list()
    passed = list()
    failed = list()
    max_num = list()
    for sub_child in root:
        labels.append(sub_child.text)
        passed.append(int(sub_child.attrib['pass']))
        failed.append(int(sub_child.attrib['fail']))
        max_num.append(int(sub_child.attrib['pass']) + int(sub_child.attrib['fail']))
    print(max_num)
    plot_bar(cat1=passed, cat2=failed,
             labels=labels,
             xlabel="测试套件", ylabel="用例数量",
             title="Statistic By Suite", max_y=max(max_num),
             filename="./statistics/Statistic_By_Suite.png"
             )


def parse_statistic_by_casetags(root):
    labels = list()
    passed = list()
    failed = list()
    max_num = list()
    for sub_child in root:
        labels.append(sub_child.text)
        passed.append(int(sub_child.attrib['pass']))
        failed.append(int(sub_child.attrib['fail']))
        max_num.append(int(sub_child.attrib['pass']) + int(sub_child.attrib['fail']))
    print(max_num)
    plot_bar(cat1=passed, cat2=failed,
             labels=labels,
             xlabel="TestCase Tag", ylabel="Case Number",
             title="Statistic By Tag", max_y=max(max_num),
             filename="./statistics/Statistic_By_Tag.png"
             )


def parse_statistics_info(root):
    for child in root:
        if child.tag == "total":
            parse_rfoutput_total(child)

        if child.tag == "tag":
            parse_statistic_by_casetags(child)

        if child.tag == "suite":
            parse_statistics_by_suite(child)


def parse_testcase_tree(root):
    case_info = {
        'CaseId': root.attrib['id'],
        'CaseName': root.attrib['name'],
        'CaseTags': set(),
        'CaseStatus': None,
        'CaseStartTime': None,
        'CaseEndTime': None,
        'CaseElapsedTime': None
    }

    for child in root:
        if child.tag == "tags":
            for sub in child:
                case_info['CaseTags'].add(sub.text.strip())
        if child.tag == "status":
            case_info['CaseStatus'] = child.attrib['status']
            case_info['CaseStartTime'] = child.attrib['starttime']
            case_info['CaseEndTime'] = child.attrib['endtime']

            case_running_elapsed_time = datetime.strptime(
                case_info['CaseEndTime'], "%Y%m%d %H:%M:%S.%f"
            ) - datetime.strptime(
                case_info['CaseStartTime'], "%Y%m%d %H:%M:%S.%f"
            )
            case_info['CaseElapsedTime'] = case_running_elapsed_time.total_seconds()

    return case_info


def parse_rf_output(root, testcasetable):
    if root.tag == 'test':
        testcasetable.append(parse_testcase_tree(root))
    elif root.tag == "statistics":
        parse_statistics_info(root)
    else:
        for child in root:
            parse_rf_output(child, testcasetable)


def get_latest_test_run_ouput(sourcedir='../TestResult/', sort_by='ctime'):
    if os.path.isdir(sourcedir):
        if len(os.listdir(sourcedir)) == 0:
            raise FileNotFoundError("指定的目录中没有文件。")
        else:
            os.chdir(sourcedir)
            files = [file for file in os.listdir(sourcedir) if \
                     file.startswith('output_') and file.endswith('.xml')]
            if sort_by == 'ctime':
                files.sort(
                    key=lambda f: os.path.getctime(sourcedir + os.sep + f)
                )
            elif sort_by == 'atime':
                files.sort(
                    key=lambda f: os.path.getatime(sourcedir + os.sep + f)
                )
            elif sort_by == 'mtime':
                files.sort(
                    key=lambda f: os.path.getmtime(sourcedir + os.sep + f)
                )
            else:
                raise ValueError("排序方式不正确。")
            return files[-1]
    else:
        raise NotADirectoryError("无此目录。")


if __name__ == '__main__':
    testcasetable = list()
    # file = get_latest_test_run_ouput(sourcedir="../TestResult")
    xmltree = xet.parse("./output_183.xml")
    root = xmltree.getroot()
    parse_rf_output(root, testcasetable)
    dt = pd.DataFrame(testcasetable)
    dt.to_excel("./statistics/testcases.xlsx")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 12,136评论 0 10
  • 我在做事情的时候,孩子和我说话,我会很烦躁。 比如,我在厨房做饭,孩子在客厅玩彩泥,然后他一直喊我:妈妈,你来看,...
    秀琴sukin阅读 2,999评论 3 5
  • 我可以独自承担 一遍一遍不知厌烦 我知道自找麻烦 一次一次自我欺骗 我走了 应该还会有人 给你嘘寒问暖 我走了 应...
    谦花成都阅读 1,521评论 8 3
  • 前几天,一个小学妹在微信上问我:“学长,为什么我这么努力,绩点还是上不了3.0啊?” “你是怎样努力呢?” “基本...
    一个特立独行的大学僧阅读 5,882评论 23 28
  • 北京时间4月19日2时45分,欧冠四分之一决赛皇家马德里主场对阵德甲巨人拜仁慕尼黑,上半场双方均无建树,下半场罗本...
    白起球阅读 1,800评论 0 0