Allure介绍与安装
Allure介绍
Allure是一款轻量级的开源自动化测试报告生成框架。它支持绝大部分测试框架,比如TestNG、Junit 、pytest、unittest等。本文主要介绍pytest框架结合Allure生成美观的测试报告。
Allure安装
安装Java
Allure是基于Java的,需要安装java1.8+,并配置环境变量
下载地址:https://www.oracle.com/cn/java/technologies/downloads/
安装步骤略,配置环境变量如下:
vim .bash_profile export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents /Home export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=.:$JAVA_HOME/bin:$PATH source .bash_profile
在终端输入
java -version
确认安装配置是否成功$ java -version java version "1.8.0_221" Java(TM) SE Runtime Environment (build 1.8.0_221-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.221-b11, mixed mode)
安装Allure
Allure下载地址:
https://github.com/allure-framework/allure2/releases
或者
https://repo1.maven.org/maven2/io/qameta/allure/allure-commandline/
下载解压后配置环境变量:
vim .bash_profile export Allure=/Users/laobai/software/allure-2.20.1/bin export PATH=$Allure:$PATH source .bash_profile
在终端输入
allure --version
确认安装配置是否成功$ allure --version 2.20.1
安装allure-pytest
allure-pytest是Pytest的一个插件,通过这个插件可以生成Allure所需要的用于生成测试报告的数据。
$ pip install allure-pytest
Allure的使用
官方的使用文档:https://docs.qameta.io/allure/#_pytest (allure支持多种语言,这里介绍的是基于pytest)
基本的生成报告方法
生成报告需要两个基本的步骤:
- 运行pytest命令:
pytest --alluredir
,生成中间结果,包括json、text格式文件 - 运行allure命令通过中间结果生成测试报告
allure serve
生成在线版本的测试报告allure generate
生成本地文件版本的测试报告
示例:
test_login.py
import time
import pytest
import allure
import xlrd
def readExecl():
datas = list()
book = xlrd.open_workbook('./testdata/login_data.xlsx')
sheet = book.sheet_by_index(0)
for item in range(1, sheet.nrows):
datas.append(sheet.row_values(item))
return datas
@pytest.mark.parametrize('username, password, result', readExecl())
class Test_login:
def test_login_success(self, driver, username, password, result):
driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click()
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys(
username)
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys(
password)
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click()
time.sleep(3)
login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text
time.sleep(1)
assert result in login_text
time.sleep(1)
conftest.py
import pytest
from config.driver_config import PLChrome
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
@pytest.fixture(params=[PLChrome])
def driver(request):
get_driver = request.param().browser
get_driver.maximize_window()
get_driver.implicitly_wait(10)
get_driver.get("http://101.43.8.10/")
yield get_driver
get_driver.quit()
生成中间文件,其中--alluredir=./report/result/
是指定中间文件生成的路径
$ pytest --alluredir=./report/result/
================================================================ test session starts ================================================================
platform darwin -- Python 3.9.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /Users/laobai/workspaces/testdemo02
plugins: variables-2.0.0, html-3.2.0, base-url-2.0.0, allure-pytest-2.12.0, metadata-2.0.4
collected 2 items
testcases/test_login.py .. [100%]
================================================================ 2 passed in 20.33s =================================================================
生成在线版本的测试报告,其中./report/result/
指通过哪个目录中的中间文件生成测试报告
$ allure serve ./report/result/
Generating report to temp directory...
Report successfully generated to /var/folders/_c/dc6074r10fb_tzfw0h_9qx4w0000gn/T/1031052424637446839/allure-report
Starting web server...
2022-12-25 18:48:28.298:INFO::main: Logging initialized @2782ms to org.eclipse.jetty.util.log.StdErrLog
Server started at <http://192.168.18.147:50525/>. Press <Ctrl+C> to exit
生成了测试报告后,会自动启动系统默认浏览器打开生成的测试报告

可以通过左下角的‘E’icon切换报告的展示语言,支持简体中文。
生成本地文件的测试报告,其中./report/result/
指通过哪个目录中的中间文件生成测试报告,-o ./report/html/
是指生成本地报告的输出目录
$ allure generate ./report/result/ -o ./report/html/
Report successfully generated to ./report/html
打开生成的报告html文件,展示测试报告内容

