pytest介绍:
pytest是一个非常成熟的全功能的python测试框架,与python自带的unittest测试框架类似,但pytest使用起来更简洁和高效,并且兼容unittest框架
pytest能够支持简单的单元测试和复杂的功能测试,结合requests实现接口测试,结合selenium、appnium实现自动化功能测试
pytest结合allure可实现测试报告自动生成
pytest支持多种第三方插件,可以跟Jenkins集成
pytest访问网址:https://docs.pytest.org/en/stable/
pytest安装(简单介绍一下):
通过python的包管理工具pip进行安装:pip install pytest;升级pytest:pip install -U pytest
pytest测试用例识别和运行:
用例名称规范:
1、python文件以test_开头,或者以_test结尾:test_*.py、*_test.py
2、测试类以Test开头,并且不能带有init方法
3、测试函数或者测试类中的用例方法以test_开头
运行pytest测试用例:
1、可以直接在terminal直接执行pytest或py.test,此时会自动去查找当前路径下符合规范的所有py文件并执行符合规范的测试用例
2、pytest -v 打印详细运行的日志信息,比如每条用例的文件路径和属于哪个类
3、pytest -s 带控制台输出结果,当代码中有print输出语句,如果想在运行结果中打印print的信息,可以加-s参数
4、pytest -k 运行含有某个关键字的一类用例,使用方法如下:
pytest -k 'classname' 运行类里所有方法,这里的匹配不是精准匹配,而是模糊匹配
pytest -k 'methodname' 运行某个方法,同理,模糊匹配
pytest -k 'name1 or name2' 运行匹配的所有用例,or为并列关系,模糊匹配
pytest -k 'classname and not methonname' 运行类里所有方法,不包含某个方法
5、pytest -x 遇到失败用例立即停止运行
6、pytest --maxfail=[num] 用例失败个数达到设定值时停止运行
7、pytest -m [标记名] 将运行有@pytest.mark.[标记名]这个标记的测试用例,在自动化过程中可以将测试用例添加标签进行分类
8、--lf,--last-failed 运行上一次执行失败的用例,上一次没有失败的用例则全部执行
9、--ff,--failed-first 先执行上一次失败的用例,后执行上一次成功的用例
10、pytest --collect-only 只收集用例,不执行用例
运行模式:
1、使用pycharm里面自带的调试方式,用例方法名前面有个绿色按钮,直接点击就即可运行
使用这种方式需要在pycharm中设置运行方式为pytest,File-Settings-Tools-Python Integrated Tools
2、使用pytest运行
pytest 文件名.py 单独执行某个py文件
pytest 文件名.py::类名 单独执行某个py文件中的类
pytest 文件名.py::类名::方法名 单独执行某个py文件下某个类的某个方法
3、使用python解释器运行
pytest参数化用例
应用场景:测试数据是传入的,测试的预期结果也是传入的,两个不同的参数一一对应
1、通过@pytest.mark.parametrize(argnames, argvalues)来进行参数化
argnames:要参数化的变量,string(用逗号分隔),list,tuple
argvalues:argnames每个对应的要参数化的值,list,list[tuple],需要和argnames一一对应
@pytest.mark.parametrize(['a', 'b'], [(1, 2), (2, 3)])
def test_param(a, b):
c = a + b
print(f"{a} + {b} eq {c}")
上图中的参数化的代码也可以修改为以下几种方式:
@pytest.mark.parametrize(('a', 'b'), [(1, 2), (2, 3)])
@pytest.mark.parametrize("a, b", [(1, 2), (2, 3)])
上面test_param代码运行结果如下:可以看到这一个用例的代码,运行结果有2条测试用例[(1-2),(2-3)],因为输入进行的参数化,并且测试用例的名称是自动生成的,格式:方法名[参数值-参数值]
可以在parametrize参数中传入ids参数,将pytest自动命名的名称替换为ids中定义的名称
@pytest.mark.parametrize("a, b", [(1, 2), (2, 3)], ids=["case1", "case2"])
def test_param(a, b):
c = a + b
print(f"{a} + {b} eq {c}")
2、参数的堆叠使用
# 参数的堆叠使用
@pytest.mark.parametrize("a", [0, 1])
@pytest.mark.parametrize("b", [2, 3])
def test_param2(a, b):
c = a + b
print(f"{a} + {b} eq {c}")
运行的输出结果:根据参数堆叠,可以生成不同组合的测试数据
3、通过yml数据文件来进行用例参数化(数据驱动,也可以使用json、excel等数据文件)
可以将1章节的参数化的数据写入一个yml文件中,通过读取yml中已经预置好的数据进行参数化
yml的基础教程参考:https://www.runoob.com/w3cnote/yaml-intro.html
步骤1:首先新建一个data.yml文件,并在文件中写入如下数据:
步骤2:在参数化中采用读取yml文件内容的方式将数据传入:
# 通过yml文件读取测试数据,需要在文件开始导入yaml模块
@pytest.mark.parametrize("a, b", yaml.safe_load(open("./data.yml"))['datas'],
ids=yaml.safe_load(open("./data.yml"))['ids'])
def test_param3(a, b):
c = a + b
print(f"{a} + {b} eq {c}")
步骤3:运行结果:
以上内容可以进一步的优化或者封装:
1、将yaml.safe_load(open("./data.yml"))['datas']使用函数封装后直接调用
# 定义获取yml文件数据函数
def get_datas():
with open("./data.yml") as f:
yml_data = yaml.safe_load(f)
print(yml_data)
datas = yml_data['datas']
ids = yml_data['ids']
return [datas, ids]
@pytest.mark.parametrize("a, b", get_datas()[0], ids=get_datas()[1])
def test_param4(a, b):
c = a + b
print(f"{a} + {b} eq {c}")
pytest -m参数详解
pytest -m [标记名] 将运行有@pytest.mark.[标记名]这个标记的测试用例,在自动化过程中可以将测试用例添加标签进行分类,比如将测试用例的等级进行分类,基本功能用例,冒烟用例等
比如,如下代码段,两个测试用例分别标记了label1和label2
class TestDemo:
@pytest.mark.label1
def test_haha(self):
assert 1 == 1
@pytest.mark.label2
def test_hehe(self):
assert 2 == 3
1、可以使用pytest -m "label1" test_mark.py只运行标记了label1的测试用例,运行结果为1条用例:test_haha
2、可以使用pytest -m "label1 or lable2" test_mark.py运行标记了label1或者label2的测试用例,运行结果为2条用例
3、将test_hehe的用例改为如下标记,一个用例可以标记多个标签:
@pytest.mark.label1
@pytest.mark.label2
def test_hehe(self):
assert 2 == 3
那么可以使用pytest -m "label1 and lable2" test_mark.py运行同时标记了label1和label2的测试用例,运行结果为1条用例:test_hehe
4、使用自己定义的标记名执行用例时,运行结果会出现warning,可以使用pytest.ini文件配置自定义标签后消除warning信息
在同级目录下创建一个pytest.ini文件,并进行如下设置:
[pytest]
markers = label1
label2
pytest的框架结构
pytest提供了setup和teardown的方法来实现用例的前置和后置条件,比如某一类用例需要在执行步骤之前进行登录,执行完成后退出登录,登录和退出登录的操作可以同一使用一个方法来进行覆盖
根据用例的运行级别可以分为以下几类:
模块级:setup_module,teardown_module,在模块的开始调用setup_module方法,结束调用teardown_module方法,在python中,一个py文件就是一个模块
函数级:setup_function,tearndown_function,在函数的开始和结束分别调用那两个方法(不在类中的函数,setup开始,teardown结束)
类级:setup_class,tearndown_class,在类的开始和结束分别调用两个方法
方法级:setup_method,teardown_method,在方法的开始和结束分别调用(专门用于类里面的方法)
方法级:setup,teardown,如果在类里面定义,使用范围和setup_method、teardown_method一样;如果在类外面定义,使用范围和setup_function、teardown_function一样
调用的顺序:
setup_module>setup_class>setup_method>setup>teardown>teardown_method>tearndown_class>teardown_module
自定义pytest的运行规则:
1、自定义标记名,跟上面的pytest -m运行参数配合使用的,自定义了之后可以消除warning
2、自定义运行时增加的默认参数
addopts = -vs
3、自定义可以被pytest识别的运行文件、运行类、运行用例等
[pytest]
markers = label1
label2
addopts = -vs
python_files = check* test*
python_classes = Test*
python_funtions = check_* test_*