1、pytest规则
pytest编写用例,需遵循一下规则:
1.测试文件名必须以test_开头(如:test_adv.py)
2.测试方法必须以test_开头,t必须小写
3.测试类必须以Test_开头,且T需要大写,如T为小写则该类下的所有测试方法均不会被执行,测试类,不能有__init__(self)初始化的方法-----测试用例的类不需要初始化
4.pytest测试用例函数可以脱离类,可以直接使用函数的形式(测试用例的py文件直接写为函数)------unittest中无此用法
5.需执行的测试用例方法不能使用@classmethod装饰器,否则无法加载到该用例!!!
6.运行脚本时注意关闭抓包工具及代理,否则可能导致运行过程中报错SSLerror ,握手错误。
2、conftest.py文件
conftest.py文件是pytest框架中非常重要的东西,它可以实现fixture对象自对应并自动应用跨模块、跨文件的应用操作,从而使fixture对象的定义更加灵活。相当于将一些用例的前置操作整理到conftest文件中,执行用例时如有需要则直接调用即可。
conftest.py的作用域:在一个测试工程中可以存在多个conftest.py文件,如果存在多个,则一般会对所有的conftest.py文件中的对象进行提取,提取出所有模块共用的对象,然后在根工程目录下放一个conftest.py,这样该文件就起到了全局作用。
如果每个子目录下都存放有conftest.py文件,则该文件中的对象作用范围只能够在当前层级及该层级的子目录有效。
@pytest.fixture()里面没有传入参数时,那么默认scope = ‘function’,也就是此时的级别是function,scope参数类型有以下几个类型:
1.scope = ‘session:所有测试.py文件执行前都会执行一次conftest文件中的fixture
2.scope = ‘module’:每一个测试.py文件执行前都会执行一次conftest文件中的fixture
3.scope = ‘class:每一个测试文件中的测试类执行前都会执行一次conftest文件中的fixture
4.scope = ‘function':所有文件的测试用例执行前都会执行一次conftest文件中的fixture
@pytest.fixture(scope='session')
ps:
1.function与class的区别:两者如果作用于测试函数,则两者是等价的,都表示创建全新的固件对象;但如果针对的是类中测试方法,function表示每个测试方法创建全新的对象,而class表示测试类中的所有用例共用一个固件对象。
2.session与module的区别:module表示针对模块而言,每个模块中使用的是同一个固件对象,不同的模块创建的固件对象不同的;而session表示整个会话,不同的模块使用的对象也是相同的。
conftest的配置需要注意以下三点:
1.conftest.py配置脚本名称是固定的,不能改名称;
2.conftest.py与运行的用例要在同一pakage下,并且有init.py文件;
3.不需要import导入conftest.py,pytest用例会自动查找。
fixture的相互调用:
import pytest
@pytest.fixture()
def get_a():
print('获取被加数')
a = 1
print(a)
return a
@pytest.fixture()
def get_b(get_a):
'''被加数调用get_a fixture'''
a = get_a
b = 2
return (a,b)
def test_1(get_b):
'''用例传fixture'''
print(get_b)
assert get_b[0] + get_b[1] == 3
上述代码中get_b固件对象需要引用get_a固件对象,get_a固件对象返回的是一个被加数的值,而此时get_b的对象就不是单纯第返回加数的值,而是引用get_a固件对象一起返回,所以在实际test_1方法中不需要调用get_a对象,只需要直接调用get_b对象即可。
3、pytest.fixture装饰携带参数
fixture提供了这么一个机制,fixture装饰的函数拥有一个内置的对象request,同时fixture中还有一个params参数是用来传递参数化数据,如果使用params方式实现参数化,那么固件对象中传入的参数名固定是request,且必须返回参数对象,及request.param,如下:
ps:@pytest.mark.parametrize中有个ids字段,这个字段可以设置测试用例的标题,上述图片中的test_data中的case字段便为设置的用例名称。
4、pytest的parametrize参数化
@pytest.mark.parametrize(argnames,argvalues)
@pytest.mark.parametrize:pytest中的装饰器,可以实现测试用例的参数化。
argnames:单个参数名
argvalues:参数值,类型为列表,列表当中可以包含字符串、元组及字典对象。
indirect参数:可以不填,默认False,
False: 就是parametrize里面argnames 参数当作一个普通的变量,不会去找变量对应函数的名的方法;
True: 就是parametrize里面argnames 参数当作函数执行,它会去找对应的函数去执行,如下:
上诉代码中indirect传入的是True,所以运行test_is_idd方法的时候程序会找parametrize中的argnames同名的函数运行。
1.单个参数的参数化应用:单个参数的参数化主要是将要读出的所有测试用放到列表中,然后依次取到列表中的每一个用例,并供函数使用,从而完成每一个用例的执行,具体用法如下:
2.多个参数的参数化应用:在接口自动化测试中,随着测试的不断深入,接口测试用例中所包含的请求地址、请求头、请求的数据类型、请求的主体内容等均可以使用参数化,同时测试环境及相关配置也可以使用参数化。当测试用例及其他测试环境使用多个参数的参数化时,可以让程序的运行、维护变得更加高效和灵活。在语法使用方面,多个参数的参数化与单个参数的参数化并无太多区别,只是参数个数多了一些而已。
在pytest测试框架中,多个参数的参数化语法如下
@pytest.mark.parametrize(argnames001,argvalues)
@pytest.mark.parametrize(argnames002,argvalues)
或者
@pytest.mark.parametrize(argnames001,argnames002,argnames)
ps:
@pytest.mark.parametrize:pytest中的装饰器,可以实现测试用例的参数化
argnames001:第一个参数名
argnames002:第二个参数名
argvalues:参数值,类型为列表。列表当中可以包含字符串、元组及字典对象
1)被参数化的内容是字符串
实例代码如下:
import pytest
@pytest.mark.parametrize("username",["aaa","bbb","ccc"])
@pytest.mark.parametrize("password",["111","222","333"])
def test_register(username,password):
print(f"登录成功:用户名为{username},密码为{password}")
if __name__ == '__main__':
pytest.main()
说明:运行结果列表中包含的对象均为字符创类型,参数username、password不是同步取值,而是交替取值!!!
2)被参数的内容是元组
import pytest
@pytest.mark.parametrize("username,password",[("aaa","111"),("bbb","222")])
def test_register(username,password):
print(f"登录成功:用户名为{username},密码为{password}")
if __name__ == '__main__':
pytest.main()
说明:列表中包含的对象均为元组类型,参数username、password并不是交替取值而是同步取值!
5、pytest的配置文件pytest.ini
pytest.ini用于读取整个项目的配置信息,pytest将按此配置文件中指定的方式去运行,并可以改变pytest的默认行为。pytest.ini配置文件存放在项目的根目录下,文件名称固定不可修改,需要手动新建。
配置项较多,常用配置项如下:
文件头[pytest]:配置文件的头信息,不能少!!
1.更改默认命令行参数:addopts = -s -v --html=../report/report.html
-v参数显示命令执行过程,-s参数显示打印的信息,--html参数主要用于设置测试报告的路径和测试报告文件名,其中..代表的是所在目录的上一级目录。
2.testpaths = testcase
定义测试用例文件夹名称,只有名称为testcase的文件夹下面的测试文件才会被pytest执行。
3.python_files = test_*.py
定义测试用例所在的文件,只有文件名称是以test开头的文件才会被pytest执行。
4.python_classes = Test*
定义测试用例文件中类的名称,只有以Test开始的类才会被pytest执行。
5.python_functions = test*
定义函数或方法的名称,只有以test开始的函数或方法才会被pytest执行。
ps:在正式的pytest.ini文配置文件中不能出现中文字符及注释内容,否则pytest在执行过程中会产生异常而导致测试执行失败;
6、pytest用例筛选-pytest.mark
1.创建标签(推荐使用第一种)
方法1.设置pytest.ini文件,在文件中按照以下格式添加标签名:
方法2.创建conftest.py文件,存放在命令行当前目录,在文件中按照以下格式添加标签名:
2. 执行用例
在测试用例/测试类前加上标记 @pytest.mark.标记名
1.命令行执行:pytest -m demo
2.pycharm执行:
PS:通过打标记的方式筛选用例时,pytest框架会取遍历每个测试用例类,所以虽然最后没找到对应标记的用例去执行,但是如果测试用例类调用了其他接口,每遍历1次就会调1次对应接口,虽然该类下的用例并未执行,如下图,右侧的用例不会执行但是遍历到该测试用例文件时,该类里调用的获取验证码、登录接口仍会调,所以这边建议测试用例类下尽量不要调用其他接口,如果用例需要依赖一些前置调用可将对应的方法封装为fixture函数,在用例执行前去自动调用。