Allure
1. Allure简介
1.1 关于Allure
Allure框架是一个灵活轻量级多语言测试报告工具,它不仅可以以WEB的方式展示简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。Allure报告简化了常见缺陷的统计:失败的测试可以分为BUG和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
Allure官方文档地址:https://docs.qameta.io/allure/
1.2 Allure安装
step1.下载JDK,下载地址:https://www.oracle.com/java/technologies/downloads/,配置环境变量:JAVA_HOME=D:\Program Files\Java,Path中添加%JAVA_HOME%\bin,在命令行中输入以下命令,不报错,即代表设置成功。java -version
step2.下载Allure命令行,下载地址:https://github.com/allure-framework/allure2/releases/,将下载到本地的allure压缩包解压到指定目录,并添加相应的环境变量Path=D:\Program Files\Allure\allure-2.16.0\bin,在命令行中输入allure,不出现报错即可
1.3 Allure用法
allure命令行语法格式:allure [options] [command] [command options]

#常用options和commands #Options -q, --quiet:切换到静默模式,默认关闭 -v, --verbose:切换详细日志模式,默认关闭 #Commands generate:生成allure的HTML报告 -c, --clean:在生成新报告前,清理之前生成报告的目录,默认关闭 --config:Allure命令行配置文件路径,如果指定将覆盖--profile和--configDirectory所设定的值 --configDirectory:Allure命令行配置文件目录,默认值为:ALLURE_HOME目录 --profile:Allure命令行配置文件 -o, --report-dir, --output:指定生成报告的目录,默认allure-report serve:启动serve并查看报告 基本语法:serve [options] allure结果目录 --config:Allure命令行配置文件路径,如果指定将覆盖--profile和--configDirectory所设定的值 --configDirectory:Allure命令行配置文件目录,默认值为: ALLURE_HOME目录 --profile:Allure命令行配置文件 -h, --host:指定访问报告的web服务器地址 -p, --port:指定访问报告的web服务器地端口,默认为0 open:查看报告 基本语法:open [options] allure报告目录 -h, --host:指定访问报告的web服务器地址 -p, --port:指定访问报告的web服务器地端口,默认为0 1.generate常用参数主要为-c和-o 2.open常用参数主要为-h和-p
最常用的命令是:allure generate <path-to-results> -o <path-to-report>
其中path-to-results是测试结果路径,path-to-report是生成的html报告路径
1.4 Allure报告结构
- Overview:报告总览
- Categories:类别,允许用户创建自定义的类别。默认分为失败和错误,在执行结果是其中一类时则被归到相应的类中。
- Suites:测试套件,即所有用例的层级关系,可以按package/module/class/method进行查找
- Graphs :测试结果图形化,包含测试用例的运行结果分布图、耗时、优先级等
- Timeline: 时序图,将测试用例的执行顺序和测试时间以可视化形式展现出来
- Behaviors:行为驱动,根据Epic、Feature、Story来对测试用例进行分组
- Packages: 用例按Package进行分组,根据测试结果按不同的Package进行分组,并以树形结构进行展示
1.5 Allure特性
1.5.1 Flaky
该特性用来标识不够稳定的测试用例集,即有些用例运行时,时而成功时而失败。其用意主要如下所示:
当用例失败的情况下,能够获取足够详细的信息
不标记为Flaky的话,可能就要禁用这些测试
用法如下所示:

@Flaky public void aTestWhichFailsFromTimeToTime { ... }
1.5.2 Environment
Environment表示环境变量参数,用来显示本次测试运行环境的参数。在生成allure-result结果前,通过创建environment.properties或environment.xml文件,并把文件放置到allure-result目录中。
environment.properties

Browser=Chrome
Browser.Version=95.0
Stand=Production
environment.xml

<environment> <parameter> <key>Browser</key> <value>Chrome</value> </parameter> <parameter> <key>Browser.Version</key> <value>95.0</value> </parameter> <parameter> <key>Stand</key> <value>Production</value> </parameter> </environment>
environment.properties和environment.xml不允许存在中文
1.5.3 Categories
默认分类分为两种,如下所示:
Product defects:产品缺陷,测试结果为失败(failed tests)
Test defects:测试缺陷,测试结果为错误(broken tests)
除了默认分类之外,也可以自定义创建分类。通过创建categories.json文件,在生成allure-result结果前,提前放置到该目录即可。
categories.json

