扩展RF,实现失败用例自动再执行
增加--retry选项,实现test级别的失败用例自动再执行:失败用例会重跑N次,直至成功or 耗尽重试次数,生成的日志和报告文件中只会体现最后一次执行的结果。
eg:pybot.bat --retry 3 e:\robot\test
retry设置为3,用例执行失败后会再次执行,每条用例最大执行次数为3成功后不会再执行,不加retry参数默认只执行一次。
基于RF3.0修改,修改代码如下:
1、robot/run.py
修改USAGE字符串,增加-X --retry retry xxxxxxx这一段
Options
=======
-X --retry retry set the retry count for the testcase
-N --name name Set the name of the top level test suite. Underscores
in the name are converted to spaces. Default name is
created from the name of the executed data source.
-D --doc documentation Set the documentation of the top level test suite.
Underscores in the documentation are converted to
spaces and it may also contain simple HTML formatting
(e.g. *bold* and http://url/).
增加导入模块
reload(sys) sys.setdefaultencoding('UTF-8') from xml.dom import minidom
RobotFramework类增加make方法
def make(self,outxml): xmldoc = minidom.parse(outxml) suiteElementList = xmldoc.getElementsByTagName('suite') mySuite = [] for suiteElement in suiteElementList: if suiteElement.childNodes is not None: for element in suiteElement.childNodes: if element.nodeName == 'test': mySuite.append(suiteElement) break for suite in mySuite: testElements = {} for element in suite.childNodes: if element.nodeName == 'test': name = element.getAttribute('name') if testElements.get(name) == None: testElements.update({name:[element]}) else: testElements.get(name).append(element) for n,el in testElements.iteritems(): for i in el[0:-1]: textElement = i.nextSibling suite.removeChild(i) suite.removeChild(textElement) savefile = open(outxml,'w') root = xmldoc.documentElement root.writexml(savefile) savefile.close()
修改RobotFramework类的main方法,插入self.make(settings.output)这段
def main(self, datasources, **options):
settings = RobotSettings(options)
LOGGER.register_console_logger(**settings.console_output_config)
LOGGER.info('Settings:\n%s' % unic(settings))
suite = TestSuiteBuilder(settings['SuiteNames'],
settings['WarnOnSkipped']).build(*datasources)
suite.configure(**settings.suite_config)
if settings.pre_run_modifiers:
suite.visit(ModelModifier(settings.pre_run_modifiers,
settings.run_empty_suite, LOGGER))
with pyloggingconf.robot_handler_enabled(settings.log_level):
result = suite.run(settings)
LOGGER.info("Tests execution ended. Statistics:\n%s"
% result.suite.stat_message)
self.make(settings.output)
if settings.log or settings.report or settings.xunit:
writer = ResultWriter(settings.output if settings.log
else result)
writer.write_results(settings.get_rebot_settings())
return result.return_code
2、robot/conf/settings.py
修改_cli_opts字典,增加 'Retry':('retry',1)
'MonitorColors' : ('monitorcolors', 'AUTO'), 'StdOut' : ('stdout', None), 'StdErr' : ('stderr', None), 'XUnitSkipNonCritical' : ('xunitskipnoncritical', False), 'Retry':('retry',1)}
3、robot/model/itemlist.py
替换visit方法如下
def visit(self, visitor): for item in self: if self.__module__ == 'robot.model.testcase' and hasattr(visitor,"_context"): testStatus = '' for i in range(0,int(visitor._settings._opts['Retry'])): if testStatus != 'PASS': if item.name in visitor._executed_tests: visitor._executed_tests.pop(item.name) item.visit(visitor) testStatus = visitor._context.variables['${PREV_TEST_STATUS}'] else: break else: item.visit(visitor)
4、robotide\contrib\testrunner\usages.py
修改USAGE字符串,增加-X --retry retry xxxxxxx这一段
Options
=======
-X --retry retry set the retry count for the testcase
-N --name name Set the name of the top level test suite. Underscores
in the name are converted to spaces. Default name is
created from the name of the executed data source.
-D --doc documentation Set the documentation of the top level test suite.
Underscores in the documentation are converted to
spaces and it may also contain simple HTML formatting
(e.g. *bold* and http://url/).