选对一款好用的框架,实现自动化的时候会事半功倍,当然每一款框架都有其优势和不足,适合自己的才是最好的,在前文中已经写过Unittest框架使用的文章,感觉整体风格统一、结构完整,对于初学者更容易理解;本文所讲的pytest框架也是python的一种单元测试框架,使用起来更简洁,效率更高,感觉更有python的风格。
一、pytest简介
pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,非常容易上手,入门简单,文档丰富,文档中有很多实例可以参考:
【视频教程:https://www.bilibili.com/video/BV1hT411U7sC/?spm_id_from=333.999.0.0】
支持单元测试
支持功能测试
支持参数化
支持跳过用例
支持标记失败用例
支持重复执行失败的用例
兼容nose, unittest编写的测试用例
具有很多第三方插件,方便扩展
支持持续集成工具集成
等等
二、pytest安装
1、pip安装
在python中一般默认安装了pip工具,如果没有,可以通过easy_install命令来安装。
easy_install pip
为了保证后面模块的正常安装,如果不是最新的版本可以使用如下命令把pip升级一下:
pip install --upgrade pip
然后使用pip命令去安装第三方的模块就非常方便了。
安裝:pip install PackageName
指定版本安裝:pip install PackageName==xx.xx
更新:pip install -U PackageName
移除:pip uninstall PackageName
2、使用requirements.txt安装
提前准备一个requirements.txt文件,里面填写需要的依赖包及其精确版本号,然后统一进行一次性安装。
1)创建一个requirements.txt文件,并填入如下数据
pytest==7.1.2
selenium==4.1.3
PyMySQL==1.0.2
2)运行该txt文件并完成三个模块的安装
pip install -r e:\requirements.txt
三、使用pytest设计单元测试用例
使用pytest设计单元测试用例,有三个基本的要求。
文件名必须以test_开头
测试类必须以Test开头,并且不能有 init 方法
测试方法必须以test_开头
1、创建单元测试用例文件
在vscode、pycharm等IDE工具中创建一个以test_开头的py文件。
2、创建单元测试用例
'''
@功能 : pytest单元测试用例
@作者 : 北凡老师
@csdn : 测试架构师北凡
'''
# 导入pytest模块
import pytest
# 单独的测试用例方法创建
def test_case1():
print("aaaa")
# 以类的形式创建单元测试用例,类名Test_开头
class Test_demo2():
# 测试用例方法以test_开头
def test_case02(self):
print("bbbbb")
def test_case03(self):
print("bbbbb")
assert 12==12
if __name__ == "__main__":
pytest.main()
3、添加断言
assert关键字后面可以接一个表达式,只要表达式的最终结果为True,那么断言通过,用例执行成功,否则用例执行失败。
assert xx:判断xx为真
assert not xx:判断xx不为真
assert a in b:判断b包含a
assert a == b:判断a等于b
assert a !=b:判断a不等于b
如果是预期要抛出异常的情况,pytest也有专门的断言方式pytest.raises(),比如预期除数为0会抛出异常。
pytest.raises 作为上下文管理器,当其管理的执行代码抛出我们指定类型的异常时,可以异常捕获为一个异常对象,不会报错,继续执行后续代码
pytest.raises只会捕获指定的异常类型,遇到其他类型异常或者没有报错,都会直接报错造成用例执行失败。
def test_division(self):
with pytest.raises(ZeroDivisionError) as z:
a = 1/0
assert z.type == ZeroDivisionError
四、单元测试用例执行
最基本的pytest单元测试用例的执行方式是pytest.main(),main()函数是单元测试用例的执行入口,它的参数是可以放在一个列表中的。
if __name__ == "__main__":
# 默认加载配置文件中的参数
pytest.main(["-s"])
1、main()方法的常见参数
-s: 显示程序中的print/logging等内容,输出到控制台
-v: 丰富信息模式, 输出更详细的用例执行信息
-q: 安静模式, 不输出环境信息
-x: 出现一条测试用例失败就退出测试
-k:可以使用and、not、or等逻辑运算符,匹配范围(文件名、类名、函数名)
使用格式为:pytest.main(["-s","-v","-q","-x","-k xxx"]),其含义等同于下面的语法。
# 执行具体的某一测试文件
pytest 脚本名称.py
# 执行所有的测试文件
pytest -sv
# 执行指定包或者文件夹下面的所有文件
pytest -sv 包名或文件夹名
# 执行测试用例名称包含phone的所有用例
pytest -k phone test_demo.py
# 执行测试用例名称 不包含phone的所有用例
pytest -s -k "not phone" test_demo.py
# 执行测试用例名称包含 phone 或 login 的所有用例
pytest -s -k "phone or login" test_demo.py
# 运行.py模块里面,测试类里面的某个方法
pytest test_demo.py::TestClass::test_one
2、常见的案例
1)运行所有用例,以test_开始的用例
import pytest
def test_one():
pass
if __name__ == '__main__':
pytest.main()
2)运行指定目录的用例
import pytest
def test_one():
pass
if __name__ == '__main__':
pytest.main(["./testcase/product"])
3)运行指定py的用例
import pytest
def test_one():
pass
if __name__ == '__main__':
pytest.main(["./testcase/product/test_add_product.py"])
4)运行指定py的测试类用例
python
import pytest
def test_one():
pass
if __name__ == '__main__':
pytest.main(["./testcase/product/test_add_product.py::TestProduct"])
5)运行指定py的测试类中的用例
import pytest
def test_one():
pass
if __name__ == '__main__':
pytest.main(["./testcase/product/test_add_product.py::TestProduct::test_add_01"])
3、用例执行状态
用例执行完成后,每条用例都有自己的状态,常见的状态有:
passed:测试通过,一般使用 . 来表示
failed:断言失败,一般使用 F 来表示
error:代码错误,一般使用 E 来表示
4、测试用例执行的其他用法
pytest xx.py::test_min:::字符后提供器名称来运行特定功能(参数化的类名、函数名、参数,需要一级一级的获取)
pytest -m smoke:标记可用于测试进行分组,然后使用pytest -m运行一组标记@pytest.mark.smoke的测试
pytest --pyargs pkg.testing:从包里面运行,将导入pkg.testing并使用其文件系统位置来查找和运行测试
- -maxfail=num:用例错误个数达到指定数量时,停止测试
pytest -h:帮助
- -junit-xml=path:输出xml文件格式,在与jenkins做集成时使用
- -pastebin=all:all , failed, passed 筛选某一部分
五、pytest的其他用法
1、pytest常用的Fixture方法
setup():每个测试方法执行之前会执行
teardown():每个测试方法执行之后会执行
setup_class():在每个类执行之前会执行
teardown_class():在每个类执行后会执行
class TestFixture():
@staticmethod
def setup_class():
print("整个测试类开始前只执行一次setup_class")
@staticmethod
def teardown_class():
print("整个测试类结束后只执行一次teardown_class")
def setup():
print("类里面的每个用例执行前都会执行setup")
def teardown():
print("类里面的每个用例执行后都会执行teardown")
def test_login_success(self):
print("登录成功")
assert True
def test_login_error(self):
print("登录失败")
assert False
if __name__=="__main__":
pytest.main(["-s","-k Fixture"])
执行结果如下:
2、忽略测试用例执行
@pytest.mark.skip(reason=""):无条件跳过执行测试用例,reason表示跳过的原因,会在执行结果中打印
@pytest.mark.skipif(condition, reason=""):希望有条件地跳过某些测试用例, condition为True时才会跳过用例
import random
from tkinter.tix import MAIN
from black import main
import pytest
class TestSkip():
def test_one(self):
print("第一个测试用例!")
@pytest.mark.skip(reason="无条件跳过")
def test_two(self):
print("第二个测试用例!")
@pytest.mark.skipif(1 == random.randint(0, 1), reason="当随机数等于1时跳过")
def test_three(self):
print("第三个测试用例!")
def test_four(self):
print("第四个测试用例!")
if __name__=="__main__":
pytest.main(["-s","-k Skip"])
执行结果为:
3、参数化的用法
编写测试用例时,多个测试用例操作步骤一样,只有测试数据及期望结果可能不一样时,此时使用参数化的方式,可以大大减少冗余代码。
语法如下:
@pytest.mark.parametrize(参数1,参数2,[[参数1值1,参数2值1],[参数1值2,参数2值2]..])deftest_xx(self,参数1,参数2)
data:用于参数化的测试用例数据,值为列表,数据可以是列表或元组
import pytest
class TestParameters():
data = [
{"username": "张三", "password": "123", "expect_code": 200},
{"username": "李四", "password": "321", "expect_code": 400},
{"username": "王五", "password": "123456", "expect_code": 400}
]
@pytest.mark.parametrize("account", data)
def test_login(self, account):
#print(account)
assert 200 == account["expect_code"]
if __name__=="__main__":
pytest.main(["-s","-k Para"])
执行结果为:
六、测试报告输出
执行单元测试或者自动化测试,都希望能输出一个可视化的html格式报告,下面我们就介绍与pytest兼容性比较好、而且非常方便使用的模块pytest-html和allure,非常方便生成html格式的报告。
1、pytest-html模块的使用
pytest-html是pytest的一个插件,可以生成html格式报告。
1)安装pytest-html
安装指令:pip install pytest-html
默认安装的pytest-html的版本是3.1.1,据说有兼容性问题。
我们可以指定版本安装:pip install pytest-html==2.1.1
2)使用pytest-html运行测试单元测试用例并生成报告
# test_demo5.py为符合pytest单元测试用例的文件
py.test test_demo5.py --html=./aaaaa.html
3)查看生成的报告
在vscode中执行后的控制台输出为:
找到当前工程目录下的aaaa.html文件,并使用chrome浏览器打开:
2、allure的使用
Allure是一款轻量级并且非常灵活的开源测试报告框架,它支持pytest等很多测试框架,并且简单易用,易于与其他工具集成,是帮助我们快速生成炫酷的自动化测试报告的不二之选。
1)下载、安装
可以从Github上下载:
地址:https://github.com/allure-framework/allure2/releases
下载后其中allure-2.18.1.zip,直接解压到本地某盘符下即可。
将上图的bin目录,设置到系统环境变量path中。
在cmd下运行:allue --version,出现下图,即为安装成功。、
2)安装Allure Pytest Plugin
allure-pytest是Pytest的一个插件,通过它我们可以生成Allure所需要的用于生成测试报告的数据。
安装allure-pytest插件,在cmd下操作输入命令:
pip install -U allure-pytest
3) pytest集合allure生成测试报告
在vscode/pycharm中,使用pytest规则设计单元测试用例。
执行方式1:在执行文件中
if __name__ == "__main__":
pytest.main(["--alluredir","./test_result"])
os.system("allure generate ./test_result -o ./test_report --clean")
执行方式2:测试用例文件所在的目录下命令行分别运行
pytest --alluredir ./test_resul
allure generate ./test_result -o ./test_report --clean
–alluredir参数的作用是指出生成的报告文件夹, result下放着生成报告的基础数据文件
通过第二条命令将./result/目录下的测试数据生成测试报告到./test_report目录下
4) 查看该index.html文件
在pycharm中,是可以直接打开该文件的,可以正常显示报告内容。
但是在vscode和资源管理器中,打开该文件后是显示Loading和404页面的。
这主要是因为该index.html文件需要allure命令渲染之后打开才能展示效果。
我们可以使用 allure open来渲染打开测试报告文件。
在test_report和test_result同级目录下,执行cmd命令或者vscode的控制台命令行:
allure open test_report/
会自动打开Chrome浏览器,并渲染打开index.html文件,展示测试结果报告。
【软件测试到测试开发全测试生涯学习路线】:【以下路线图太详细了只能展开部分,具体的可以在文章末尾扫描小卡片备注000领取哦】
1:自动化测试进阶系列:
2:全栈性能测试,监控以及调优
3:全栈测试开发平台实战
4:全栈安全测试渗透测试
5:devops持续集成部署
6:全栈接口测试工具进阶
7:跨平台自动化测试工具
8:大厂简历,真题,录音
9:全栈系列课企业项目实战
学完这整套教程,拿下大厂30k到50k不是问题