[ { "name": "Ignored tests", "matchedStatuses": ["skipped"] }, { "name": "Infrastructure problems", "matchedStatuses": ["broken", "failed"], "messageRegex": ".*bye-bye.*" }, { "name": "Outdated tests", "matchedStatuses": ["broken"], "traceRegex": ".*FileNotFoundException.*" }, { "name": "Product defects", "matchedStatuses": ["failed"] }, { "name": "Test defects", "matchedStatuses": ["broken"] } ]
- name(必填项):分类名称
- matchedStatuses(可选项):测试用例的运行结果,默认值["failed", "broken", "passed", "skipped", "unknown"]
- messageRegex(可选项):测试用例运行的错误信息,默认是 .* ,通过正则进行匹配
- traceRegex(可选项):测试用例运行的错误堆栈信息,默认是 .* ,通过正则进行匹配
2. Allure与pytest集成
2.1 Allure行为驱动
allure除了支持Pytest自带的特性之外(fixture、parametrize、xfail、skip),自身也有非常强大的特性,下面来详细介绍。
2.1.1 @allure.step
allure报告允许对每个测试用例的执行步骤进行详细说明,该功能通过@allure.step()装饰器来实现,@allure.step()只有一个参数,就是title,还可以用with allure.step("step:步骤")实现。
allure.step demo

一》Allure添加用例步骤详解 (1)在测试用例中添加详细的步骤有助于更好的阅读用例,也方便报错后迅速的定位问题 例子: 用例步骤:1.登陆,2.浏览商品 3.添加购物车 4.生成订单 5.支付成功 (2)第一种方式 <-----common_function.py-----> 将用例步骤做关键字封装 #coding=utf-8 import allure import pytest def login(username,password): """登陆""" print("前置操作:先登陆") def open_goods(): """浏览商品""" print("浏览商品") def add_shopping_cart(goods_id="10086"): """添加购物车""" print("添加购物车") def buy_goods(): """生成订单""" print("buy") def pay_goods(): """支付""" print("pay") <-----test_allure_step.py-----> 开始用例设计,登陆单独拿出来,做成前置操作,后面的步骤合起来就是一个用例 #coding=utf-8 import os import allure import pytest from test010.test0102.p05_testcase_step.common_function import * @pytest.fixture(scope="session") def login_fix(): with allure.step("setup:登陆"): login("zz","123456") @allure.feature("购物模块") @allure.story("子模块") @allure.title("流程性用例,添加测试步骤") def test_add_goods_and_buyg(login_fix): """ 用例步骤: 1.登陆, 2.浏览商品 3.添加购物车 4.生成订单 5.支付成功 """ with allure.step("step1:浏览商品"): open_goods() with allure.step("step2:添加购物车"): add_shopping_cart() assert 1 == 2 with allure.step("step3:生成订单"): buy_goods() with allure.step("step4:支付"): pay_goods() with allure.step("断言"): assert 1 == 1 if __name__ == '__main__': pytest.main(['-s','test_allure_step.py','--alluredir','./result','--clean-alluredir']) os.system('allure serve result') (3)第二种方式 测试步骤也可以在函数上加上装饰器来实现:@allure.step() <-----common_function2.py-----> #coding=utf-8 import allure import pytest @allure.step("setup:登陆") def login(username,password): """登陆""" print("前置操作:先登陆") @allure.step("step:浏览商品") def open_goods(): """浏览商品""" print("浏览商品") #注意这里的参数会在报告里展示 @allure.step("step添加购物车") def add_shopping_cart(goods_id="10086"): """添加购物车""" print("添加购物车") @allure.step("step:生成订单") def buy_goods(): """生成订单""" print("buy") @allure.step("step:支付") def pay_goods(): """支付""" print("pay") <-----test_allure_stepx.py-----> #coding=utf-8 import os import allure import pytest from test010.test0102.p05_testcase_step.common_function2 import * @pytest.fixture(scope="session") def login_fix(): with allure.step("setup:登陆"): login("zz","123456") @allure.feature("购物模块") @allure.story("子模块") @allure.title("流程性用例,添加测试步骤") def test_add_goods_and_buyg(login_fix): """ 用例步骤: 1.登陆, 2.浏览商品 3.添加购物车 4.生成订单 5.支付成功 """ open_goods() add_shopping_cart() buy_goods() pay_goods() assert 1 == 1 if __name__ == '__main__': pytest.main(['-s','test_allure_stepx.py','--alluredir','./result','--clean-alluredir']) os.system('allure serve result') (4)两种方式对比 使用 with allure.step("step:步骤") 这种方式代码可读性更好一点, 但不会带上函数里面的传参和对应的值。 使用 @allure.step("step:步骤") 这种方式会带上函数的传参和对应的值。 这两种方式结合起来使用,才能更好的展示测试报告!
2.1.2 @allure.attach
allure报告支持添加附件并进行展示,可用以补充测试结果,第一种基本语法如下所示:
allure.attach(body, name, attachment_type, extension)
- body:要显示的附件内容
- name: 附件名称
- attachment_type:附件类型,属于allure.attachment_type里面的一种
- extension:附件扩展名
allure.attachment_type主要有TEXT、CSV、HTML、XML、JSON、YAML、PCAP、PNG、JPG、SVG、GIF、BMP、MP4、OGG、WEBM、PDF等
第二种基本语法如下所示:
allure.attach.file(source, name, attachment_type, extension)
- source:上传文件所在路径
- 其他参数和上面参数一致
2.1.3 @allure.description
给用例添加详细的描述,常见语法有三种:
1.@allure.description(str)
2.在测试用例函数声明下方添加 """ """
3.@allure.description_html(str)
相当于传一个HTML代码组成的字符串,类似 allure.attach()中传HTML
方式一和方式二作用和效果是一样的
allure.description demo

