会员
周边
众包
新闻
博问
闪存
赞助商
Chat2DB
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
大话人生
博客园
::
首页
::
新随笔
::
联系
::
订阅
::
管理
公告
pytest从入门到精通-1
pytest从入门到精通-1
pytest从入门到精通-1
一、pytest单元测试框架
二、单元测试框架和自动化测试框架有什么关系
三、pytest简介
1.什么是单元测试框架
单元测试是指在软件开发当中,针对软件的最小单位(函数,方法)进行正确性的检查
测试
2.单元测框架的分类
3.单元测试框架主要做什么
java
junit
testng
python
unittest
pytest
1.测试发现
2.测试执行
3.测试判断
4.测试报告
从多个文件里面去找测试用例
按照一定的顺序和规则去执行,并生成结果
通过断言判断预期结果和实际结果的差异
统计测试进度,耗时,通过率等,生成测试报告
1.什么是自动化测试框架
2.自动化测试框架的作用
自动化测试框架是由测试组长或者自动化测试主管搭建的一套用于自动化测试的系统框
架
1.提高测试效率,降低维护成本
2.减少人工干预,提高测试的准确性,增加代码的重用性
3.核心思想是让不懂代码的人也能够通过这个框架去实现自动化测试
3.pytest单元测试框架和自动化测试框架的关系
单元测试框架是自动化测试框架中的组成部分之一
pom设置模式是自动化测试框架中组成部分之一
数据驱动是自动化测试框架中组成部分之一
关键字驱动是自动化测试框架中组成部分之一
全局配置文件是自动化测试框架中组成部分之一
日志监控是自动化测试框架中组成部分之一
pytest全局配置文件为pytest.ini,
需要放置在项目的根目录下
selenium,requests二次封装是自动化测试框架中组成部分之一
断言是自动化测试框架中组成部分之一
报告邮件是自动化测试框架中组成部分之一
其他更多的内容
1.pytest是一个非常成熟的python的单元测试框架,比unittest更灵活,更容易上手
2.pytest可以和selenium,requests,appium结合实现web自动化,接口自动化,app自动化
3.pytest可以实现测试用例的跳过以及reruns失败用例重试
4.pytest可以和allure生成非常美观的测试报告
5.pytest可以和Jenkins持续集成
6.pytest有很多非常强大的插件,并且这些插件能够实现很多的实用的操作
插件
pytest
pytest-xdist
pytest-ordering
pytest-rerunfailures
pytest-html
用于测试用例分布式执行,多CPU分发
用于改变测试用例的执行顺序
用例失败后重跑
生成html格式的自动化测试报告
allure-pytest
用于生成美观的测试报告
插件安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
requirements.txt
pytest
pytest-xdist
pytest-ordering
pytest-rerunfailures
pytest-html
allure-pytest
查看检验安装后的版本
pytest --version
四、使用pytest,默认的测试用例的规则以及基础应用
1.模块名必须以test_开头或者_test结尾
test_baidu.py
google_test.py
2.测试类必须以Test开头,并且不能有init方法
class TestBaiDu():
3.测试方法必须以test开头
def test001(self):
print("测试百度搜索")
def test002():
print("测试百度登录")
class TestBaiDu():
def test001(self):
print("测试百度搜索")
五、pytest测试用例的运行方式
1.主函数模式
2.命令模式
参数详解
1.运行所有
pytest.main()
import pytest
def test002():
print("测试百度登录")
class TestBaiDu():
def test001(self):
print("测试百度搜索")
if __name__ == '__main__':
pytest.main()
模块内运行
模块外运行
test_baidu.py
import pytest
def test002():
print("测试百度登录")
class TestBaiDu():
def test001(self):
print("测试百度搜索")
runPytest.py
import pytest
pytest.main()
test_baidu.py
2.指定模块
3.指定目录
4.通过nodeid指定用例运行
1.运行所有
pytest
(mypytest) D:\PycharmProjects\mypytest>pytest
pytest.main(['-vs','test_baidu.py'])
runPytest.py
import pytest
pytest.main(['-vs','test_baidu.py'])
2.指定模块
pytest -vs test_baidu.py
(mypytest) D:\PycharmProjects\mypytest>pytest -vs test_baidu.py
pytest.main(['-vs','./testcase'])
runPytest.py
import pytest
pytest.main(['-vs','./testcase'])
3.指定目录
pytest -vs ./testcase
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase
nodeid由模块名,分隔符,类名,方法名,函数名组成
运行目录下模块中的函数
pytest.main(['-vs','./testcase/souhu_test.py::testsouhulogin'])
runPytest.py
import pytest
pytest.main(['-vs','./testcase/souhu_test.py::testsouhulogin'])
其中模块名字和函数之间的分隔符用英文双冒号(::)
运行目录下模块中类的函数
pytest.main(['-vs','./testcase/souhu_test.py::TestSouHu::testsearch'])
runPytest.py
import pytest
pytest.main(['-vs','./testcase/souhu_test.py::TestSouHu::testsearch'])
其中模块名字和类名之间的分隔符用英文双冒号(::)
类名与函数名之间的分隔符也用英文双冒号(::)
4.通过nodeid指定用例运行
pytest -vs ./testcase/souhu_test.py::TestSouHu::testsearch
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase/souhu_test.py::TestSouHu::testsearch
3.通过读取pytest.ini全局配置文件运行
-s
表示输出调试信息,包括print打印的信息
-v
表示更详细的信息,会打印出用例名字和执行结果
-vs
这两个参数一起用
-n
支持多线程或者分布式运行测试用例
主函数模式运行
命令模式运行
runPytest.py
import pytest
pytest.main(['-vs','./testcase','-n 2'])
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase -n 2
--reruns NUM
失败用例重跑
命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase -n 2 --reruns 2
-x
表示只要有一个用例报错,那么测试停止
主函数模式运行
命令模式运行
runPytest.py
import pytest
pytest.main(['-vsx','./testcase'])
(mypytest) D:\PycharmProjects\mypytest>pytest -vsx ./testcase
--maxfail=2
出现两个用例失败就停止
命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase --maxfail=2
-k
根据测试用例的部分字符串指定测试用例
命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase -k "ch"
--html ./report/report.html
生成html的测试报告
命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest -vs ./testcase -m "smoke or usermanage or productnamage"
pytest.ini 这个文件是pytest单元测试框架的核心配置文件
1.位置
2.编码
3.作用
4.运行的规则;不管是主函数的模式运行,命令行模式运行,都会去读这个配置文件。
一般放在项目的根目录
必须是ANSI,可以使用notpad++修改编码格式
改变pytest默认的行为
pytest.ini内容
[pytest]
addopts=-vs #命令行的参数,用空格分隔
testpaths=./testcase #测试用例的路径
python_files=test_*.py #模块名的规则
python_classes=Test* #类名的规则
python_functions=test #方法名的规则
使用命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest
注释实际配置中要将中文去掉,文件编码模式修改为ANIS编码(用nodepad++修改)
[pytest]
addopts=-vs --html ./report/report.html
testpaths=./testcase
python_files=*_test.py
python_classes=Test*
python_functions=test
六、pytest执行测试用例的顺序是怎样的呢
unittest
是根据测试用例名称的ascII值的大小来绝对的执行的顺序
pytest
默认从上到下顺序执行
改变默认的执行顺序
使用mark标记
@pytest.mark.run(order=1)
import pytest
def testsouhulogin():
print("登录搜狐")
class TestSouHu():
@pytest.mark.run(order=2)
def testsearch(self):
print("搜狐搜索视频")
assert False
@pytest.mark.run(order=3)
def testclick(self):
print("搜狐点击")
assert False
@pytest.mark.run(order=1)
def testswipe(self):
print("搜狐滑动")
assert False
七、如何分组执行(冒烟,分模块执行,分接口和web执行)
smoke
冒烟用例,分布在各个模块里面
-m "smoke or usermanage or productnamage"
分组执行
(mypytest) D:\PycharmProjects\mypytest>pytest -m "smoke"
代码中的标记
import pytest
def testsouhulogin():
print("登录搜狐")
class TestSouHu():
@pytest.mark.run(order=2)
def testsearch(self):
print("搜狐搜索视频")
assert False
@pytest.mark.run(order=3)
@pytest.mark.smoke
def testclick(self):
print("搜狐点击")
assert False
@pytest.mark.run(order=1)
def testswipe(self):
print("搜狐滑动")
assert False
命令模式运行
(mypytest) D:\PycharmProjects\mypytest>pytest -m "smoke"
代码中标记的“smoke”与命令模式中-m后面的“smoke”一定要一致
八、pytest跳过测试用例
1.无条件跳过
2.有条件跳过
@pytest.mark.skip(reason="太难了")
import pytest
def testsouhulogin():
print("登录搜狐")
class TestSouHu():
@pytest.mark.run(order=2)
def testsearch(self):
print("搜狐搜索视频")
assert False
@pytest.mark.run(order=3)
@pytest.mark.smoke
@pytest.mark.skip(reason="太难了")
def testclick(self):
print("搜狐点击")
assert False
@pytest.mark.run(order=1)
def testswipe(self):
print("搜狐滑动")
assert False
@pytest.mark.skipif(age>=18,reason='已成年')
第一个参数是条件:age>=18
第二个参数是描述原因:reason='已成年'
import pytest
def testsouhulogin():
print("登录搜狐")
class TestSouHu():
age=18
@pytest.mark.run(order=2)
def testsearch(self):
print("搜狐搜索视频")
assert False
@pytest.mark.run(order=3)
@pytest.mark.smoke
@pytest.mark.skip(reason="太难了")
def testclick(self):
print("搜狐点击")
assert False
@pytest.mark.run(order=1)
@pytest.mark.skipif(age>=18,reason='已成年')
def testswipe(self):
print("搜狐滑动")
assert False
allure
安装allure
1.下载allure
网址::https://github.com/allure-framework/allure2/releases/tag/2.17.3
下载其中的如allure-2.17.3.zip,解压放到本地,并配置环境变量到path,如D:\Program
Files\allure-2.17.3\bin(配置到bin目录)
2.验证allure是否配置成功
cmd中或者pycharm的命令行中输入
allure --version
出现版本信息即可
3.生成allure报告
1.先生成临时的json格式的报告
2.再根据生成的json格式的报告生成html的报告
在pytest.ini配置文件中添加 --alluredir ./temps --clean-alluredir
[pytest]
addopts=-vs --html ./report/report.html --alluredir ./temps --clean-alluredir
testpaths=./testcase
python_files=*_test.py
python_classes=Test*
python_functions=test
表示生成临时的json格式的报告到项目根目录下的temps文件夹下;
--clean-alluredir,表示先清除temps文件夹下之前的内容,保证是最新的json内容;
os.system("allure generate ./temps -o ./reports --clean")
主函数模式运行
runPytest.py
import pytest
import os
import time
pytest.main()
time.sleep(2) #生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean")
表示生成的json格式放在temps目录下,生成的报告放在reports目录下;
--clean,表示生成报告前先清除原有内容
参数都可以放到pytest.ini中的addopts 的值中
[pytest]
addopts=-vs -m "smoke" #命令行的参数,用空格分隔
testpaths=./testcase #测试用例的路径
python_files=test_*.py #模块名的规则
python_classes=Test* #类名的规则
python_functions=test #方法名的规则
[pytest]
addopts=-vs -m "smoke" --maxfail=2 --html ./report/report.html #命令行的参数,用空格分隔
4.通过装饰器对allure报告进行定制
1.安装allure-pytest
pip install allure-pytest -i https://pypi.tuna.tsinghua.edu.cn/simple
2.查看是否安装allure-pytest
pip show allure-pytest
3.使用装饰器对测试报告中的测试用例进行分组
代码
souhu_test.py
import pytest
import allure
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题005:通过微信注册用户密码为空的情况')
def testsouhulogin():
print("登录搜狐")
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题006:通过微信注册用户,用户名超长情况测试')
def testlonglogin():
print("用户名超长")
class TestSouHu():
age=18
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题001:通过微信正常注册男用户')
@pytest.mark.run(order=2)
def testsearch(self):
print("搜狐搜索视频")
assert False
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题002:通过微信正常注册女用户')
@pytest.mark.run(order=3)
@pytest.mark.smoke
@pytest.mark.skip(reason="太难了")
def testclick(self):
print("搜狐点击")
assert False
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题003:通过微信注册用户名为空白的用户')
@pytest.mark.run(order=1)
@pytest.mark.skipif(age>=18,reason='已成年')
def testswipe(self):
print("搜狐滑动")
assert False
class TestBaiDuYun():
@allure.feature('测试大需求001,用户注册')
@allure.story('大需求下的一个场景(或者又叫故事)001,微信用户注册')
@allure.title('测试用例的标题004:通过微信注册用户名为特殊字符的用户')
def testloginBaiDuYun(self):
print("登录百度云")
说明
@allure.feature
一个大需求
@allure.story
大需求下的一个故事,一个场景
@allure.title
本条用例的标题
4.功能用例和自动化用例做关联
自动化作到什么程度
自动化覆盖率为多少
自动化用例与功能用例无关,则无效
自动化测试用例去覆盖功能用例
一个功能用例
用例标题
前置条件
执行步骤
预期结果
一条自动化测试用例与功能用例的关联
feature
对应的模块
story
对应的场景
用例对应的禅道系统的bug用例url地址,关联起来
issue
如果这个用例有bug,应该关联对应的bug地址
自动化测试用例代码
test_case_01.py
"""
feature 对应的模块名称
story 对应的场景
用例对应的禅道系统的bug用例url地址,关联起来
issue 如果这个用例有bug,应该关联对应的bug地址
"""
import pytest
import allure
import os
import time
@allure.feature("编辑分类文章")
class TestArticle():
"""
编辑文章分类
"""
@allure.story("登录-编辑文章分类,重复保存,保存失败")
@allure.issue(url="http://127.0.0.1:8080/zentao/bug-view-1.html",name="不应该重复保存,而实际可以") #关联禅道bug
@allure.testcase(url="http://127.0.0.1:8080/zentao/testcase-view-1.html",name="重复保存失败") #关联禅道用例
def test_edit_class(self):
"""
用例描述:编辑文章分类-输入重复的分类,保存失败,不能添加重复的
setup(前置条件):登录成功
step(步骤)1:编辑文章分类,输入文章类别,如:计算机
step(步骤)2:点击保存按钮
step(步骤)3:重新打开编辑页面,输入:计算机
step(步骤)4:再次打开保存按钮
assert(断言,验证):保存失败,提示:已存在
"""
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("setup:登录成功"):
print("判断是否登录成功")
assert 1==1
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("step(步骤)1:编辑文章分类,输入文章类别,如:计算机"):
print("step(步骤)1:编辑文章分类,输入文章类别,如:计算机")
assert 1==1
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("step(步骤)2:点击保存按钮"):
print("step(步骤)2:点击保存按钮")
assert 1==1
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("step(步骤)3:重新打开编辑页面,输入:计算机"):
print("step(步骤)3:重新打开编辑页面,输入:计算机")
assert 1==1
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("step(步骤)4:再次打开保存按钮"):
print("step(步骤)4:再次打开保存按钮")
assert 1==1
#用with来做步骤执行,用assert来断言的是否登录成功(如存在某个元素等)
with allure.step("assert(断言,验证):保存失败,提示:已存在"):
print("assert(断言,验证):保存失败,提示:已存在")
assert 1==2
if __name__ == '__main__':
pytest.main(["-vs","test_case_01.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
说明
@allure.feature
模块
@allure.story
@allure.issue
@allure.testcase
故事,场景
bug关联
用例关联
with allure.step
用例步骤
5.用例的等级
allure 对用例的等级划分成五个等级
blocker
critical
normal
minor
trivial
阻塞缺陷(功能未实现,无法下一步)
严重缺陷(功能点缺失)
一般缺陷(边界情况,格式错误)
次要缺陷(界面错误与ui需求不符)
轻微缺陷(必须项无提示,或者提示不规范)
代码
test_case_02.py
import pytest
import allure
import os
import time
"""
用例等级
allure 对用例的等级划分成五个等级
blocker 阻塞缺陷(功能未实现,无法下一步)
critical 严重缺陷(功能点缺失)
normal 一般缺陷(边界情况,格式错误)
minor 次要缺陷(界面错误与ui需求不符)
trivial 轻微缺陷(必须项无提示,或者提示不规范)
"""
@allure.severity("normal")
def test_case_1():
"""
修改个人姓名为空
"""
print("test case 1:修改姓名为空")
@allure.severity("critical")
def test_case_2():
"""
修改个人姓名为已有人的身份证信息
"""
print("test case 2:修改姓名为他人信息")
@allure.severity("critical")
def test_case_3():
"""
修改个人信息-生日必填项置空
"""
print("test case 3:修改生日为空")
@allure.severity("blocker")
def test_case_4():
"""
修改个人信息-无法保存
"""
print("test case 4:无法保存")
def test_case_5():
"""
没标记的severity的用例默认为normal
"""
print("test case 5:不标记")
if __name__ == '__main__':
# pytest.main(["-vs","test_case_02.py",'--alluredir','./temps'])
#只执行指定级别的用例
pytest.main(["-vs", "test_case_02.py", '--alluredir', './temps','--allure-severities','blocker,critical'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
说明
@allure.severity
设置优先级
没有标记的用例优先级默认为normal
只执行指定级别的用例
pytest.main(["-vs", "test_case_02.py", '--alluredir', './temps','--allure-severities','blocker,critical'])
只执行blocker和critical的用例
6.allure用例描述
使用方法 参数值 参数说明
@allure.epic() epic描述 敏捷里面的概念,对用例或用例集进行描述分类,往下是feature
@allure.feature() 模块名称 与epic类似,只是比epic级别低,往下是story
@allure.story() 用户故事 与epic类似,只是比feature级别低,往下是title
@allure.title(用例的标题) 用例的标题 重命名html报告的用例名称
@allure.testcase() 测试用例的链接地址 与link类似
@allure.issue() 缺陷 与link类似
@allure.description() 用例描述 进行测试用例的描述
@allure.step() 操作步骤 进行测试用例的步骤
@allure.severity() 用例等级 blocker,critical,normal,minor,trivial
@allure.link() 链接 定义一个链接,在测试报告展现(推荐使用)
@allure.attachment() 附件 报告添加附件
将描述信息加入到用例中
代码
test_case_03.py
import os
import time
import pytest
import allure
@pytest.fixture(scope="session")
def login_fixture():
print("前置条件:登录")
@allure.step("步骤1")
def step_1():
print("操作步骤%s1"%("-"*30))
@allure.step("步骤2")
def step_2():
print("操作步骤2")
@allure.step("步骤3")
def step_3():
print("操作步骤%s3"%("-"*30))
@allure.epic("epic:大特性,一个描述性标签,大特性1")
@allure.feature("测试模块1")
class TestDemoAllure():
@allure.testcase("http://127.0.0.1:8080/zentao/testcase-view-6-1.html")
@allure.issue("http://127.0.0.1:8080/zentao/bug-view-1.html")
@allure.title("用例的标题")
@allure.story("用户故事:1")
@allure.severity("critical")
def test_case_1(self,login_fixture):
"""
case desc:
1.点文章分类导航标签 -跳转编辑页面
2.编辑页面输入,分类名称,如:上海-悠悠-可以输入
3.点保存按钮保存成功
"""
print("测试用例1")
step_1()
step_2()
@allure.story("用户故事:2")
def test_case_2(self,login_fixture):
"""
case desc:
1.点文章分类导航标签 -跳转编辑页面
2.编辑页面输入,分类名称,如:上海-悠悠-可以输入
3.点保存按钮保存成功
"""
print("测试用例2")
step_1()
step_3()
@allure.epic("epic对大Story的一个描述性标签,大特性2")
@allure.feature("模块2")
class TestDemoTwo():
@allure.story("用户故事:3")
@allure.severity("critical")
def test_case_3(self,login_fixture):
"""
case desc:
1.点文章分类导航标签 -跳转编辑页面
2.编辑页面输入,分类名称,如:上海-悠悠-可以输入
3.点保存按钮保存成功
"""
print("测试用例3")
step_1()
step_2()
@allure.story("用户故事:4")
def test_case_4(self,login_fixture):
"""
case desc:
1.点文章分类导航标签 -跳转编辑页面
2.编辑页面输入,分类名称,如:上海-悠悠-可以输入
3.点保存按钮保存成功
"""
print("测试用例4")
step_1()
step_3()
if __name__ == '__main__':
pytest.main(["-vs","test_case_03.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
7.添加用例步骤详解
代码
common_function.py
通用函数方法
"""
举个常见的测试场景用例
从登录开始,到浏览商品添加购物车,最后下单支付
用例步骤:
1.登录
2.浏览商品
3.添加购物车
4.生成订单
5.支付成功
"""
#把上面的每个环节,写成函数放到common_function.py
def login(username,password):
"""登录"""
print("前置操作:先登录")
def open_goods():
"""浏览商品"""
print("浏览商品")
def add_shopping_cart(goods_id="10086"):
"""添加购物车"""
print("添加购物车")
def buy_goods():
"""生成订单"""
print("生成订单")
def pay_goods():
"""支付订单"""
print("支付订单")
test_allure_step.py
测试用例编写用到通用方法
import os
import time
import pytest
import allure
from p05_testcase_step.common_function import *
#接下来的测试用例设计,登录可以单独那出来,当成前置操作
@pytest.fixture(scope="session")
def login_setup():
login(username="zz",
password="123456")
@allure.feature("功能模块")
@allure.story("测试用例小模块-成功案例")
@allure.title("测试用例名称:流程性用例,添加测试步骤")
def test_add_goods_and_buy(login_setup):
"""
用例描述:
前置:登录
用例步骤:
1.浏览商品
2.添加购物车
3.生成订单
4.支付成功
"""
with allure.step(title="step1:浏览商品"):
open_goods()
with allure.step(title="step2:添加购物车"):
add_shopping_cart(goods_id="10086")
with allure.step(title="step3:生成订单"):
buy_goods()
with allure.step(title="step4:支付成功"):
pay_goods()
with allure.step(title="断言"):
assert 1==1
if __name__ == '__main__':
pytest.main(["-vs","test_allure_step.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
另一种写测试步骤的方法
测试步骤也可以用装饰器实现@allure.step
代码
common_function_two.py
"""
举个常见的测试场景用例
从登录开始,到浏览商品添加购物车,最后下单支付
用例步骤:
1.登录
2.浏览商品
3.添加购物车
4.生成订单
5.支付成功
"""
#把上面的每个环节,写成函数放到common_function.py
#测试步骤也可以用装饰器实现@allure.step
import allure
@allure.step(title="setup:登录")
def login(username,password):
"""登录"""
print("前置操作:先登录")
@allure.step(title="step:浏览商品")
def open_goods():
"""浏览商品"""
print("浏览商品")
@allure.step(title="step:添加购物车")
def add_shopping_cart(goods_id="10086"):
"""添加购物车"""
print("添加购物车")
@allure.step(title="step:生成订单")
def buy_goods():
"""生成订单"""
print("生成订单")
@allure.step(title="step:支付订单")
def pay_goods():
"""支付订单"""
print("支付订单")
test_allure_step_two.py
import os
import time
import pytest
import allure
from p05_testcase_step.common_function_two import *
#接下来的测试用例设计,登录可以单独那出来,当成前置操作
@pytest.fixture(scope="session")
def login_setup():
login(username="zz",
password="123456")
@allure.feature("功能模块")
@allure.story("测试用例小模块-成功案例2")
@allure.title("测试用例名称:流程性用例,添加测试步骤")
def test_add_goods_and_buy_2(login_setup):
"""
用例描述:
前置:登录
用例步骤:
1.浏览商品
2.添加购物车
3.生成订单
4.支付成功
"""
open_goods()
add_shopping_cart(goods_id="10086")
buy_goods()
pay_goods()
assert 1==2
if __name__ == '__main__':
pytest.main(["-vs","test_allure_step_two.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
好处
可以将函数的参数带进报告中,展示出来
8.参数化(parametrize)结合allure.title()生成不同标题报告
allure报告清空上一次运行的记录(--clean-alluredir)
allure.dynamic动态生成用例标题
allure添加环境配置(environment)
allure报告添加用例失败截图
@pytest.mark.parametrize
表示参数化内容
代码
test_a.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!"),
({"username": "yoyo2", "password": "123456"}, "failed!"),
({"username": "yoyo3", "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(["-vs","test_a.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
这样生成的报告在用例列表里面并不能很友好的展示出每个用例的执行场景,只知道哪个用例报错了。
解决:可以对每个用例加上描述,加一个 ids 参数
代码
test_a_ids.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!"),
({"username": "yoyo2", "password": "123456"}, "failed!"),
({"username": "yoyo3", "password": "123456"}, "success!"),
]
@allure.story("登录用例")
@pytest.mark.parametrize("test_input,expected",
test_datas,
ids=[
"输入正确账号,密码,登录成功",
"输入错误账号,密码,登录失败",
"输入正确账号,密码,登录成功",
]
)
def test_login(test_input, expected):
'''测试登录用例'''
# 获取函数返回结果
result = login(test_input["username"], test_input["password"])
# 断言
assert result["msg"] == expected
if __name__ == '__main__':
pytest.main(["-vs","test_a_ids.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
也可以用 allure.title("用例描述") 添加用例描述的方式解决
代码
test_a_allure_title.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!"),
({"username": "yoyo2", "password": "123456"}, "failed!"),
({"username": "yoyo3", "password": "123456"}, "success!"),
]
@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(["-vs","test_a_allure_title.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
当没有加allure.title()时候,用例的描述就是 item.name 值(也就是上面的 ids 用例的名
称),
如果加了allure.title(),那么用例的描述就是添加的title值,这两个地方取其中的一个。
代码
(源代码)allure_pytest/utils.py
def allure_name(item, parameters):
name = escape_name(item.name)
title = allure_title(item)
return title.format(**parameters) if title else name
test_a_ids_allure_title.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!"),
({"username": "yoyo2", "password": "123456"}, "failed!"),
({"username": "yoyo3", "password": "123456"}, "success!"),
]
@allure.story("登录用例")
@allure.title("用例描述,测试输入:{test_input}")
@pytest.mark.parametrize("test_input,expected",
test_datas,
ids=[
"输入正确账号,密码,登录成功",
"输入错误账号,密码,登录失败",
"输入正确账号,密码,登录成功",
]
)
def test_login(test_input, expected):
'''测试登录用例'''
# 获取函数返回结果
result = login(test_input["username"], test_input["password"])
# 断言
assert result["msg"] == expected
if __name__ == '__main__':
pytest.main(["-vs","test_a_ids_allure_title.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
结合上面两种实现方式,把用例描述当成一个测试输入的参数,继续优化
代码
test_a_ids_allure_title_youhua.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!", "输入正确账号,密码,登录成功"),
({"username": "yoyo2", "password": "123456"}, "failed!", "输入错误账号,密码,登录失败"),
({"username": "yoyo3", "password": "123456"}, "success!", "输入正确账号,密码,登录成功"),
]
@allure.story("登录用例")
@allure.title("{title}")
@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(["-vs","test_a_ids_allure_title_youhua.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
使用allure.dynamic可以给用例动态添加内容
属性有
allure.dynamic.feature
allure.dynamic.link
allure.dynamic.issue
allure.dynamic.testcase
allure.dynamic.story
allure.dynamic.title
allure.dynamic.description
用法
代码
test_a_ids_allure_title_youhua_dynamic.py
"""
一个简单的pytest参数化案例演示
"""
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!", "输入正确账号,密码,登录成功","模块1","禅道链接1"),
({"username": "yoyo2", "password": "123456"}, "failed!", "输入错误账号,密码,登录失败","模块2","禅道链接2"),
({"username": "yoyo3", "password": "123456"}, "success!", "输入正确账号,密码,登录成功","模块3","禅道链接3"),
]
@allure.story("登录用例")
@pytest.mark.parametrize("test_input,expected,title,feature,link_url",
test_datas
)
def test_login(test_input, expected, title,feature,link_url):
'''测试登录用例'''
# 获取函数返回结果
result = login(test_input["username"], test_input["password"])
allure.dynamic.feature(feature)
allure.dynamic.link(url=link_url)
# allure.dynamic.issue()
# allure.dynamic.testcase()
# allure.dynamic.story()
allure.dynamic.title(test_title=title)
# allure.dynamic.description()
# 断言
assert result["msg"] == expected
if __name__ == '__main__':
pytest.main(["-vs","test_a_ids_allure_title_youhua_dynamic.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
先配置一个文件environment.properties,放在和测试用例运行脚本同目录下
environment.properties
systemVersion=win10
pythonVersion=3.6.0
allureVersion=2.13.0
baseUrl=http://192.168.1.x:8080
projectName=test
author=YOYO
email=283340479@qq.com
blog=https://www.cnblogs.com/yoyoketang/
或者配置文件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>
运行命令
配置文件不支持中文,否则会报乱码
pytest.main(["-vs","test_a_ids_allure_title_youhua_dynamic.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("copy environment.properties temps\environment.properties")
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
代码
test_a_ids_allure_title_youhua_dynamic.py
import pytest
import allure
import time
import os
def login(username, password):
'''登录'''
print("输入账号:%s" % username)
print("输入密码:%s" % password)
# 返回
return {"code": 0, "msg": "success!"}
# 测试数据
test_datas = [
({"username": "yoyo1", "password": "123456"}, "success!", "输入正确账号,密码,登录成功","模块1","禅道链接1"),
({"username": "yoyo2", "password": "123456"}, "failed!", "输入错误账号,密码,登录失败","模块2","禅道链接2"),
({"username": "yoyo3", "password": "123456"}, "success!", "输入正确账号,密码,登录成功","模块3","禅道链接3"),
]
@allure.story("登录用例")
@pytest.mark.parametrize("test_input,expected,title,feature,link_url",
test_datas
)
def test_login(test_input, expected, title,feature,link_url):
'''测试登录用例'''
# 获取函数返回结果
result = login(test_input["username"], test_input["password"])
allure.dynamic.feature(feature)
allure.dynamic.link(url=link_url)
# allure.dynamic.issue()
# allure.dynamic.testcase()
# allure.dynamic.story()
allure.dynamic.title(test_title=title)
# allure.dynamic.description()
# 断言
assert result["msg"] == expected
if __name__ == '__main__':
pytest.main(["-vs","test_a_ids_allure_title_youhua_dynamic.py",'--alluredir','./temps'])
time.sleep(2) # 生成json格式报告后等2秒
os.system("copy environment.properties temps\environment.properties") #复制环境变量配置文件
os.system("allure generate ./temps -o ./reports --clean") # 表示生成的json格式放在temps目录下,生成的报告放在reports目录下, --clean,表示生成报告前先清除原有内容
Created With
EdrawMind
posted on
2022-04-15 10:28
大话人生
阅读(
297
) 评论(
0
)
编辑
收藏
举报
刷新页面
返回顶部