再次执行生成本地报告文件时,会提示文件已存在,需要增加--clean
参数进行覆盖生成文件内容
$ allure generate ./report/result/ -o ./report/html/ --clean
Report successfully generated to ./report/html
也可以通过命令来启动系统默认浏览器,自动打开生成的本地html报告文件
$ allure open -h 127.0.0.1 -p 8883 ./report/html/
Starting web server...
2022-12-25 19:45:15.837:INFO::main: Logging initialized @420ms to org.eclipse.jetty.util.log.StdErrLog
Server started at <http://localhost:8883/>. Press <Ctrl+C> to exit
报告内容展示:
总览【Overview】:测试运行结果整体预览
类别 【Categories】:用于展示测试结果,默认只显示测试结果为failed/error/broken测试
测试套【Suites】:测试套件,根据所有用例的层级关系,packgae、module、class、method/function来展示用例
图表【Graphs】:测试结果图形化,包括执行状态的分布图、优先级、耗时等
时间刻度【Timeline】:展示测试用例精确的测试时序
功能【Behaviors】:根据Allure特性标记epic、feature、story等分组展示测试用例和结果
包【Packages】:按照package、module来分组展示测试用例
生成具有丰富内容的报告
Allure提供以下一些装饰器对测试用例进行详细的分类、描述及信息补充,可以用于丰富报告内容,更加直观的体现出测试的结果。
方法 | 详细描述 |
---|---|
@allure.epic() | 史诗,相当于module级的标签 |
@allure.feature() | 功能模块和特性,相当于class级的标签 |
@allure.story() | 故事,相当于method级的标签 |
@allure.title | 用例标题 |
@allure.testcase() | 测试用例的链接 |
@allure.issue() | bug的链接 |
@allure.link() | 用于定义一个需要再测试报告中展示的链接 |
@allure.step() | 测试用例的步骤 |
@allure.severity() | 测试用例的等级,共5个等级:BLOCKER、CRITICAL、NORMAL、MINOR、TRIVAL |
@allure.description() | 为测试用例添加描述信息 |
allure.attach | 为测试用例添加附件 |
增加常用特性
修改test_login.py如下:
import time
import pytest
import allure
import xlrd
def readExecl():
datas = list()
book = xlrd.open_workbook('./testdata/login_data.xlsx')
sheet = book.sheet_by_index(0)
for item in range(1, sheet.nrows):
datas.append(sheet.row_values(item))
return datas
@pytest.mark.parametrize('username, password, result', readExecl())
class Test_login:
@allure.description("测试登录功能的测试用例")
@allure.epic("登录注册epic")
@allure.feature("登录feature")
@allure.story("登录story")
@allure.title("登录成功title")
@allure.tag("登录注册tag")
@allure.link('http://101.43.8.10/', name='ShopXO商城')
@allure.issue('https://demo16.zentao.net/bug-view-162.html', name='bug162')
@allure.testcase('https://demo16.zentao.net/testcase-view-690-1.html', name='登录注册测试用例')
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(self, driver, username, password, result):
with allure.step("点击登录按钮,跳转到登录页面"):
driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click()
with allure.step("在登录页面输入用户名"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys(
username)
with allure.step("在登录页面输入密码"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys(
password)
with allure.step("点击登录按钮"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click()
time.sleep(3)
with allure.step("获取登录成功后左上角的登录名"):
login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text
time.sleep(1)
with allure.step("断言获取的登录名与预期结果是否一致"):
assert result in login_text
time.sleep(1)
执行测试,查看报告内容

增加附件
插入文本类附件
向allure报告中插入本地文件的语法如下:
allure.attach.file(body, name=None, attachment_type=None, extension=None)
- body:需要显示的内容,附件文本信息的内容;
- name:附件名称;
- attachment_type:附件类型,可以是文本内容也可以是HTML代码等,由
allure.attachment_type
指定; - extension:附件的扩展名,可省略;
修改test_login.py增加插入文本内容附件
import time
import pytest
import allure
import xlrd
def readExecl():
datas = list()
book = xlrd.open_workbook('./testdata/login_data.xlsx')
sheet = book.sheet_by_index(0)
for item in range(1, sheet.nrows):
datas.append(sheet.row_values(item))
return datas
@pytest.mark.parametrize('username, password, result', readExecl())
class Test_login:
@allure.description("测试登录功能的测试用例")
@allure.epic("登录注册epic")
@allure.feature("登录feature")
@allure.story("登录story")
@allure.title("登录成功title")
@allure.tag("登录注册tag")
@allure.link('http://101.43.8.10/', name='ShopXO商城')
@allure.issue('https://demo16.zentao.net/bug-view-162.html', name='bug162')
@allure.testcase('https://demo16.zentao.net/testcase-view-690-1.html', name='登录注册测试用例')
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(self, driver, username, password, result):
with allure.step("点击登录按钮,跳转到登录页面"):
driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click()
with allure.step("在登录页面输入用户名"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys(
username)
with allure.step("在登录页面输入密码"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys(
password)
with allure.step("点击登录按钮"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click()
time.sleep(3)
# add_img_to_report(driver, "登录成功")
with allure.step("获取登录成功后左上角的登录名"):
login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text
time.sleep(1)
allure.attach('<head></head><body> 内嵌一个HTML文档 </body>', '添加一个HTML内容的附件', allure.attachment_type.HTML)
with allure.step("断言获取的登录名与预期结果是否一致"):
assert result in login_text
time.sleep(1)
执行测试,查看生成的报告

插入本地附件文件
向allure报告中插入本地文件的语法如下:
allure.attach.file(source, name=None, attachment_type=None, extension=None)
- source:需要显示的内容,即本地文件的路径;
- name:附件名称;
- attachment_type:附件类型,可以是CSV、JPG、HTML等,由
allure.attachment_type
指定; - extension:附件的扩展名,可省略;
修改test_login.py增加插入本地文件附件
import time
import pytest
import allure
import xlrd
def readExecl():
datas = list()
book = xlrd.open_workbook('./testdata/login_data.xlsx')
sheet = book.sheet_by_index(0)
for item in range(1, sheet.nrows):
datas.append(sheet.row_values(item))
return datas
@pytest.mark.parametrize('username, password, result', readExecl())
class Test_login:
@allure.description("测试登录功能的测试用例")
@allure.epic("登录注册epic")
@allure.feature("登录feature")
@allure.story("登录story")
@allure.title("登录成功title")
@allure.tag("登录注册tag")
@allure.link('http://101.43.8.10/', name='ShopXO商城')
@allure.issue('https://demo16.zentao.net/bug-view-162.html', name='bug162')
@allure.testcase('https://demo16.zentao.net/testcase-view-690-1.html', name='登录注册测试用例')
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(self, driver, username, password, result):
with allure.step("点击登录按钮,跳转到登录页面"):
driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click()
with allure.step("在登录页面输入用户名"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys(
username)
with allure.step("在登录页面输入密码"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys(
password)
with allure.step("点击登录按钮"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click()
time.sleep(3)
with allure.step("获取登录成功后左上角的登录名"):
login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text
time.sleep(1)
allure.attach.file(source='/Users/laobai/Desktop/testdata.csv', name='测试数据文件',
attachment_type=allure.attachment_type.CSV)
with allure.step("断言获取的登录名与预期结果是否一致"):
assert result in login_text
time.sleep(1)
执行测试,查看生成的报告

插入运行过程中的截图
在项目的common目录下的tools.py中新建一个插入截图方法
import time
import allure
def add_img_to_report(driver, step_name, need_sleep=True):
"""
截图并插入allure报告
:param driver:
:param step_name:
:param need_sleep:
:return:
"""
if need_sleep:
time.sleep(2)
allure.attach(driver.get_screenshot_as_png(), step_name + '.png', allure.attachment_type.PNG)
修改test_login.py增加插入截图方法,这里在登录成功后进行截图并插入到报告中
import time
import pytest
import allure
import xlrd
from common.tools import add_img_to_report
def readExecl():
datas = list()
book = xlrd.open_workbook('./testdata/login_data.xlsx')
sheet = book.sheet_by_index(0)
for item in range(1, sheet.nrows):
datas.append(sheet.row_values(item))
return datas
@pytest.mark.parametrize('username, password, result', readExecl())
class Test_login:
@allure.description("测试登录功能的测试用例")
@allure.epic("登录注册epic")
@allure.feature("登录feature")
@allure.story("登录story")
@allure.title("登录成功title")
@allure.tag("登录注册tag")
@allure.link('http://101.43.8.10/', name='ShopXO商城')
@allure.issue('https://demo16.zentao.net/bug-view-162.html', name='bug162')
@allure.testcase('https://demo16.zentao.net/testcase-view-690-1.html', name='登录注册测试用例')
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(self, driver, username, password, result):
with allure.step("点击登录按钮,跳转到登录页面"):
driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click()
with allure.step("在登录页面输入用户名"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys(
username)
with allure.step("在登录页面输入密码"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys(
password)
with allure.step("点击登录按钮"):
driver.find_element('xpath',
'/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click()
time.sleep(3)
add_img_to_report(driver, "登录成功")
with allure.step("获取登录成功后左上角的登录名"):
login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text
time.sleep(1)
with allure.step("断言获取的登录名与预期结果是否一致"):
assert result in login_text
time.sleep(1)
执行测试,查看生成的报告

动态获取allrue.title()
前面介绍的方法中,指定title的allrue.title()
是在代码中写死的,下面介绍通过使用pytest.mark.parametrize()
从测试用例(测试数据文件)中动态获取。测试用例管理工具,比如禅道中,书写用例时,用例标题是必填字段,所以没有增加任何工作量。
修改login_data.xlsx增加title列
修改test_login.py,在
pytest.mark.parametrize()
增加参数title
import time import pytest import allure import xlrd def readExecl(): datas = list() book = xlrd.open_workbook('./testdata/login_data.xlsx') sheet = book.sheet_by_index(0) for item in range(1, sheet.nrows): datas.append(sheet.row_values(item)) return datas @pytest.mark.parametrize('username, password, result, title', readExecl()) class Test_login: @allure.description("测试登录功能的测试用例") @allure.epic("登录注册epic") @allure.feature("登录feature") @allure.story("登录story") @allure.title("登录用例-{title}") @allure.tag("登录注册tag") @allure.link('http://101.43.8.10/', name='ShopXO商城') @allure.issue('https://demo16.zentao.net/bug-view-162.html', name='bug162') @allure.testcase('https://demo16.zentao.net/testcase-view-690-1.html', name='登录注册测试用例') @allure.severity(allure.severity_level.CRITICAL) def test_login_success(self, driver, username, password, result, title): with allure.step("点击登录按钮,跳转到登录页面"): driver.find_element('xpath', '/html/body/div[6]/div/div[1]/div[2]/a[1]').click() with allure.step("在登录页面输入用户名"): driver.find_element('xpath', '/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[1]/input').send_keys( username) with allure.step("在登录页面输入密码"): driver.find_element('xpath', '/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[2]/div/input').send_keys( password) with allure.step("点击登录按钮"): driver.find_element('xpath', '/html/body/div[4]/div/div[2]/div[2]/div/div/div[1]/form/div[3]/button').click() time.sleep(3) with allure.step("获取登录成功后左上角的登录名"): login_text = driver.find_element('xpath', '/html/body/div[2]/div/ul[1]/div/div/em[2]').text time.sleep(1) with allure.step("断言获取的登录名与预期结果是否一致"): assert result in login_text time.sleep(1)
执行测试,查看生成的报告
以上即完成了动态从测试用例中获取title。同样,epic、feature、stroy等字段也可以尝试从测试用例中进行动态获取。
增加ENVIRONMENT环境
新建environment.properties文件或environment.xml,二者均可
environment.properties
SystemVersion=macOS Mojave
PythonVersion=3.9.12
AllureVersion=2.20.1
ProjectName=PLScript Demo01
Author=laobai
environment.xml
<environment>
<parameter>
<key>SystemVersion</key>
<value>macOS Mojave</value>
</parameter>
<parameter>
<key>PythonVersion</key>
<value>3.9.12</value>
</parameter>
<parameter>
<key>AllureVersion</key>
<value>2.20.1</value>
</parameter>
<parameter>
<key>ProjectName</key>
<value>PLScript Demo01</value>
</parameter>
<parameter>
<key>Author</key>
<value>laobai</value>
</parameter>
</environment>
将上面两个文件之一,拷贝到执行测试生成过程文件(json\text)的目录中后,再执行生成报告的命令。(因为在执行生成过程文件时,经常会增加--clean-aaluredir
参数,会删除整个目录中的内容)
生成的报告如下图所示:

Allure执行命令封装
从上面的介绍可知,生成最终的报告需要执行3次命令:
- 生成过程文件(json、text)
- 拷贝environment.xml文件到过程文件目录
- 生成最终的allure测试报告
可以将上面的3个步骤分别封装成一个方法,然后写一个run.py依次调用这3个方法即可。
代码略
执行测试:
$ python run.py
================================================================ test session starts ================================================================
platform darwin -- Python 3.9.12, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /Users/laobai/workspaces/testdemo02/venv/bin/python
cachedir: .pytest_cache
metadata: {'Python': '3.9.12', 'Platform': 'macOS-10.14.6-x86_64-i386-64bit', 'Packages': {'pytest': '6.2.5', 'pluggy': '1.0.0'}, 'Plugins': {'variables': '2.0.0', 'html': '3.2.0', 'base-url': '2.0.0', 'allure-pytest': '2.12.0', 'metadata': '2.0.4'}, 'JAVA_HOME': '/Library/Java/JavaVirtualMachines/jdk1.8.0_221.jdk/Contents/Home', 'Base URL': ''}
rootdir: /Users/laobai/workspaces/testdemo02
plugins: variables-2.0.0, html-3.2.0, base-url-2.0.0, allure-pytest-2.12.0, metadata-2.0.4
collected 2 items
testcases/test_login.py::Test_login::test_login_success[PLChrome-laobai-a123456-laobai-登录成功-管理员账号登录] PASSED
testcases/test_login.py::Test_login::test_login_success[PLChrome-plscript-y123456-plscript-登录成功-商户账号登录] PASSED
================================================================ 2 passed in 20.03s =================================================================
Report successfully generated to /Users/laobai/workspaces/testdemo02/report/html