# coding=utf-8 import os import allure import pytest """ 假设这是一个登陆操作,简单实现为一个print """ @pytest.fixture def login_fix(): print("前置条件:登陆") """ 封装常用的方法 """ @allure.step("某某常用操作一") def step_1(): print("常用操作一-----------------") @allure.step("某某常用操作二") def step_2(): print("常用操作二-----------------") @allure.step("某某常用操作三") def step_3(): print("常用操作三-----------------") @allure.epic("大模块名称:NGBSS") @allure.feature("文章编辑") class TestDemoAllure(): @allure.testcase("http://127.0.0.1:8666/zentao/testcase-view-6-1.html") @allure.issue("http://127.0.0.1:8666/zentao/bug-view-1.html") @allure.title("用例标题一") @allure.story("测试场景一") @allure.severity("critical") def test_case_1(self, login_fix): """ 用例标题 步骤 预期结果 """ step_1() step_2() @allure.story("测试场景二") def test_case_2(self, login_fix): step_1() step_3() @allure.epic("大模块名称:CBS") @allure.feature("欠费催缴") class TestDemoAllure2(): @allure.story("测试场景三") @allure.severity("critical") def test_case_3(self, login_fix): """ 用例标题 步骤 预期结果 """ step_1() @allure.story("测试场景四") def test_case_4(self, login_fix): step_3() if __name__ == '__main__': # pytest.main(['--alluredir','./muzi']) # os.system('allure serve muzi') # 根据epic执行 # pytest.main(['--alluredir','./muzi', # '--allure-epics=大模块名称:NGBSS', # '--clean-alluredir']) # os.system('allure serve muzi') # 根据feature来执行 # pytest.main(['--alluredir','./muzi', # '--allure-features=欠费催缴', # '--clean-alluredir']) # os.system('allure serve muzi') # 根据story来执行 # pytest.main(['--alluredir', './muzi', # '--allure-stories=测试场景四', # '--clean-alluredir']) # os.system('allure serve muzi') # 多条件筛选 pytest.main(['--alluredir', './muzi', '--allure-stories=测试场景四,测试场景三', '--clean-alluredir']) os.system('allure serve muzi')
2.1.4 @allure.title
添加测试用例标题,支持占位符传递关键字参数(动态标题,结合(@pytest.mark.parametrize使用)
如果没有添加 @allure.title()的话,测试用例的标题默认就是函数名
2.1.5 @allure.link & @allure.issue & @allure.testcase
三个装饰器源码如下所示:

def link(url, link_type=LinkType.LINK, name=None): return safely(plugin_manager.hook.decorate_as_link(url=url, link_type=link_type, name=name)) def issue(url, name=None): return link(url, link_type=LinkType.ISSUE, name=name) def testcase(url, name=None): return link(url, link_type=LinkType.TEST_CASE, name=name)
issue()和testcase()调用的也是link(),只是link_type不一样
- url:跳转的链接,必传参数
- name:显示在allure报告的名字,如果不传就是显示完整的链接
出现三个装饰器的原因是为了更好地将链接分类:访问连接、Bug链接、测试用例链接
2.1.6 BDD标记装饰器
在pytest中,可以使用@pytest.mark进行标识,但并不会显示在allure报告上,而allure也提供了三种类型的标记装饰器,它们则是可以显示在allure报告上的,如下所示:
@allure.epic:敏捷里面的概念,往下是 feature
@allure.feature:功能点的描述,理解成模块往下是 story
@allure.story:故事,往下是 title
1.story 是 feature 的子集,当测试用例有 @allure.feature、@allure.story 时,在报告上会先显示 feature,点开之后再显示 story
2.如果不加 @allure.feature、@allure.story 时,在Behaviors栏目下,测试用例都不会分类显示
用命令行方式运行时,可以指定运行某个story、feature、epic
--allure-epics
--allure-features
--allure-stories
2.1.7 allure.severity
allure提供了用例级别,因此在allure报告可以清晰看到不同级别用例的缺陷数量。详细等级如下所示:
级别 含义 详细解释
blocker 阻塞缺陷 无法执行下一步操作等
critical 严重缺陷 功能点缺失或直接崩溃等
normal 一般缺陷 边界值问题,格式错误等
minor 次要缺陷 UI类错误等
trivial 轻微缺陷 必填项无提示或提示信息不规范和统一等
用例等级设置demo

import pytest import allure import os @allure.severity("normal") def test_case_1(): """ 修改个人姓名-置空 """ print("用例1111") @allure.severity("critical") def test_case_2(): """ 修改个人信息-设置为系统已有人员的信息 """ print("用例2222") @allure.severity("critical") def test_case_3(): """ 修改个人姓名-生日必选项置空保存 """ print("用例3333") @allure.severity("blocker") def test_case_4(): """ 修改个人姓名-点击保存成功 """ print("用例4444") def test_case_5(): """ 不设置等级,默认等级为 """ print("用例5555") if __name__ == '__main__': # 执行所有的用例级别 # pytest.main(['--alluredir','./muzi']) # os.system('allure generate ./muzi/ -o ./report/ --clean') # 如果有很多测试用例,现在想做快速回顾,只执行用例级别为blocker和critical的测试用例 # 第一种方式: # pytest.main(['--alluredir','./muzi','--allure-severities','blocker,critical','--clean-alluredir']) # os.system('allure generate ./muzi/ -o ./report/ --clean') # 第二种方式: pytest.main(['--alluredir', './muzi', '--allure-severities', 'blocker,critical']) os.system('allure serve muzi')
2.2 Allure和pytest集成示例
执行以下命令即可安装Allure和Pytest
2.2.1 allure.step示例

import pytest import allure import os @allure.step("这是第一步") def inputUrl(url: str): print(f"输入的网址为:{url}") @allure.step(title="这是第二步") def locateElement(xpath: str): print(f"查找元素的xpath是{xpath}") @allure.step("这是第三步") def sendElement(): inputUsernameAndPasswd("Surpass", "password") @allure.step("这是第四步,{username},{password}") def inputUsernameAndPasswd(username: str, password: str): print(f"输入的用户名和密码分别为:{username},{password}") @allure.step("这是第五步") def test_login(): inputUrl("https://www.baidu.com") locateElement('//*[@id="su"]') sendElement()

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_login.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
示例2:

import os import allure import pytest @allure.feature("编辑分类文章") class TestArticaleClassify(): @allure.story("典型场景") @allure.title("编辑文章分类,重复保存,保存失败") @allure.issue("http://127.0.0.1:8080/zentao/bug-view-1.html") # 禅道bug地址 @allure.testcase("http://127.0.0.1:8080/zentao/testcase-view-5-1.html") # 禅道用例链接地址 def test_edit_classify(self): """ 编辑文章分类,重复保存,保存失败 前置条件:1.登录 步骤: 1.编辑文章分类,输入文章类别,如计算机 2.点击保存按钮 3.重新打开编辑页面,输入:计算机 4.再次点击保存按钮 预期结果: 1.输入成功 2.保存成功 3.输入成功 4.保存失败,提示:已存在 """ with allure.step("step:登陆"): print("登陆") assert 1 == 1 with allure.step("step1:编辑文章分类,输入文章类别,如计算机"): print("step1") assert 1 == 1 with allure.step("step2:点击保存按钮"): print("step2") assert 1 == 1 with allure.step("step3:重新打开编辑页面,输入:计算机"): print("step3") assert 3 == 4 with allure.step("step4:再次点击保存按钮"): print("step4") assert 4 == 5 if __name__ == '__main__': pytest.main(['--alluredir','./muzi']) os.system('allure generate ./muzi/ -o ./report/ --clean')
2.2.2 allure.attach示例

import pytest import allure import os def attach01(body, name, attachment_type=allure.attachment_type.TEXT): """ 附件为内容 """ allure.attach(body, name, attachment_type=attachment_type) def attach02(filePath, name, attachment_type=allure.attachment_type.TEXT): """ 附件为文件 """ allure.attach.file(filePath, name, attachment_type=attachment_type) def test_attach01(): body = "<h3>方法一:测试allure附件内容为HTML</h3>" name = "attach-01-test" attach01(body, name, attachment_type=allure.attachment_type.HTML) def test_attach02(): filePath = os.path.join(os.getcwd(), "attach", "sample.png") name = "attach-02-test" attach02(filePath, name, attachment_type=allure.attachment_type.PNG)

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_attach.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.2.3 allure.description示例

import pytest import allure def test_allureDescription01(): """这是一个allure.description示例01""" assert (7 + 8) == 15 @allure.description("这是一个allure.description示例02") def test_allureDescription02(): assert (7 + 8) == 15 @allure.description_html(""" <h2>这是一个 <font size=15>allure.description </font>示例03 </h2> """) def test_allureDescription03(): assert (7 + 8) == 15

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_description.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.2.4 allure.title示例

import pytest import allure @allure.title("登录") @pytest.fixture(scope="session") def loginData(request): params = request.param name = params.get("name", "") password = params.get("password", "") code = params.get("code", "") print(f"param is {name},{password},{code}") yield name, password, code @allure.title(f"登录成功") @pytest.mark.parametrize("loginData", [ {"name": "Surpass", "password": "123456", "code": "SHCQ"}, {"name": "Diana", "password": "20210227", "code": "FKDT"} ], indirect=True) def test_loginSucces(loginData): name, password, code = loginData body = f"用户名:{name},密码:{password},验证码:{code}" name = "allure.title.test" allure.attach(body, name, attachment_type=allure.attachment_type.TEXT)

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_title.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.2.5 @allure.link & @allure.issue & @allure.testcase示例

import pytest import allure @allure.link("https://www.google.com") def test_basicLink(): pass @allure.link(url="https://www.surpassme.com", name="basicLink") def test_basicLinkWithName(): pass @allure.issue(url="https://www.baidu.com", name="issueLink") def test_issueLink(): pass @allure.testcase(url="https://www.zentao.net", name="testcaseLink") def test_testcaseLink(): pass

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_link.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.2.6 BDD装饰器示例

import pytest import allure @allure.step("第一步") def firstStep(): print("这是第一步") @allure.step("第二步") def secondStep(): print("这是第二步") @allure.step("第N步") def nStep(): print("第N步") @allure.epic("总体描述") @allure.feature("测试模块A") class TestEpicAndFeatureAndStory(): @allure.issue("http://www.surpamssme.com/issue/id=0227") @allure.testcase("http://www.surpassme.com/testcase/id=0227") @allure.title("功能A-用例-01") @allure.story("测试功能A") @allure.description("Surpassme 测试验证") def test_CaseA01(self): print("test_Case01") firstStep() secondStep() @allure.story("测试功能A") @allure.title("功能A-用例-02") def test_CaseA02(self): pass @allure.story("测试功能A") @allure.title("功能A-用例-03") def test_CaseA03(self): pass @allure.story("测试功能B") @allure.title("功能B用例-01") def test_CaseB01(self): pass @allure.story("测试功能B") @allure.title("功能B用例-03") def test_CaseB02(self): pass

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_bdd.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.2.7 allure.severity示例

import allure @allure.title("blocker") @allure.severity("blocker") def test_Case01(): pass @allure.title("critical") @allure.severity("critical") def test_Case02(): pass @allure.title("normal") @allure.severity("normal") def test_Case03(): pass @allure.title("minor") @allure.severity("minor") def test_Case04(): pass @allure.title("trivial") @allure.severity("trivial") def test_Case05(): pass

import pytest import os if __name__=="__main__": pytest.main(['-s', '-v','./testcase/test_severity.py','--alluredir', './report/tmp', "--clean-alluredir"]) os.system(r"allure generate ./report/tmp -o ./report/html --clean")
生成结果如下:
2.3 pytest 和allure综合示例
2.3.1 参数化结合allure.title()生成不同标题报告

(1)参数化parametrize <-----test_a.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!"), ({"username":"zz2","password":"123456"},"failed!"), ({"username":"zz3","password":"123456"},"success!") ] @allure.story("登陆接口") @pytest.mark.parametrize("test_input,expected",test_datas) def test_login(test_input,expected): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected if __name__ == '__main__': pytest.main(["test_a.py",'--alluredir','./result','--clean-alluredir']) os.system('allure generate ./result/ -o ./report_allure/ --clean') (2)param+ids参数 <-----test_a_ids.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!"), ({"username":"zz2","password":"123456"},"failed!"), ({"username":"zz3","password":"123456"},"success!") ] @allure.story("登陆接口") @pytest.mark.parametrize("test_input,expected", test_datas, ids=[ "输入正确账号A,密码,登陆", "输入错误账号B,密码,登陆", "输入正确账号C,密码,登陆", ]) def test_login(test_input,expected): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected if __name__ == '__main__': pytest.main(["test_a_ids.py",'--alluredir','./result2','--clean-alluredir']) os.system('allure generate ./result2/ -o ./report_allure2/ --clean') <-----conftest.py-----> #coding=utf-8 def pytest_collection_modifyitems(items): """ 测试用例收集完成时,将收集到的item的name和nodeid的中文显示在控制台上 """ for item in items: item.name = item.name.encode("utf-8").decode("unicode_escape") item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape") (3)allure.title描述用例 <-----test_a_title.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!"), ({"username":"zz2","password":"123456"},"failed!"), ({"username":"zz3","password":"123456"},"success!") ] """ 使用@allure.title()时,可以加上传入的参数, 比如test_input,可以拼接test_input的值 """ @allure.story("登陆接口") @allure.title("用例描述,测试输入:{test_input}") @pytest.mark.parametrize("test_input,expected", test_datas) def test_login(test_input,expected): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected if __name__ == '__main__': pytest.main(["test_a_title.py",'--alluredir','./result3','--clean-alluredir']) os.system('allure generate ./result3/ -o ./report_allure3/ --clean') (4)优化用例title <-----test_a_title_new.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"), ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"), ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆") ] """ 使用@allure.title()时,可以加上传入的参数, 比如test_input,可以拼接test_input的值 """ @allure.story("登陆接口") @allure.title("{test_input}") @pytest.mark.parametrize("test_input,expected,title", test_datas) def test_login(test_input,expected,title): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected if __name__ == '__main__': pytest.main(["test_a_title_new.py",'--alluredir','./result4','--clean-alluredir']) os.system('allure generate ./result4/ -o ./report_allure4/ --clean')
2.3.2 allure动态生成用例标题

