• 最快最便捷的pytest使用allure测试报告


    一、前言

    最近通过群友了解到了allure这个报告,开始还不以为然,但还是逃不过真香定律。

    经过试用之后,发现这个报告真的很好,很适合自动化测试结果的展示。下面说说我的探索历程吧。

    • 选用的项目为Selenium自动化测试Pytest框架实战,在这个项目的基础上说allure报告。

    二、allure安装

    • 首先安装python的allure-pytest包
    1. pip install allure-pytest
    • 然后安装allure的command命令行程序

    MacOS直接使用homebrew工具执行 brew install allure 即可安装,不用配置下载包和配置环境

    在GitHub下载安装程序https://github.com/allure-framework/allure2/releases

    但是由于GitHub访问太慢,我已经下载好并放在了群文件里面

    下载完成后解压放到一个文件夹。我的路径是D:\Program Files\allure-2.13.3

    然后配置环境变量: 在系统变量path中添加D:\Program Files\allure-2.13.3\bin,然后确定保存。

    打开cmd,输入allure,如果结果显示如下则表示成功了:

    1. C:\Users\hoou>allure
    2. Usage: allure [options] [command] [command options]
    3. Options:
    4. --help
    5. Print commandline help.
    6. -q, --quiet
    7. Switch on the quiet mode.
    8. Default: false
    9. -v, --verbose
    10. Switch on the verbose mode.
    11. Default: false
    12. --version
    13. Print commandline version.
    14. Default: false
    15. Commands:
    16. generate Generate the report
    17. Usage: generate [options] The directories with allure results
    18. Options:
    19. -c, --clean
    20. Clean Allure report directory before generating a new one.
    21. Default: false
    22. --config
    23. Allure commandline config path. If specified overrides values from
    24. --profile and --configDirectory.
    25. --configDirectory
    26. Allure commandline configurations directory. By default uses
    27. ALLURE_HOME directory.
    28. --profile
    29. Allure commandline configuration profile.
    30. -o, --report-dir, --output
    31. The directory to generate Allure report into.
    32. Default: allure-report
    33. serve Serve the report
    34. Usage: serve [options] The directories with allure results
    35. Options:
    36. --config
    37. Allure commandline config path. If specified overrides values from
    38. --profile and --configDirectory.
    39. --configDirectory
    40. Allure commandline configurations directory. By default uses
    41. ALLURE_HOME directory.
    42. -h, --host
    43. This host will be used to start web server for the report.
    44. -p, --port
    45. This port will be used to start web server for the report.
    46. Default: 0
    47. --profile
    48. Allure commandline configuration profile.
    49. open Open generated report
    50. Usage: open [options] The report directory
    51. Options:
    52. -h, --host
    53. This host will be used to start web server for the report.
    54. -p, --port
    55. This port will be used to start web server for the report.
    56. Default: 0
    57. plugin Generate the report
    58. Usage: plugin [options]
    59. Options:
    60. --config
    61. Allure commandline config path. If specified overrides values from
    62. --profile and --configDirectory.
    63. --configDirectory
    64. Allure commandline configurations directory. By default uses
    65. ALLURE_HOME directory.
    66. --profile
    67. Allure commandline configuration profile.

    三、allure初体验

    改造一下之前的测试用例代码

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import re
    4. import pytest
    5. import allure
    6. from utils.logger import log
    7. from common.readconfig import ini
    8. from page_object.searchpage import SearchPage
    9. @allure.feature("测试百度模块")
    10. class TestSearch:
    11. @pytest.fixture(scope='function', autouse=True)
    12. def open_baidu(self, drivers):
    13. """打开百度"""
    14. search = SearchPage(drivers)
    15. search.get_url(ini.url)
    16. @allure.story("搜索selenium结果用例")
    17. def test_001(self, drivers):
    18. """搜索"""
    19. search = SearchPage(drivers)
    20. search.input_search("selenium")
    21. search.click_search()
    22. result = re.search(r'selenium', search.get_source)
    23. log.info(result)
    24. assert result
    25. @allure.story("测试搜索候选用例")
    26. def test_002(self, drivers):
    27. """测试搜索候选"""
    28. search = SearchPage(drivers)
    29. search.input_search("selenium")
    30. log.info(list(search.imagine))
    31. assert all(["selenium" in i for i in search.imagine])
    32. if __name__ == '__main__':
    33. pytest.main(['TestCase/test_search.py', '--alluredir', './allure'])
    34. os.system('allure serve allure')

    然后运行一下:

    注意:如果你使用的是pycharm编辑器,请跳过该运行方式,直接使用.bat.sh的方式运行

    1. ***
    2. ------------------------------- generated html file: file://C:\Users\hoou\PycharmProjects\web-demotest\report.html --------------------------------
    3. Results (12.97s):
    4. 2 passed
    5. Generating report to temp directory...
    6. Report successfully generated to C:\Users\hoou\AppData\Local\Temp\112346119265936111\allure-report
    7. Starting web server...
    8. 2020-06-18 22:52:44.500:INFO::main: Logging initialized @1958ms to org.eclipse.jetty.util.log.StdErrLog
    9. Server started at . Press to exit

    命令行会出现如上提示,接着浏览器会自动打开:

    点击左下角En即可选择切换为中文。

    是不是很清爽很友好,比pytest-html更舒服。

    四、allure装饰器介绍

    五、报告的生成和展示

    刚才的两个命令:

    • 生成allure原始报告到report/allure目录下,生成的全部为json或txt文件。
    1. pytest TestCase/test_search.py --alluredir ./allure
    • 在一个临时文件中生成报告并启动浏览器打开
    1. allure serve allure

    但是在关闭浏览器之后这个报告就再也打不开了。不建议使用这种。

    所以我们必须使用其他的命令,让allure可以指定生成的报告目录。

    我们在项目的根目录中创建run_case.py文件,内容如下:

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import sys
    4. import subprocess
    5. WIN = sys.platform.startswith('win')
    6. def main():
    7. """主函数"""
    8. steps = [
    9. "venv\\Script\\activate" if WIN else "source venv/bin/activate",
    10. "pytest --alluredir allure-results --clean-alluredir",
    11. "allure generate allure-results -c -o allure-report",
    12. "allure open allure-report"
    13. ]
    14. for step in steps:
    15. subprocess.run("call " + step if WIN else step, shell=True)
    16. if __name__ == "__main__":
    17. main()

    命令释义:

    1、使用pytest生成原始报告,里面大多数是一些原始的json数据,加入--clean-alluredir参数清除allure-results历史数据。

    1. pytest --alluredir allure-results --clean-alluredir
    • --clean-alluredir 清除allure-results历史数据

    2、使用generate命令导出HTML报告到新的目录

    1. allure generate allure-results -o allure-report
    • -c 在生成报告之前先清理之前的报告目录
    • -o 指定生成报告的文件夹

    3、使用open命令在浏览器中打开HTML报告

    1. allure open allure-report

    好了我们运行一下该文件。

    1. Results (12.85s):
    2. 2 passed
    3. Report successfully generated to c:\Users\hoou\PycharmProjects\web-demotest\allure-report
    4. Starting web server...
    5. 2020-06-18 23:30:24.122:INFO::main: Logging initialized @260ms to org.eclipse.jetty.util.log.StdErrLog
    6. Server started at 172.18.47.241:7932/>. Press to exit

    可以看到运行成功了。

    在项目中的allure-report文件夹也生成了相应的报告。

    六、allure发生错误截图

    上面的用例全是运行成功的,没有错误和失败的,那么发生了错误怎么样在allure报告中生成错误截图呢,我们一起来看看。

    首先我们先在config/conf.py文件中添加一个截图目录和截图文件的配置。

    1. +++
    2. class ConfigManager(object):
    3. ...
    4. @property
    5. def screen_path(self):
    6. """截图目录"""
    7. screenshot_dir = os.path.join(self.BASE_DIR, 'screen_capture')
    8. if not os.path.exists(screenshot_dir):
    9. os.makedirs(screenshot_dir)
    10. now_time = dt_strftime("%Y%m%d%H%M%S")
    11. screen_file = os.path.join(screenshot_dir, "{}.png".format(now_time))
    12. return now_time, screen_file
    13. ...
    14. +++

    然后我们修改项目目录中的conftest.py

    1. #!/usr/bin/env python3
    2. # -*- coding:utf-8 -*-
    3. import base64
    4. import pytest
    5. import allure
    6. from py.xml import html
    7. from selenium import webdriver
    8. from config.conf import cm
    9. from common.readconfig import ini
    10. from utils.times import timestamp
    11. from utils.send_mail import send_report
    12. driver = None
    13. @pytest.fixture(scope='session', autouse=True)
    14. def drivers(request):
    15. global driver
    16. if driver is None:
    17. driver = webdriver.Chrome()
    18. driver.maximize_window()
    19. def fn():
    20. driver.quit()
    21. request.addfinalizer(fn)
    22. return driver
    23. @pytest.hookimpl(hookwrapper=True)
    24. def pytest_runtest_makereport(item):
    25. """
    26. 当测试失败的时候,自动截图,展示到html报告中
    27. :param item:
    28. """
    29. pytest_html = item.config.pluginmanager.getplugin('html')
    30. outcome = yield
    31. report = outcome.get_result()
    32. report.description = str(item.function.__doc__)
    33. extra = getattr(report, 'extra', [])
    34. if report.when == 'call' or report.when == "setup":
    35. xfail = hasattr(report, 'wasxfail')
    36. if (report.skipped and xfail) or (report.failed and not xfail):
    37. screen_img = _capture_screenshot()
    38. if screen_img:
    39. html = '
      screenshot \
    40. 'onclick="window.open(this.src)" align="right"/>
      ' % screen_img
  • extra.append(pytest_html.extras.html(html))
  • report.extra = extra
  • def pytest_html_results_table_header(cells):
  • cells.insert(1, html.th('用例名称'))
  • cells.insert(2, html.th('Test_nodeid'))
  • cells.pop(2)
  • def pytest_html_results_table_row(report, cells):
  • cells.insert(1, html.td(report.description))
  • cells.insert(2, html.td(report.nodeid))
  • cells.pop(2)
  • def pytest_html_results_table_html(report, data):
  • if report.passed:
  • del data[:]
  • data.append(html.div('通过的用例未捕获日志输出.', class_='empty log'))
  • def pytest_html_report_title(report):
  • report.title = "pytest示例项目测试报告"
  • def pytest_configure(config):
  • config._metadata.clear()
  • config._metadata['测试项目'] = "测试百度官网搜索"
  • config._metadata['测试地址'] = ini.url
  • def pytest_html_results_summary(prefix, summary, postfix):
  • # prefix.clear() # 清空summary中的内容
  • prefix.extend([html.p("所属部门: XX公司测试部")])
  • prefix.extend([html.p("测试执行人: 随风挥手")])
  • def pytest_terminal_summary(terminalreporter, exitstatus, config):
  • """收集测试结果"""
  • result = {
  • "total": terminalreporter._numcollected,
  • 'passed': len(terminalreporter.stats.get('passed', [])),
  • 'failed': len(terminalreporter.stats.get('failed', [])),
  • 'error': len(terminalreporter.stats.get('error', [])),
  • 'skipped': len(terminalreporter.stats.get('skipped', [])),
  • # terminalreporter._sessionstarttime 会话开始时间
  • 'total times': timestamp() - terminalreporter._sessionstarttime
  • }
  • print(result)
  • if result['failed'] or result['error']:
  • send_report()
  • def _capture_screenshot():
  • """截图保存为base64"""
  • now_time, screen_file = cm.screen_path
  • driver.save_screenshot(screen_file)
  • allure.attach.file(screen_file,
  • "失败截图{}".format(now_time),
  • allure.attachment_type.PNG)
  • with open(screen_file, 'rb') as f:
  • imagebase64 = base64.b64encode(f.read())
  • return imagebase64.decode()
  • 来看看我们修改了什么:

    • 我们修改了_capture_screenshot函数

    在里面我们使用了webdriver截图生成文件,并使用allure.attach.file方法将文件添加到了allure测试报告中。

    并且我们还返回了图片的base64编码,这样可以让pytest-html的错误截图和allure都能生效。

    运行一次得到两份报告,一份是简单的一份是好看内容丰富的。

    现在我们在测试用例中构建一个预期的错误测试一个我们的这个代码。


    修改test_002测试用例

    1. assert not all(["selenium" in i for i in search.imagine])

    运行一下:

    可以看到allure报告中已经有了这个错误的信息。

    再来看看pytest-html中生成的报告:

    可以看到两份生成的报告都附带了错误的截图,真是鱼和熊掌可以兼得呢。

    好了,到这里可以说allure的报告就先到这里了,以后发现allure其他的精彩之处我再来分享。

    B站最牛的Python自动化测试框架全栈测试开发实战项目入门到精通,涨薪必备教程!!!

     

  • 相关阅读:
    音频处理:Acon Digital Acoustica Premium Mac
    PowerBI依据字段取一列从小到大的第三个值(没三个值取第二个,第二个没有取第一个)
    C++ STL 概述_严丝合缝的合作者们
    Blob 文件下载对应的常见 MIME 类型列表
    浅谈vue的自定义指令
    一张图读懂TuGraph Analytics开源技术架构
    Bash脚本debug攻略
    nginx学习(2)
    GitHub价值1w的Java最新面试宝典(附答案解析)被我弄到手了
    想提高跨境电商转化率?采用这几个技巧!
  • 原文地址:https://blog.csdn.net/m0_68405758/article/details/128123062