Allure
自动化用例
#coding=utf-8 """ 【自动化用例】 feature 特性名称 story 用户故事/场景 title 对应用例的标题 testcase 对应禅道系统的bug用例url地址,关联起来 issue 如果这个用例有bug,应该关联对应的bug地址 step 用例步骤描述 功能用例整体描述:写在用例方法的注释里 """ 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')
【用例等级设置】
#coding=utf-8 """ 用例等级 allure对用例的等级划分成五个等级: blocker 阻塞缺陷(功能未实现,无法下一步) critical 严重缺陷(功能点缺失) normal 一般缺陷(边界情况,格式错误) minor 次要缺陷(界面错误与ui需求不符) trivial 轻微缺陷(必须项无提示,或者提示不规范) """ import os import allure import pytest @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']) # 如果有很多测试用例,现在想做快速回顾,只执行用例级别为blocker和critical的测试用例 # pytest.main(['--alluredir', './muzi', '--allure-severities', 'blocker,critical']) # pytest.main(['--alluredir','./muzi','--allure-severities','blocker,critical','--clean-alluredir']) os.system('allure generate ./muzi/ -o ./report/ --clean') # os.system('allure serve muzi')
desc
#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']) # 根据epic执行 # pytest.main(['--alluredir','./muzi', # '--allure-epics=大模块名称:NGBSS', # '--clean-alluredir']) # 根据feature来执行 # pytest.main(['--alluredir','./muzi', # '--allure-features=欠费催缴', # '--clean-alluredir']) # 根据story来执行 # pytest.main(['--alluredir', './muzi', # '--allure-stories=测试场景四', # '--clean-alluredir']) # 多条件筛选 pytest.main(['--alluredir', './muzi', '--allure-stories=测试场景四,测试场景三', '--clean-alluredir']) os.system('allure serve muzi')
step
将用例步骤做关键字封装
1)将用例步骤做关键字封装
1 #common_function.py
2)开始用例设计,登陆单独拿出来,做成前置操作,后面的步骤合起来就是一个用例
1 #test_allure_step.py
3)测试步骤也可以在函数上加上装饰器来实现:
@allure.step()
1 #common_function2.py
2 #test_allure_stepx.py
两种方式对比:
使用 with allure.step("step:步骤") 这种方式代码可读性更好一点, 但不会带上函数里面的传参和对应的值。
使用 @allure.step("step:步骤") 这种方式会带上函数的传参和对应的值。
这两种方式结合起来使用,才能更好的展示测试报告!
# coding=utf-8 # @time: 2022/3/3-16:50 # @author: ljf # @file:common_function.py 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")
# coding=utf-8 # @time: 2022/3/3-16:50 # @author: ljf # @file:common_function2.py 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")
# coding=utf-8 # @time: 2022/3/3-16:51 # @author: ljf # @file:test_allure_step.py import os from 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')
# coding=utf-8 # @time: 2022/3/3-16:53 # @author: ljf # @file:test_allure_stepx.py import os from 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')
title
【参数化结合allure.title()生成不同标题报告】
1.参数化parametrize
1 #test_a.py
2.param+ids参数
1 #test_a_ids.py
3.allure.title描述用例
1 #test_a_title.py
4.优化用例title
1 #test_a_title_new.py
# coding=utf-8 # @time: 2022/3/3-17:05 # @author: ljf # @file:conftest.py 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")
# coding=utf-8 # @time: 2022/3/3-17:11 # @author: ljf # @file:test_a_ids.py 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') os.system('allure serve result2')
# coding=utf-8 # @time: 2022/3/3-18:00 # @author: ljf # @file:test_a_title.py 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')
# coding=utf-8 # @time: 2022/3/3-18:15 # @author: ljf # @file:test_a_title_new.py 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')
Prame参数
# coding=utf-8
# @time: 2022/3/3-18:36
# @author: ljf
# @file: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")
@allure.description("原始描述")
def test_dynamic_description():
# 断言成功后,可以在测试主体内部动态更新描述
assert 42 == int(6 * 7)
# 断言失败,不会动态更新描述
# assert 43 == int(6 * 7)
allure.dynamic.description(desc)
@allure.title("原始标题")
def test_with_dynamic_title():
assert 2 + 2 == 4
allure.dynamic.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')
# coding=utf-8 # @time: 2022/3/3-18:37 # @author: ljf # @file:test_case_02.py 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')
【allure动态生成用例标题】
1.allure.dynamic 常用动态属性
feature 模块
allure.dynamic.feature(feature_name)
功能点 story
allure.dynamic.story(case_story)
用例标题 title
allure.dynamic.title(case_title)
2.description 用例描述动态更新
1 # test_case_01.py 2 # 接口用例描述例子 3 desc = "<font color='red'>请求URL:</font>{}<Br/>" \ 4 "<font color='red'>请求类型:</font>{}<Br/>" \ 5 "<font color='red'>期望结果:</font>{}<Br/>" \ 6 "<font color='red'>实际结果描述:</font>{}<Br/>" \ 7 .format("http://www.baidu.com", "post", "200", "404") 8 9 @allure.description("原始描述") 10 def test_dynamic_description(): 11 # 断言成功后,可以在测试主体内部动态更新描述 12 # assert 42 == int(6*7) 13 # 断言失败,不会动态更新描述 14 assert 43 == int(6*7) 15 allure.dynamic.description(desc)
3.title 用例标题动态更新
1 @allure.title("原始标题") 2 def test_dynamic_title(): 3 assert 2 + 2 ==4 4 allure.dynamic.title("当断言成功时,用例标题会动态更新")
4.参数化时,使用@allure.title给用例不同标题
1 @allure.title("参数化用例标题:添加{param1}和{param2}") 2 @pytest.mark.parametrize('param1,param2,expected',[ 3 (2,2,4), 4 (1,2,5) 5 ]) 6 def test_param_title(param1,param2,expected): 7 assert param1 + param2 == expected
5.参数化时,在用例里使用allure.dynamic.title更新用例的标题
1 @allure.story("登陆接口") 2 @pytest.mark.parametrize("test_input,expected,title", 3 test_datas) 4 def test_login(test_input,expected,title): 5 """测试登陆用例""" 6 # 获取函数返回结果 7 result = login(test_input["username"],test_input["password"]) 8 # 断言 9 assert result["msg"] == expected 10 # 断言成功的用例,动态更新标题 11 allure.dynamic.title(title)
allure_env
#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')
【allure报告清空上一次记录】
1.allure报告可以记录用例每次执行的情况,方便跟踪用例的成功率,数据保留到json文件 中
2.会带来一个问题,当你代码里面的用例删除或者更换名称后,依然会记录之前的用例报告
3.--clean-alluredir 每次用例执行之前先清空allure的报告记录
4.使用 pytest -h 可以查看报告相关的三个参数
reporting:
--alluredir=DIR Generate Allure report in the specified directory (may not exist)
--clean-alluredir Clean alluredir folder if it exists
--allure-no-capture Do not attach pytest captured logging/stdout/stderr to report reporting
报告相关参数
--alluredir=DIR 指定报告的目录路径
--clean-alluredir 如果已经存在报告,就先清空它
--allure-no-capture 不加载
logging/stdout/stderr 文件到报告
【allure生成环境配置】
1.allure报告默认没有环境信息
2.添加环境信息方式一:environment.properties
在allure的result目录(json数据里的)下添加一个 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> <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>
3.通过copy命令解决配置文件被删除问题
在运行 pytest 生成 allure 报告的时候,有时候需要加 --clean 参数,清除之前的报告记 录,这样会之前清空 result 目录,environment.properties文件也会被删除。
为了不让 environment.properties 文件删除掉,可以把 environment.properties 文件放 项目根目录,在运行报告的时候,先 copy 到 report 目录
1 if __name__ == '__main__': 2 pytest.main(["test_case_02.py",'‐‐alluredir','./result4','‐‐clean‐allure dir']) 3 # 把 environment.properties 文件放项目根目录,在运行报告的时候,先 copy 到 r esult 目录 4 os.system('copy environment.properties result4\\environment.properties') 5 os.system('allure serve result4')