nose测试中修改nose_html_reporting插件,使生成的html报告加入显示截图功能
使用nose框架在测试WEB UI自动化时,使用了第三方插件nose-html-reporting,来生成HTML报告,nose-html-reporting具体使用参见管网https://pypi.python.org/pypi/nose-html-reporting
但在真实使用测试时,经常会将错误截图,但nose-html-reporting只显示错误日志,不太直观,怎么将错误截图也加入到HMTL报告中呢,google了一把也没有答案。那就自己动手吧。
一、首先看看原始的报告,如下
二、需求
我们加一列在失败或错误时,有图片链接,在成功时没有。
解决思路:从截图存储的文件夹中,遍历与测试名称一致的文件,如果有,则显示链接,没有则空。
三、实现
先看看nose_html_reporting插件怎么实现输出HTML的
安装好插件后,查看对应的目录,只有__init__.py和template/report.html、template/report2.jinja2几个文件
在查看__int__.py文件后,从下面两段代码中,我们可以知道,html是通过report2.jinja2模板生成的
parser.add_option( '--html-report-template', action='store', dest='html_template', metavar="FILE", default=env.get('NOSE_HTML_TEMPLATE_FILE', os.path.join(os.path.dirname(__file__), "templates", "report2.jinja2")), help="Path to html template file in with jinja2 format." "Default is report.html in the lib sources" "[NOSE_HTML_TEMPLATE_FILE]") ...... self.stats['total'] = sum(self.stats.values()) for group in self.report_data.values(): group.stats['total'] = sum(group.stats.values()) self.report_file.write(self.jinja.get_template(os.path.basename(self.report_template_filename)).render( report=self.report_data, stats=self.stats, rawoutput=self._format_output(self.complete_global_output()) ))
1、修改report2.jinja2模版,加入可以显示链接的一列
我们在time后面加一列,用于显示错误图片链接,红色行。
<tr id='{{ class + test.name }}' class='testcase'> <td class="{{ test_status.lower() }}Case"> {{ test.name }} {% if test.shortDescription %} <div class="shortDescription"> {{ test.shortDescription }} </div> {% endif %} </td> <td>{{ test.time }}</td> <td><p><a href="{{test.dir}}\{{test.snap}}">{{ test.snap }}</a></td> <td colspan='4' align='center'> <!--css div popup start-->
2、修改__init__.py文件,传入截图存储文件夹参数及处理图片链接参数
加入截图文件夹options参数
def options(self, parser, env): """Sets additional command line options.""" Plugin.options(self, parser, env) parser.add_option( '--html-report', action='store', dest='html_file', metavar="FILE", default=env.get('NOSE_HTML_FILE', 'nosetests.html'), help="Path to html file to store the report in. " "Default is nosetests.html in the working directory " "[NOSE_HTML_FILE]") parser.add_option( '--html-report-template', action='store', dest='html_template', metavar="FILE", default=env.get('NOSE_HTML_TEMPLATE_FILE', os.path.join(os.path.dirname(__file__), "templates", "report2.jinja2")), help="Path to html template file in with jinja2 format." "Default is report.html in the lib sources" "[NOSE_HTML_TEMPLATE_FILE]") parser.add_option( '--snap-dir', action='store', dest='snap_dir', metavar="FILE", default="c:\\report", help="snap-dir.")
def configure(self, options, config): """Configures the xunit plugin.""" Plugin.configure(self, options, config) self.config = config if self.enabled: self.jinja = Environment( loader=FileSystemLoader(os.path.dirname(options.html_template)), trim_blocks=True, lstrip_blocks=True ) self.stats = {'errors': 0, 'failures': 0, 'passes': 0, 'skipped': 0} self.report_data = defaultdict(Group) htmlfile_dirname = os.path.dirname(options.html_file) if not os.path.exists(os.path.abspath(htmlfile_dirname)): os.makedirs(htmlfile_dirname) self.report_file = codecs.open(options.html_file, 'w', self.encoding, 'replace') self.report_template_filename = options.html_template self.snap_dir = options.snap_dir
修改错误和fail时,加入图片文件名
def addError(self, test, err, capt=None): """Add error output to Xunit report. """ exc_type, exc_val, tb = err tb = ''.join(traceback.format_exception( exc_type, exc_val if isinstance(exc_val, exc_type) else exc_type(exc_val), tb )) name = id_split(test.id()) group = self.report_data[name[0]] if issubclass(err[0], SkipTest): type = 'skipped' self.stats['skipped'] += 1 group.stats['skipped'] += 1 else: type = 'error' self.stats['errors'] += 1 group.stats['errors'] += 1 group.tests.append({ 'name': name[-1], 'failed': True, 'type': type, 'dir':self.snap_dir, 'errtype': nice_classname(err[0]), 'message': exc_message(err), 'tb': self._format_output(tb), 'output': self._format_output(self.complete_test_output(exc_message(err), tb)), 'shortDescription': test.shortDescription(), 'time': str(datetime.now() - self.test_start_time), 'snap': "".join([x for x in os.listdir(self.snap_dir) if x==name[-1]]), })
def addFailure(self, test, err, capt=None): """Add failure output to Xunit report. """ exc_type, exc_val, tb = err tb = ''.join(traceback.format_exception( exc_type, exc_val if isinstance(exc_val, exc_type) else exc_type(exc_val), tb )) name = id_split(test.id()) group = self.report_data[name[0]] self.stats['failures'] += 1 group.stats['failures'] += 1 group.tests.append({ 'name': name[-1], 'failed': True, 'dir':self.snap_dir, 'errtype': nice_classname(err[0]), 'message': exc_message(err), 'tb': self._format_output(tb), 'output': self._format_output(self.complete_test_output(exc_message(err), tb)), 'shortDescription': test.shortDescription(), 'time': str(datetime.now() - self.test_start_time), 'snap': "".join([x for x in os.listdir(self.snap_dir) if x==name[-1]]), })
四、测试使用
修改完__init__.py后,我们通过nosetests -h,我们可以看到多了一个参数:
首先写个测试程序,如下:
#coding:utf-8 from selenium import webdriver import inspect driver = webdriver.Firefox() def test_001(): assert 2==1 def test_0002(): assert 3==1 def test_learn_3(): try: driver.get("http://www.baidu.com") driver.find_element_by_id("xx") except Exception,e: driver.get_screenshot_as_file("c:\\report_1\\%s" % (inspect.stack()[0][3])) raise
在使用nose测试,因为在刚刚的程序中,我们截图保存在c:\\report_1这个目录,所以测试使用如下:
C:\>nosetests -v nose_test.py --with-html --snap-dir="c:\report_1"
最后生成的HTML报告如下:
time后面多了一列,是失败时的截图链接,点击test_lean_3后,浏览器会自动跳转至截图显示。
大功告成。。。。。。
在实际的自动化代码中,你还需要加入清理资源的功能,把截图都清理或移至其它地方,不然截图会覆盖或显示上次结果
cnblogs不能上传附件,如果需要源码,可以联系我。
-----后期优化了下,把jinja2模板改了下,直接在html中显示缩略图,链接显示大图
{% if test_status == 'Fail' or test_status == 'Error' %} <td><p><a href="{{test.dir}}\{{test.snap}}" title="link to datu"><img src="{{test.dir}}\{{test.snap}}" width="165" height="60" /></a></p></td> {%- endif %}