(1)allure.dynamic 常用动态属性 模块feature allure.dynamic.feature(feature_name) 功能点 story allure.dynamic.story(case_story) 用例标题 title allure.dynamic.title(case_title) (2)description 用例描述动态更新 (3)title 用例标题动态更新 (4)参数化时,使用@allure.title给用例不同标题 <-----test_case_01.py-----> import os import allure import pytest # 接口用例描述例子 desc = "<font color='red'>请求URL:</font>{}<Br/>" \ "<font color='red'>请求类型:</font>{}<Br/>" \ "<font color='red'>期望结果:</font>{}<Br/>" \ "<font color='red'>实际结果描述:</font>{}<Br/>"\ .format("http://www.baidu.com","post","200","404") # description 用例描述动态更新 @allure.description("原始描述") def test_dynamic_description(): # 断言成功后,可以在测试主体内部动态更新描述 assert 42 == int(6 * 7) # 断言失败,不会动态更新描述 # assert 43 == int(6 * 7) allure.dynamic.description(desc) # title 用例标题动态更新 @allure.title("原始标题") def test_with_dynamic_title(): assert 2 + 2 == 4 allure.dynamic.title('当断言成功时,用例标题会动态更新') # 参数化时,使用@allure.title给用例不同标题 @allure.title("参数化用例标题: 添加 {param1} 和 {param2}") @pytest.mark.parametrize('param1,param2,expected', [ (2, 2, 4), (1, 2, 5) ]) def test_with_parameterized_title(param1, param2, expected): assert param1 + param2 == expected if __name__ == '__main__': # pytest.main(['-s',"test_case_01.py",'--alluredir','./result']) pytest.main(['-s', "test_case_01.py", '--alluredir', './result','--clean-alluredir']) # os.system('allure generate ./result/ -o ./report_allure/ --clean') os.system('allure serve result') (5)参数化时,在用例里使用allure.dynamic.title更新用例的标题 <-----test_case_02.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"), ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"), ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆") ] """ 使用@allure.title()时,可以加上传入的参数, 比如test_input,可以拼接test_input的值 """ @allure.story("登陆接口") @pytest.mark.parametrize("test_input,expected,title", test_datas) def test_login(test_input,expected,title): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected # 断言成功的用例,动态更新标题 allure.dynamic.title(title) if __name__ == '__main__': pytest.main(["test_case_02.py",'--alluredir','./result4','--clean-alluredir']) os.system('allure serve result4')
2.3.3 allure生成环境配置

