背景:公司的接口测试用例作为定时脚本运行在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
参数用来传入标签,过滤本次要运行的测试用例,可以传入多个标签,如:H5ANDP1
、H5ORMini
、NotPaid
等。
在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
Env
和Tag
都是在参数化构建时传入的,并且也有默认值,如下所示:
这样就可以减少一些无效的报错邮件了。
关于以上方案,有一点还要进行特别说明,那就是项目中测试用例之前必须是相互独立的。保持Case独立性我认为是很有必要的,每一个 Test Case 应该只测试一种场景,根据case复杂程度,不同场景同样可大可小,但不能相互影响。当系统较为庞杂时,可能会将数百上千的Cases放在一起跑,Robot框架本身不会规定Case执行的顺序,所以从某种程度上来说同一层级的Cases是随机执行的。很典型的情况就是,测试用例在本地调试时怎么跑怎么过,放到Server上所有Cases一起跑的时候就会Fail,还可能是偶发的,这种情况下就很可能是由于其他Case的痕迹影响到了它,查找问题的根源往往比较耗时。保持Case的独立性,这一点应当作为自动化用例编写规范,严格要求组内其他成员。
【To be continud...】
网友评论