Environment 是环境变量,报告默认是没有任何变量参数的,是需要自己配置的。
通过创建 environment.properties 或者 environment.xml 文件,并把文件存放到测试结果的文件夹(执行脚本时,--alluredir 选项后指定的目录)。
例如:
pytest -n auto --alluredir=allure
存放在allure文件夹里。
1、添加配置文件
方式一:environment.properties
文件内容:
Browser=Chrome Browser.Version=89.0.4389.128 Stand=Test ApiUrl=127.0.0.1/login python.Version=3.7.9
方式二:environment.xml
文件内容:
<environment> <parameter> <key>Browser</key> <value>Chrome</value> </parameter> <parameter> <key>Browser.Version</key> <value>89.0.4389.128</value> </parameter> <parameter> <key>Stand</key> <value>Test</value> </parameter> <parameter> <key>ApiUrl</key> <value>127.0.0.1/login</value> </parameter> <parameter> <key>python.Version</key> <value>3.7.9</value> </parameter> </environment>
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
3、报告展示效果:
注:environment.xml 方式,文件内容含中文时,报告显示正常。
注:environment.properties 方式,文件内容含中文时,报告显示乱码。
运行 pytest 生成 allure 报告时,有时候需要加参数 --clean-alluredir(清除之前的报告记录),而配置文件(environment.properties 或 environment.xml)也会被删除。
解决方法:
将配置文件(environment.properties 或 environment.xml)存放于项目根目录,运行报告之前,拷贝到报告目录里即可。
项目目录结构:
运行命令(配置文件 environment.properties)
pytest test_case.py --alluredir=allure --clean-alluredir cp environment.properties ./allure/environment.properties allure serve allure
运行命令(配置文件 environment.xml)
pytest test_case.py --alluredir=allure --clean-alluredir cp environment.xml ./allure/environment.xml allure serve allure
Categories 是分类(测试用例结果的分类)
默认情况下,有两类缺陷:
Product defects 产品缺陷(测试结果:failed)
Test defects 测试缺陷(测试结果:error/broken)
可以创建自定义缺陷分类,将 categories.json 文件添加到测试结果的目录即可(和 environment.properties 放同一个目录)。
categories.json 参数:
name:分类名称。
matchedStatuses:测试用例的运行状态,默认["failed", "broken", "passed", "skipped", "unknown"]。
messageRegex:测试用例运行的错误信息,默认是 .* ,是通过正则去匹配的。
traceRegex:测试用例运行的错误堆栈信息,默认是 .* ,是通过正则去匹配的。
categories.json文件内容:
[ { "name": "Ignored tests", "matchedStatuses": ["skipped"] }, { "name": "Infrastructure problems", "matchedStatuses": ["broken", "failed"], "messageRegex": ".*signOut.*" }, { "name": "Outdated tests", "matchedStatuses": ["broken"], "traceRegex": ".*FileNotFoundException.*" }, { "name": "Product defects", "matchedStatuses": ["failed"] }, { "name": "Test defects", "matchedStatuses": ["broken"] } ]
如图所示:测试用例报错时,显示效果
在 allure 报告中添加测试用例步骤有两种方式:
1、@allure.step() 这种方式会带上函数的传参和对应的值。
2、with allure.step() 这种方式代码可读性更好一点,但不会带上函数里面的传参和对应的值。
allure 报告允许对每个测试用例进行非常详细的步骤说明,通过 @allure.step() 装饰器,可以让测试用例在 allure 报告中显示更详细的测试过程。
@allure.step() 只有一个参数,就是 title,输入标题内容,allure 报告上就会显示出来。
1、创建test_allure_step.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure @allure.step("第一步") def step_one(): pass @allure.step("第二步") def step_two_with_nested(): step_three() @allure.step("第三步") def step_three(): step_four_with_arguments(123456, 'AllTests') @allure.step("第四步{0},{arg2}") def step_four_with_arguments(arg1, arg2): pass @allure.step("第五步") def test_step_five(): step_one() step_two_with_nested()
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
像Python字符串一样,支持位置参数和关键字参数
如:第四步{0},{arg2}
1、创建test_allure_step2.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure def one(): pass def two_with_nested(): three() def three(): pass def four(arg1, arg2): pass def five(): one() two_with_nested() def test_case(): with allure.step("第一步"): one() with allure.step("第二步"): two_with_nested() with allure.step("第三步"): three() with allure.step("第四步"): four(arg1=123456, arg2='AllTests') with allure.step("第五步"): five()
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
执行第四步时,报告没有带上函数里面的传参和对应的值。
allure 报告可以显示许多不同类型的附件,这些附件可以补充测试、步骤或装置结果。
可以通过调用:
方式一:
allure.attach(body, name, attachment_type, extension)
参数:
body:要写入文件的原始内容。
name:附件名。
attachment_type:附件类型(是 allure.attachment_type 里面的其中一种)。
extension:所创建文件的扩展名。
allure.attachment_type提供的附件类型:
方式二:
allure.attach.file(source, name, attachment_type, extension)
参数:
source:包含文件路径的字符串。
(其他参数相同)
1、创建test_allure_attach.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import pytest import allure @pytest.fixture def attach_fixture_one(request): allure.attach('fixture前置操作,添加一个附件txt', 'fixture前置附件', allure.attachment_type.TEXT) def attach_fixture_two(): allure.attach('fixture后置操作,添加一个附件txt', 'fixture后置附件', allure.attachment_type.TEXT) request.addfinalizer(attach_fixture_two) def test_attach_fixture(attach_fixture_one): print("allure") def test_attach_fixture_file(): allure.attach('<head></head><body> a page </body>', 'page demo', allure.attachment_type.HTML) allure.attach.file('./demo.html', 'AllTests demo', attachment_type=allure.attachment_type.HTML)
创建demo.html文件(存放到项目的根目录上)
文件内容:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>软件测试</title> </head> <body> <h1>AllTests</h1> </body> </html>
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
用例test_attach_fixture
用例test_attach_fixture_file,第一个附件为手写的HTML,第二个附件是导入的HTML文件。
添加足够详细的测试用例描述,更加方便查看测试步骤。
三种方式:
方式一: @allure.description_html(str):传一个HTML代码组成的字符串 方式二: @allure.description(str) 方式三: 在测试用例函数下方添加 """ """
1、创建test_allure_description.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure # 方式一 @allure.description_html(""" <h1>Test with some complicated html description</h1> <table style="width:100%"> <tr> <th>Firstname</th> <th>Lastname</th> <th>Age</th> </tr> <tr align="center"> <td>William</td> <td>Smith</td> <td>50</td> </tr> <tr align="center"> <td>Vasya</td> <td>Jackson</td> <td>94</td> </tr> </table> """) def test_html_description(): assert True # 方式二 @allure.description(""" 多行测试描述 这是一个@allure.description装饰器 """) def test_description_from_decorator(): assert 42 == int(6 * 7) # 方式三 def test_unicode_in_docstring_description(): """ 多行测试描述 assert断言 """ assert 42 == int(6 * 7)
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
方式一:
方式二:
方式三:
测试用例的标题可以通过特殊的方式变得更易读,标题支持参数占位符并支持动态替换。
示例一:
1、创建test_allure_title.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import pytest import allure @allure.title("前置操作:登录") @pytest.fixture def test_login(request): params = request.param name = params["username"] pwd = params["pwd"] allure.attach(f"测试用例传的参数{params}") print(name, pwd, params) yield name, pwd @allure.title("登录成功,测试数据:{test_login}") @pytest.mark.parametrize("test_login", [{"username": "admin", "pwd": "123456"}, {"username": "root", "pwd": "root"}], indirect=True) def test_login_success(test_login): name, pwd = test_login allure.attach(f"账号:{name},密码:{pwd}")
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
示例二:
1、创建test_allure_title2.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import pytest import allure @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
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
链接(访问链接)
装饰器源码:
参数:
url:跳转的链接。
name:显示在 allure 报告的名字,如果不传就是显示完整的链接。
类似的装饰器:
Bug链接:@allure.issue()
测试用例链接:@allure.testcase()
1、创建test_allure_link.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure @allure.link('https://www.baidu.com/') def test_with_link(): pass @allure.link('https://www.baidu.com/', name='百度一下') def test_with_named_link(): pass
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
无name参数
有name参数
链接(Bug链接)
装饰器源码:
调用link(),但link_type=LinkType.ISSUE。
参数:
url:跳转的链接。
name:显示在 allure 报告的名字,如果不传就是显示完整的链接。
类似的装饰器:
访问链接:@allure.link()
测试用例链接:@allure.testcase()
1、创建test_allure_issue.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure @allure.issue('https://www.baidu.com/') def test_with_issue(): pass @allure.issue('https://www.baidu.com/', 'BUG链接') def test_with_named_issue(): pass
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
无name参数
有name参数
链接(测试用例链接)
装饰器源码:
调用link(),但link_type=LinkType.TEST_CASE。
参数:
url:跳转的链接。
name:显示在 allure 报告的名字,如果不传就是显示完整的链接。
类似的装饰器:
访问链接:@allure.link()
Bug链接:@allure.issue()
1、创建test_allure_testcase.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure @allure.testcase('https://www.baidu.com/') def test_with_testcase(): pass @allure.testcase('https://www.baidu.com/', '测试用例地址') def test_with_named_testcase(): pass
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
无name参数
有name参数
allure 标记装饰器(可显示在测试报告上):
@allure.epic:敏捷里面的概念,定义史诗,往下是 feature。
@allure.feature:功能点的描述,理解成模块,往下是 story。
@allure.story:故事,往下是 title。
示例一:
1、创建test_allure_epic_feature_story.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure def test_without_any_annotations_that_wont_be_executed(): pass @allure.story('story1') def test_with_story1(): pass @allure.story('story2') def test_with_story2(): pass @allure.feature('feature3') @allure.story('story3') def test_with_feature3_story3(): pass @allure.epic('epic4') @allure.feature('feature4') @allure.story('story4') def test_with_epic4_feature4_story4(): pass @allure.epic('epic5') @allure.feature('feature5') class TestCase: @allure.story('story5_1') def test_with_story5_1(self): print("执行 test_with_story5_1") @allure.story('story5_2') def test_with_story5_2(self): print("执行 test_with_story5_2")
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
首页FEATURES BY STORIES区域显示所设置的标记
Behaviors栏目下,带有标记的测试用例显示的标记层次顺序
示例二:命令行运行,指定运行某个标记(epic、feature、story)
命令行参数:
--allure-epics
--allure-features
--allure-stories
1、创建test_allure_epic_feature_story2.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import pytest import allure import os @pytest.fixture(scope="session") def login_fixture(): print("===前置操作-登陆===") @allure.step("步骤1") def step1(): print("===操作步骤1===") @allure.step("步骤2") def step2(): print("===操作步骤2===") @allure.step("步骤3") def step3(): print("===操作步骤3===") @allure.epic("总体描述1") @allure.feature("测试模块1") class TestCaseAll1: @allure.testcase("https://www.baidu.com/", "测试用例") @allure.issue("https://www.baidu.com/", "Bug链接") @allure.title("用例标题") @allure.story("story1") @allure.severity("critical") def test_case1(self, login_fixture): print("===测试用例1===") step1() step2() @allure.story("story2") def test_case2(self, login_fixture): print("===测试用例2===") step1() step3() @allure.epic("总体描述2") @allure.feature("测试模块2") class TestCaseAll2: @allure.story("story3") def test_case3(self, login_fixture): print("===测试用例3===") step1() @allure.story("story4") def test_case4(self, login_fixture): print("===测试用例4===") step3() if __name__ == '__main__': pytest.main(['-s', '-q', '--alluredir', './allure']) os.system('allure -c ./allure') os.system('allure serve ./allure')
2、运行结果:
(1)运行全部:
执行完成后,自动打开浏览器加载测试报告
(2)命令行指定运行:
1)、只运行epic名为“总体描述1”的测试用例
pytest --alluredir ./allure --allure-epics=总体描述1 allure serve allure
运行结果:
2)、只运行feature名为“测试模块2”的测试用例
pytest --alluredir ./allure --allure-features=测试模块2 allure serve allure
运行结果:
3)、只运行story1、story3的测试用例(可以不用=号 空格也可以)
pytest --alluredir ./allure test_allure_epic_feature_story2.py --allure-stories story1,story3 allure serve allure
运行结果:
4)运行指定的feature+story的测试用例(可以不用=号 空格也可以)
pytest --alluredir ./allure test_allure_epic_feature_story2.py --allure-features 测试模块2 --allure-stories story2 allure serve allure
运行结果:
用来标记用例级别。
Allure 提供的用例等级:
BLOCKER = 'blocker' 阻塞缺陷(功能未实现,无法下一步)
CRITICAL = 'critical' 严重缺陷(功能点缺失)
NORMAL = 'normal' 一般缺陷(边界情况,格式错误)
MINOR = 'minor' 次要缺陷(界面错误与UI需求不符)
TRIVIAL = 'trivial 轻微缺陷(必须项无提示,或者提示不规范等)
一、示例:
1、创建test_allure_severity.py文件
脚本代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 微信公众号:AllTests软件测试 """ import allure def test_with_no_severity(): pass @allure.severity(allure.severity_level.BLOCKER) def test_with_blocker_severity(): pass @allure.severity(allure.severity_level.CRITICAL) def test_with_critical_severity(): pass @allure.severity(allure.severity_level.MINOR) def test_with_minor_severity(): pass @allure.severity(allure.severity_level.TRIVIAL) def test_with_trivial_severity(): pass @allure.severity(allure.severity_level.NORMAL) def test_with_normal_severity(): pass @allure.severity(allure.severity_level.NORMAL) class TestClassWithNormalSeverity(object): def test_inside_the_normal_severity_test_class(self): """ 测试类优先级 normal """ print("测试类优先级 normal") @allure.severity(allure.severity_level.CRITICAL) def test_inside_the_normal_severity_test_class_with_overriding_critical_severity(self): """ 测试类优先级 normal 测试用例优先级 critical """ print("测试类优先级 normal;测试用例优先级 critical") @allure.severity("normal") def test_case_1(): """ normal 级别测试用例 """ print("normal 级别测试用例") @allure.severity("critical") def test_case_2(): """ critical 级别测试用例 """ print("critical 级别测试用例") @allure.severity("blocker") def test_case_3(): """ blocker 级别测试用例 """ print("blocker 级别测试用例") @allure.severity("minor") def test_case_4(): """ minor 级别测试用例 """ print("minor 级别测试用例") @allure.severity("trivial") def test_case_5(): """ trivial 级别测试用例 """ print("trivial 级别测试用例") def test_case_6(): """ 未标记 severity 的用例默认为 normal """ print("未标记 severity 的用例默认为 normal") @allure.severity("normal") def test_case_7(): """ normal 级别测试用例 """ assert (1 == 2) @allure.severity("critical") def test_case_8(): """ critical 级别测试用例 """ assert (1 == 2) @allure.severity("blocker") def test_case_9(): """ blocker 级别测试用例 """ assert (1 == 2)
2、输入命令运行:
pytest -n auto --alluredir=allure allure serve allure
运行结果:
Severity字段标记用例级别
图表里统计用例优先级
二、命令行参数运行:
根据优先级选择需要运行的测试用例
参数:
--allure-severities
例如:只运行severity=blocker、critical的测试用例,命令行输入
写法一:
pytest test_allure_severity.py -sq --alluredir=allure --allure-severities=blocker,critical
写法二:
pytest test_allure_severity.py -sq --alluredir=allure --allure-severities blocker,critical
运行结果:
按照需要运行的用例级别,运行了7条测试用例。