pytest是python语言中一款强大的单元测试框架,用来管理和组织测试用例,可应用在单元测试、自动化测试工作中。 官网:(https://docs.pytest.org/en/7.2.x/)
文章主要以unittest为参考分析pytest
pytest主要作用是编写测试用例、收集用例、执行用例、生成测试结果文件(html、xml)
unittest: 模板化 不需要安装
1.基于python的单元测试框架,它可以和selenium,requests,appium结合实现自动化测试。2.实现用例跳过skip和reruns失败用例重跑。3.它可以结合allure-pytest插件生成allure报告。4.很方便和jenkins实现持续集成。5.有很多强大的插件:pytest-html 生成html测试报告。pytest-xdist 多线程执行测试用例。pytest-ordering 改变测试用例的执行顺序。pytest-rerunfailures 失败用例重跑allure-pytest 生成allure报告。
pip install pytest
一 编写用例
unittest: 继承unittest.TestCase类,用例名要以test_开头。
pytest: 函数的形式、类的形式。用例名要以test_开头或者_test结尾。测试类要以Test开头。
二 收集和执行用例:
unittest: 用例收集(TestSuite/TestLoader)到TestSuite, TestRunner去执行用例。
pytest: 自动收集用例,再去执行。
2.1 pycharm设置 以pytest方式执行用例
pycharm默认是以unittest方式执行测试用例
修改方式:File--Settings--Tools--Python Intergrated Tools 将Testing 中 Default test runner改成pytest
2.2 pytest自动收集用例的规则
1)确定搜索目录:
从哪个目录开始搜索用例?
-- pytest命令在哪个目录下执行,就以哪个目录为rootdir
-- 新建main.py,在文件当中使用pytest.main() - 与在命令行当中执行pytest是一样的。
2)过滤测试文件:
--测试文件名:test*.py 或者 *test.py
3)过滤测试用例:文件当中,如何过滤测试用例?
-- 测试用例名:test_开头 测试类名:Test开头。
4) pytest收集到的用例执行顺序
先找到测试文件,再找测试文件当中的用例。
测试文件顺序:ASCII码
测试文件内部顺序:代码先后顺序
5) 通过插件pytest-ordering改变用例执行顺序
@pytest.mark.run(order=1)
注意:有order装饰器的优先,相同的order标记序号从上到下,然后是没有装饰器的,从上到下.负数不起作用.
2.3 pytest运行方式
1.主函数方式。
import pytest
#1
if __name__ == '__main__':
pytest.main()
常见参数:-v:输出更加详细的信息。比如文件和用例名称等。-s:输出调试信息。打印信息等。可以合并成:-vs--reruns 数字:失败重跑-x:出现1个失败就停止测试。--maxfail=2 出现N个失败就终止测试。--html=report.html 生成html的测试报告-n:多线程。-k:运行测试用例名称中包含指定字符串的用例。
#2.指定模块运行。
if __name__ == '__main__':
pytest.main(['‐vs','testcases/test_api2.py'])
#3.指定文件夹
if __name__ == '__main__':
pytest.main(['‐vs','testcases/'])
#4.通过node id的方式运行测试用例。
if __name__ == '__main__':
pytest.main(['‐vs','testcases/test_api.py::TestApi::test_product_manage'])
2.命令行方式。
3.通过pytest.ini的配置文件运行。
(不管是命令行还是主函数都会读取这个配置文件)
[pytest]用于标记这个文件是pytest的配置文件addopts = -vs命令行参数,多个参数之间用空格分隔。addoptionstestpaths = testcases/ 配置搜索测试用例的范围python_files = test_*.py 改变默认的文件搜索规则python_classes = Test* 改变默认的类搜索规则python_functions = test_* 改变默认的测试用例的搜索规则。#用例分组markers =smoke:冒烟用例productmanage:商品管理模块特别提示:此文件中最好不要出现中文,如果有中文的情况下,比如使用notpad++改成GBK的编码
2.4 跳过用例
@pytest.mark.skip
1)直接跳过
#无条件跳过
@pytest.mark.skip(reason="不需要")
@pytest.mark.smoke
def test_mk(self):
print("mk")
2)有条件跳过
@pytest.mark.skipif(age>2,reason="以后的版本都不执行")
@pytest.mark.smoke
def test_aaa(self):print("aaa")
三 生成测试结果文件:
unittest: text,html(HtmlTestRunner,beautifulReport)
pytest主要介绍四种
3.1. 生成JunitXML 格式的测试报告:
命令:--junitxml=path
3.2. 生成result log格式的测试报告:
命令:--resultlog=report\log.txt
3.3. 生成Html格式的测试报告:
命令:--html=report\test_one_func.html(相对于rootdir路径 )
第一步:安装pytest html插件 pip install pytest-html
第二步:在pytest的命令行参数中:--html=....
3.4生成allure的测试文件(unittest不支持,主要介绍)
3.4.1allure介绍及安装
allure依据测试结果文件,呈现更好看的更多维度的测试报告。
注意:它不执行用例也不生成测试结果文件。所以,要使用allure的时候,一定要先生成测试结果文件。 要结合其它的测试框架一起使用的
1) 安装allure命令行工具
下载地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/
下载以后解压,然后配置环境变量
我的解压位置是 D:\pycharm\allure-2.20.1\ 配置环境变量:allure的bin目录D:\pycharm\allure-2.20.1\ bin
在cmd当中,执行allure命令查看是否安装成功
2)安装allure-pytest插件
#安装插件:
pip install allure-pytest
3)配置生成allure可以识别的测试文件的路径
pytest在执行用例之后,要生成allure可以识别的测试结果文件
在pytest.main()的参数当中添加:--alluredir=xx/xxx (相对于rootdir路径)
4)allure去解析2中的测试结果文件
使用allure去解析测试结果文件,再呈现最终的测试报告
在cmd当中首先跳转到rootdir下在cmd当中执行命令:allure serve 中的测试结果文件路径
或者在main函数直接添加allure serve 测试文件
写的一个demo
test_01
# @File : test_01.py
import pytest
def test_01():
assert 1==1
print('hello')
def test_02():
print("demo02")
assert 1+1 >2
def test_03():
print("demo03")
main
# @File : main.py
import os
import pytest
if __name__ == '__main__':
pytest.main(["-s", "-v",
"--alluredir=allure_files"])
os.system("allure serve allure_files")
执行结果如下
四 数据驱动:
unittest: ddt模块
pytest 使用@pytest.mark.parametrize装饰器来实现数据驱动测试
4.1单个数据
import pytest
data = ["get", "post"]
@pytest.mark.parametrize("name",data)
def test_demo(name):
print("测试数据为{}".format(name))
4.2组数据
列表嵌套字典
import pytest
datas=[
{"method":"get","code":"200"},
{"method":"post","code":"201"},
{"method":"put","code":"301"},
{"method":"delete","code":"204"}
]
@pytest.mark.parametrize("case",datas)
def test_read_cases01(case):
print(case["method"],case["code"])
print("=======================")
02 列表嵌套列表
import pytest
data_1 = [
["admin1", "123456"],
["admin2", "12345678"],
]
@pytest.mark.parametrize("username,password", data_1)
def test_login(username,password):
print("账号:{},密码:{}".format(username, password))
03 列表嵌套元组
import pytest
data_1 = [
("admin1", "123456"),
("admin2", "12345678"),
]
@pytest.mark.parametrize("username,password", data_1)
def test_login(username,password):
print("账号:{},密码:{}".format(username, password))