美文网首页RobotframeworkWhat is SoftWare Test
Jenkins+RobotFramework 失败用例重执行方案

Jenkins+RobotFramework 失败用例重执行方案

作者: Rethink | 来源:发表于2020-07-07 14:39 被阅读0次

背景:公司的接口测试用例作为定时脚本运行在Jenkins节点上,在某些情况下,如凌晨回收机制引发的预下单失败或网络波动等,会导致用例运行失败,此时会触发邮件通知给到责任人,按照现有策略,当本次构建失败时,会立马触发第二次构建活动,若第二次构建仍然失败,则会再次触发邮件通知。在这种策略下,会导致相关邮件接收人收到一些额外的无意义邮件(如第一次构建超时,而第二次构建成功),所以就想了个办法写了脚本,在Jenkins中作为Robotframework用例的运行入口,当用例执行失败时,在所有cases执行完成后,会选择本次运行失败的case再重试一次,然后合并两次的测试报告文件。脚本内容如下:

import getopt
import os
import sys
from pathlib import Path

from robot.api import ExecutionResult

# 扩展参数,后面按照项目需要再在这里加
opts, args = getopt.getopt(sys.argv[1:], '-i:-e:-F:-E', ["includeTag=", "excludeTag=", "format=", "env="])

for opt_name, opt_value in opts:
    include_tag = opt_value if opt_name in ("-i", "--includeTag") else None  # 包含用例标签
    exclude_tag = opt_value if opt_name in ("-e", "--excludeTag") else None  # 排除用例标签
    env = opt_value if opt_name in ("-E", "--env") else "m"  # 用例运行环境
    fm = opt_value if opt_name in ("-F", "--format") else "robot"  # 用例文件后缀名

try:
    target = args[0]
except IndexError:
    target = "./"

if Path(target).is_dir():
    os.chdir(Path(target))
else:
    os.chdir(Path(target).parent)


def first_run():
    try:
        os.remove("output.xml")
        os.remove("rerun.xml")
        os.remove("report.html")
        os.remove("log.html")
    except:
        pass

    if include_tag is not None:
        cmd = r"robot -F {} -i {} -V commonVars.py:{} {}".format(fm, include_tag, env, target)
    elif exclude_tag is not None:
        cmd = r"robot -F {} -e {} -V commonVars.py:{} {}".format(fm, exclude_tag, env, target)
    else:
        cmd = r"robot -F {} -V commonVars.py:{} {}".format(fm, env, target)
    os.system(cmd)


def parse_robot_result(xml_path):
    suite = ExecutionResult(xml_path).suite

    fail = {}
    for test in suite.tests:
        if test.status == "FAIL":
            fail.update({test.name: test.status})

    all_tests = suite.statistics.critical
    print("*"*50)
    print("当前运行目录为: ", os.getcwd())
    print("总测试条数:{0}, 通过的用例数: {1}, 失败的用例数: {2}".format(all_tests.total, all_tests.passed, all_tests.failed))
    print("*" * 50)

    if all_tests.failed > 0:
        print("失败的用例为: %s" % str(fail))
        print("*" * 50)

    return all_tests.failed > 0


def rerun_fail_case():
    os.system("robot --rerunfailed output.xml --output rerun.xml {}".format(target))


def merge_output():
    os.system("rebot --merge output.xml rerun.xml")


if __name__ == '__main__':
    first_run()
    failed = parse_robot_result("output.xml")
    if failed:
        rerun_fail_case()
        merge_output()

脚本内容很简单,除-E参数外,其他都是robot提供的的命令行参数,在我的项目中,使用了变量文件,来使得用例支持切换运行环境,-E参数需要传入用例运行的环境,默认是m,即正式环境。-i-e参数用来传入标签,过滤本次要运行的测试用例,可以传入多个标签,如:H5ANDP1H5ORMiniNotPaid等。

在Jenkins项目配置中,构建操作配置的 Execute Windows Batch Cmd 如下:

cd /
cd %WORKSPACE%/ParkTest/interface
dir
C:/python37/python.exe C:/python37/Scripts/runrobot.py --env=%Env% -F robot -i %Tag% ./
exit 0

EnvTag都是在参数化构建时传入的,并且也有默认值,如下所示:

当项目第一次构建失败,但第二次构建只会运行之前失败的测试用例时,两次生成的测试报告会合并,在测试报告中展示如下:

这样就可以减少一些无效的报错邮件了。

关于以上方案,有一点还要进行特别说明,那就是项目中测试用例之前必须是相互独立的。保持Case独立性我认为是很有必要的,每一个 Test Case 应该只测试一种场景,根据case复杂程度,不同场景同样可大可小,但不能相互影响。当系统较为庞杂时,可能会将数百上千的Cases放在一起跑,Robot框架本身不会规定Case执行的顺序,所以从某种程度上来说同一层级的Cases是随机执行的。很典型的情况就是,测试用例在本地调试时怎么跑怎么过,放到Server上所有Cases一起跑的时候就会Fail,还可能是偶发的,这种情况下就很可能是由于其他Case的痕迹影响到了它,查找问题的根源往往比较耗时。保持Case的独立性,这一点应当作为自动化用例编写规范,严格要求组内其他成员。

【To be continud...】

相关文章

网友评论

    本文标题:Jenkins+RobotFramework 失败用例重执行方案

    本文链接:https://www.haomeiwen.com/subject/mqvaqktx.html