(1)allure报告默认没有环境信息 (2)添加环境信息方式一:environment.properties 在allure的result目录(json数据里的)下添加一个 environment.properties 文件(配置文件不支持中文,有中文会有乱码) environment.properties 文件格式 systemVersion=win10 pythonVersion=3.6.0 allureVersion=2.13.0 baseUrl=http://192.168.1.x:8080 projectName=test author=zz email=123123123@qq.com (3)添加环境信息方式二:environment.xml 在allure的result目录(json数据里的)下添加一个environment.xml 文件 environment.xml 文件格式 <environment> <parameter> <key>Browser</key> <value>Chrome</value> </parameter> <parameter> <key>Browser.Version</key> <value>63.0</value> </parameter> <parameter> <key>Stand</key> <value>Production</value> </parameter> </environment> (4)通过copy命令解决配置文件被删除问题 (1)在运行 pytest 生成 allure 报告的时候,偶尔需要加 --clean 参数,清除之前的报告记 录,这样会之前清空 result 目录,environment.properties文件也会被删除 (2)为了不让 environment.properties 文件删除掉,可以把 environment.properties 文件放 项目根目录,在运行报告的时候,先 copy 到 report 目录 <-----test_case_02.py-----> #coding=utf-8 import os import pytest import allure def login(username,password): """登陆""" print("输入账户: %s" % username) print("输入密码: %s" % password) # 返回 return {"code":0,"msg":"success!"} # 测试数据 test_datas = [ ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"), ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"), ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆") ] """ 使用@allure.title()时,可以加上传入的参数, 比如test_input,可以拼接test_input的值 """ @allure.story("登陆接口") @pytest.mark.parametrize("test_input,expected,title", test_datas) def test_login(test_input,expected,title): """测试登陆用例""" # 获取函数返回结果 result = login(test_input["username"],test_input["password"]) # 断言 assert result["msg"] == expected # 断言成功的用例,动态更新标题 allure.dynamic.title(title) if __name__ == '__main__': pytest.main(["test_case_02.py",'--alluredir','./result4','--clean-alluredir']) # 把 environment.properties 文件放项目根目录,在运行报告的时候,先 copy 到 result 目录 os.system('copy environment.properties result4\\environment.properties') os.system('allure serve result4')
>>>>>待续
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构