一、allure简介
Allure框架是一个灵活轻量级多语言测试报告工具,它不仅可以以WEB的方式展示简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。Allure报告简化了常见缺陷的统计:失败的测试可以分为BUG和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
从开发/测试的角度来看:
- Allure报告可以快速查看到缺陷点,可以将测试未通过划分为Bug和中断的测试。还可以配置日志,步骤,固件,附件,时间,历史记录,以及与TMS的集成和Bug跟踪系统,以便掌握所有信息。
从管理者的角度来看:
- Allure提供了一个清晰的全局,涵盖了所涵盖的功能,缺陷聚集的位置,执行时间表,以及许多其他方便的事情。独特的模块化和可扩展性,确保你能够进行适当的微调,以使更适合你自己。
二、安装
2.1.命令行安装:
在pytest中集成allure的依赖安装:
在命令行中运行以下命令进行安装:
pip install allure-pytest
或者(使用国内的豆瓣源,数据会定期同步国外官网,速度快。)
pip install allure-pytest -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
2.2.安装allure插件
Allure 是一个命令行工具,可以下载后进行环境变量配置。下载地址:https://github.com/allure-framework/allure2/releases,如下图:
allure的运行需要java8+,JDK 1.8+环境,所以提前配置好java环境,将安装包解压后配置allure环境变量,在系统变量path中添:
D:\allure-2.21.0
配置成功后在命令窗口输入allure或者allure --version,可以看到我的allure版本是2.21.0
三、allure在pytest框架中的应用
要使allure侦听器能够在测试执行过程中收集结果,只需添加 --alluredir 选项并提供路径即可存储结果。
pytest --alluredir=<directory-with-results>
如果你运行后进行了用例更改,那么下次运行可能还是会查看到之前记录,可添加 --clean-alluredir 选项清除之前记录。
pytest --alluredir=<directory-with-results> --clean-alluredir
要在测试完成后查看实际报告,你需要使用allure命令行应用程序从结果生成报告。
(1)在默认浏览器中显示生成的报告
allure serve <my-allure-results>
(2)要从现有的Allure结果生成报告,可以使用以下命令:
allure generate <directory-with-results>
默认报告将生成到allure-report文件夹,你可以使用 -o 标志更改目标文件夹:
allure generate <directory-with-results>
(3)生成报告后,可以在默认系统浏览器中将其打开,只需运行:
allure open <directory-with-report>
你也可以找到该目录,使用浏览器打开该目录下index.html。注意:有时打开会找不到数据或者乱码,如果你使用的是pycharm,请在pycharm中右击打开。完整的案例执行如下:
# 执行test_case包下的用例,生成执行信息到根目录下的logs中
pytest ./test_case/ --alluredir=./outfile/logs --clean-alluredir
# 默认报告将生成
allure generate ./outfile/logs -o ./outfile/report --clean
说明:
- 指定在根目录test_case包下加载测试用例,执行后产生的json信息存放在./outfile/logs中
- 根据./outfile/logs中的执行信息生成测试报告,存放在./outfile/report目录中
四、allure中常见装饰器
allure中常见的装饰器有一下几个:
4.1.@allure.feature注解
@allure.feature :用于定义被测试的功能,被测产品的需求点,如下在测试用例类前面加上注解:
import time
import allure
@allure.feature("购物车")
class Test_pass01:
def test_01(self):
print('********用例01********')
time.sleep(1)
assert 1 == 1
@allure.feature("订单功能")
class Test_pass02:
def test_04(self):
print('********用例01********')
time.sleep(1)
assert 1 == 1
@allure.feature("支付功能")
class Test_pass03:
def test_07(self):
print('********用例01********')
time.sleep(1)
assert 1 == 1
执行生成测试报告,显示如下:
4.2.@allure.story注解
@allure.story
:使用该装饰器可以为被测试的功能点定义一个用户场景或子功能点(story)。在测试报告中,用户场景将作为特性下的子分类,用于更详细地描述测试用例。准备代码如下:
import time
import allure
@allure.feature("购物车")
class Test_pass01:
@allure.story("添加购物车")
def test_01(self):
print('********用例01********')
time.sleep(1)
assert 1 == 1
@allure.story("删除购物车")
def test_02(self):
print('********用例02********')
time.sleep(1)
assert 2 == 2
@allure.story("修改购物车")
def test_03(self):
print('********用例03********')
time.sleep(1)
assert 2 == 2
执行生成测试报告,如下会显示用户场景或者子功能点:
4.3.@allure.step
@allure.step
:使用该装饰器可以将一个测试用例分成多个步骤(steps),并在测试报告中按步骤展示。这有助于更详细地描述测试过程和测试步骤。创建测试代码test_case04.py代码如下:
import allure
@allure.step("步骤1:打开登录页面")
def open_login_page():
print("打开登录页面的代码")
@allure.step("步骤2:输入用户名和密码")
def enter_username_and_password():
print("输入用户名和密码的代码")
@allure.step("步骤3:点击登录按钮")
def click_login_button():
print("点击登录按钮的代码")
@allure.step("步骤4:验证登录成功")
def verify_login_success():
print("验证登录成功的代码")
def test_login_success():
open_login_page()
enter_username_and_password()
click_login_button()
verify_login_success()
assert True
执行生成测试报告,如下会显示用户场景或者子功能点:
4.4.@allure.attach
@allure.attach
:使用该装饰器可以向测试报告中添加附加的信息,通常是一些测试数据或日志。这对于在报告中显示额外的信息或文件非常有用。
4.4.1.用法一:
语法: allure.attach(body, name, attachment_type, extension)
参数列表
- body:要显示的内容(附件)
- name:附件名字
- attachment_type:附件类型,是 allure.attachment_type 里面的其中一种
- extension:附件的扩展名(比较少用)
allure.attachment_type提供的文件类型如下:
4.4.2.用法二:
语法如下,跟上面是有区别的
allure.attach.file(source, name, attachment_type, extension)
参数说明:
- source:文件路径,相当于传一个文件
- 其他参数和上面的一致
4.4.3.测试
准备测试用例代码如下:
import allure
import pytest
@pytest.fixture
def attach_text_file(request):
allure.attach("在fixture前置操作里面添加一个txt附件", "fixtrue前置附件", allure.attachment_type.TEXT)
def finalizer_scope():
allure.attach("在fixture后置操作里面添加一个txt附件", "fixtrue后置操作", allure.attachment_type.TEXT)
request.addfinalizer(finalizer_scope)
# 测试用例
def test_attach(attach_text_file):
allure.attach("<head></head><body> 测试页面 </body>", "创建一个HTML页面", allure.attachment_type.HTML)
allure.attach.file("./report.html", attachment_type=allure.attachment_type.HTML)
执行后查看如下:
五、利用钩子函数进行异常截图到allure测试报告
pytest测试框架提供的很多钩子函数方便我们对测试框架进行二次开发,可以根据自己的需求进行改造。例如:钩子方法:pytest_runtest_makereport ,可以更清晰的了解测试用例的执行过程,并获取到每个测试用例的执行结果。
5.1.pytest_runtest_makereport方法简介
先看下相关的源码,在 _pytest/runner.py 文件下,可以导入之后查看:
from _pytest import runner
# 对应源码
def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport:
return TestReport.from_item_and_call(item, call)
@pytest.hookimpl(hookwrapper=True)装饰的钩子函数,有以下两个作用:
- 可以获取到测试用例不同执行阶段的结果(setup,call,teardown)
- 可以获取钩子方法 pytest_runtest_makereport(item, call) 的调用结果(yield返回一个测试用例执行后的result对象)和调用结果result对象中的测试报告(返回一个report对象)
pytest_runtest_makereport(item, call) 钩子函数参数解释:
- item 是测试用例对象;
- call 是测试用例的测试步骤;具体执行过程如下:
- ①先执行 when="setup" ,返回setup用例前置操作函数的执行结果。
- ②然后执行 when="call" ,返回call测试用例的执行结果。
- ③最后执行 when="teardown" ,返回teardown用例后置操作函数的执行结果。
演示案例:
在:conftest.py 文件编写pytest_runtest_makereport 钩子方法,打印运行过程和运行结果:
import pytest
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
print('------------------------------------')
# 获取钩子方法的调用结果,返回一个result对象
out = yield
print('用例执行结果', out)
# 从钩子方法的调用结果中获取测试报告
report = out.get_result()
print('测试报告:%s' % report)
print('步骤:%s' % report.when)
print('nodeid:%s' % report.nodeid)
print('description:%s' % str(item.function.__doc__))
执行结果如下:
在 Pytest 中,测试用例的执行过程分为以下主要阶段:
- 收集阶段(Collection Stage):在这个阶段,Pytest 会搜索指定目录及其子目录中的测试文件,并收集所有的测试函数、测试类或测试模块。它会根据一些规则(如文件名、函数命名等)确定哪些是测试用例。
- 构建阶段(Construction Stage):在这个阶段,Pytest 会根据收集到的测试项构建一个测试项树的结构。这个树状结构反映了测试用例的层级关系,如模块、类级别的测试用例。
- 配置阶段(Configuration Stage):在这个阶段,Pytest 会加载和应用相关的配置,如解析命令行选项、加载 pytest.ini 文件、注册插件等。这个阶段还会初始化一些全局对象,如配置对象和插件管理器。
- 运行阶段(Execution Stage):在这个阶段,Pytest 会逐个执行每个测试项,并进行断言检查。这个阶段包括了几个子阶段:
- pytest_fixture_setup:在执行测试项之前,Pytest 会为每个测试项设置所需的夹具(Fixture)并执行相应的夹具代码段。
- pytest_runtest_protocol:在这个阶段,Pytest 会执行测试项的实际测试代码段,并检查断言结果。
- pytest_fixture_teardown:在执行完测试项之后,Pytest 会清理和销毁相关的夹具。
- 结束阶段(Completion Stage):在这个阶段,Pytest 会生成测试报告并输出到终端或文件中。它会统计测试结果,包括通过的用例数、失败的用例数、错误的用例数等。
实际上,"call" 阶段并不是 Pytest 中的一个独立阶段,而是在 “运行阶段(Execution Stage)” 中的一部分。具体来说,"call" 阶段包括以下几个步骤:
- 设置测试环境:在 “call” 阶段开始之前,Pytest 会为测试用例设置好必要的测试环境,例如创建浏览器驱动对象、初始化数据库连接等。
- 执行测试函数:在 “call” 阶段,Pytest 会执行测试函数,也就是运行测试用例的代码。在这个阶段,测试函数中的断言语句会被执行,用于判断测试结果是否符合预期。
- 收集测试结果:在测试函数执行完毕后,Pytest 会收集测试结果,包括测试用例是否通过、失败的断言信息等。
总结起来,"call" 阶段是指测试用例的实际执行阶段,包括设置测试环境、执行测试函数和收集测试结果。
5.2.利用钩子函数实现异常截图集成到allure测试报告中
使用 pytest_runtest_makereport
钩子函数来处理测试失败的情况。在这个钩子函数中,我们获取测试用例的执行结果,并在测试失败时获取浏览器截图,并使用 Allure 的 attach
方法将截图添加到测试报告中。在conftest.py中添加如下内容:
import allure
import pytest
from selenium import webdriver
@pytest.fixture(scope="session", autouse=True)
def driver(request):
# 在测试函数之前建立浏览器驱动对象
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.maximize_window()
def fin():
# 在测试函数完成后关闭浏览器
driver.quit()
request.addfinalizer(fin)
return driver
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item):
# 获取到用例执行之后的result对象
outcome = yield # 获取用例执行结果
report = outcome.get_result() # 获取用例执行报告
driver = item.funcargs["driver"] # 获取 driver 对象
if report.when == "call": # 判断用例执行阶段是否为 call 阶段
xfail = hasattr(report, "wasxfail") # 判断用例是否被标记为 xfail
# 判断用例是否跳过或者失败
if (report.skipped and xfail) or (report.failed and not xfail):
with allure.step("添加失败截图... ..."): # 添加 Allure 报告步骤
allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG) # 添加失败截图到 Allure 报告
在test_case包下创建test_case07.py准备测试用例,代码如下:
import time
from selenium.webdriver.common.by import By
# 测试用例
def test_screenshot(driver):
# 使用浏览器进行测试操作
driver.get("https://www.baidu.com")
driver.find_element(By.ID, "kw").send_keys("python")
driver.find_element(By.ID, "su").click()
time.sleep(2)
# 执行测试断言,故意让它失败
assert driver.title == "Example" # 这里故意错误地将断言值设置为 "Example"
执行用例生成allrue测试报告如下:
六、执行生成allure测试报告
6.1.在命令行执行命令生成测试报告
在项目根目录创建mian.py,写入内容如下:
import os
def run():
# 定义执行信息保存路径
data_path = "./outfile/logs"
# 执行命令,将执行信息保存到logs目录
os.system(f'pytest test_case --alluredir={data_path}')
report_path = "./outfile/report"
# 执行生成测试报告
os.system(f'allure generate {data_path} -o {report_path} --clean')
# 打开生成的测试报告
os.system("allure open ./outfile/report/")
if __name__ == '__main__':
run()
6.2.通过pytest.man生成allure测试报告
在项目根目录创建run.py,写入内容如下:
import os
import pytest
def run():
pytest.main(['--alluredir', './outfile/logs', '--clean-alluredir'])
os.system('allure generate ./outfile/logs -o ./outfile/report --clean')
os.system("allure open ./outfile/report/")
if __name__ == '__main__':
run()