robotframework如何提取失败的测试,以便下次运行
目录
robotframework如何提取失败的测试,以便下次运行
思路
robotframework在运行的结果中会生成一个output.xml文件,只要通过分析这个文件就可以获得所有失败状态下的测试的名称,获得名称后,将这些名称通过写入参数文件中,然后下次运行生成的参数文件就可以了
下面是我写的提取失败测试名称到参数文件的一个脚本:parse_fail_test.py,另外分享一个小技巧,可以直接借助于robotframework强大的参数处理机制,从而避免过多参数处理操作:
#!/usr/bin/env python
# encoding: utf-8
"""用于提取失败的测试,以便下次直接运行失败的测试
使用方法: parse_fail_test.py [options] input_files
输入一个或者多个测试输出xml文件,如默认生成的output.xml,最终得到一个用于下次跑失败测试的配置
文件.
选项:
-f --file file 最终生成的配置文件,如果不指定名字默认为args.txt文件
-n --name name * 输入的文件名字,如果使用了参数,那么只能够放在最前面,不
带参数的全部认为是输入文件.不带参数和带参数一起使用也没问题的
-r --report name 设置参数文件生成的下次运行脚本时的报告名称
? 输出帮助信息.
标有*号的参数是可以带多个参数的.
例子:
$ parse_fail_test.py output1.xml output2.xml output3.xml
$ parse_fail_test.py --report 重新跑失败测试报告 -f fail_run_args.txt output1.xml output2.xml
"""
import os
import sys
import inspect
from xml.etree import ElementTree
from robot.utils import ArgumentParser
from robot.errors import DataError, Information
def _to_str(unicode_or_str):
''' 将unicode字符串转换为str类型
'''
if isinstance(unicode_or_str, unicode):
value = unicode_or_str.encode('utf-8')
else:
value = unicode_or_str
return value
def _get_failed_test_name(input_file):
'''提供一个需要分析测试结果文件,获得失败的测试用例的名字
'''
with open(input_file, 'r') as f:
tree = ElementTree.parse(f)
for test in tree.getiterator('test'):
if test.find('status').attrib.get('status') == 'FAIL':
yield _to_str(test.attrib.get('name'))
def _write_args(file_name,inputfiles):
'''指定要产生的参数文件名字,以及对应失败的output.xml文件,
可以同时放入多个output.xml
'''
if not isinstance(inputfiles,list) :
_exit(u'%s中传入write_args方法的参数不正确'%inspect.stack()[1][3], error=True)
#获得所有的失败测试,然后生成参数文件,注意去掉重复的失败测试名字
fail_test_set = set()
for input_file in inputfiles:
fail_tests = _get_failed_test_name(input_file)
if fail_tests:
for test in fail_tests:
fail_test_set.add(test)
with open(file_name, 'w') as f:
for uniq_test in fail_test_set:
f.write('--test '+ uniq_test +'\n')
def _get_paths(opts, paths):
'''解析参数获得所有的输入文件,返回文件列表
'''
if not opts['name'] and not paths:
_exit(u'没有输入要提取的文件', error=True)
all_paths = paths
all_paths.extend(opts['name'])
return all_paths
def main(args):
opts, paths = _process_args(args)
if '?' in paths :
print __doc__
sys.exit()
all_paths = _get_paths(opts, paths)
arg_file_name = opts['file'] or 'args.txt'
report_name = opts['report'] or u'下次运行时的报告名称'
#清理可能已经存在的参数文件
if os.path.exists(arg_file_name):
os.remove(arg_file_name)
_write_args(arg_file_name, all_paths)
#如果传入的文件没有分析得到失败的case,那就没有必要生成最后的参数文件了
if os.path.exists(arg_file_name):
with open(arg_file_name, 'a') as f:
f.write('--loglevel DEBUG\n')
f.write('--reporttitle '+_to_str(report_name)+'\n')
else:
_exit(u'传入的文件没有失败的测试', error=True)
def _process_args(cliargs):
'''解析参数
'''
ap = ArgumentParser(__doc__, arg_limits=(0, ))
try:
return ap.parse_args(cliargs)
except Information, msg:
_exit(msg)
except DataError, err:
_exit(err, error=True)
def _exit(msg, error=False):
print unicode(msg)
if error:
print u"\n请用 '?' 命令查看帮助文档."
sys.exit(int(error))
if __name__ == '__main__':
main(sys.argv[1:])