fixture很是有用,它们提供了固定的基准,所以测试能够被可靠地执行并产生一致的,可重复的结果。使用fixture能够设置服务,状态或其余操做环境。测试函数经过参数调用fixture方法。json
fixture比setup、teardown等方法更好api
1.fixture具备明确的名称,能够经过在测试功能,模块,类或整个项目中声明其使用来激活。cookie
2.fixture以模块的方式实现,由于每一个fixture方法都会触发一个fixture功能,该功能自己可使用其余fixture。session
3.fixture管理的范围从简单的单元测试到复杂的功能测试,能够根据配置和组件选项对fixture和测试进行参数化,或者在功能,类,模块或整个测试会话范围内重复使用fixture。app
下面应用理解框架
使用测试程序函数
/testapi/add/单元测试
/testapi/minus/测试
/testapi/chengfa/url
使用pytest测试类
import pytest import requests import json import os import logging class TestMath(object): @pytest.mark.parametrize('a,b',[(0.1,0.2),(1,2)]) def testadd(self,a,b): '''测试加法程序''' headers = { 'Content-Type': "application/json", } reqdata = {'a':a,'b':b} resp = requests.request(method='POST', url='http://127.0.0.1:8000/testapi/add/', verify=False, headers=headers, json=reqdata) resp = json.loads(resp.text) assert resp['status']==1 assert resp['data'] == a + b return resp['data'] @pytest.mark.parametrize('a,b',[(0.1,0.2),(1,2)]) def testminus(self,a,b): '''测试加法程序''' headers = { 'Content-Type': "application/json", } reqdata = {'a':a,'b':b} print(reqdata) resp = requests.request(method='POST', url='http://127.0.0.1:8000/testapi/minus/', verify=False, headers=headers, json=reqdata) resp = json.loads(resp.text) print(resp) assert resp['status']==1 assert resp['data'] == a - b return resp['data'] @pytest.mark.parametrize('a,b',[(0.1,0.2),(1,2)]) def testchengfa(self,a,b): '''测试加法程序''' headers = { 'Content-Type': "application/json", } reqdata = {'a':a,'b':b} print(reqdata) resp = requests.request(method='POST', url='http://127.0.0.1:8000/testapi/chengfa/', verify=False, headers=headers, json=reqdata) # warnings.warn('这是个警告', category=None, stacklevel=1, source=None) resp = json.loads(resp.text) print(resp) assert resp['status']==1 assert resp['data'] == a * b return resp['data'] if __name__ == '__main__': pytest.main(['D:/PycharmProjects/untitled/test_math.py'])
好比说要使用cookie,通常来讲是须要初始化
@pytest.fixture
def mycookie(self):
self.s = requests.session()
c = requests.cookies.RequestsCookieJar()
c.set('testcookies', 'XXXXXXX')
self.s.cookies.update(c)
return self.s
测试方法中加入print(mycookie.cookies['testcookies'])
运行看见能打印XXXXXXX
conftest.py
若是在实施测试期间您意识到要使用fixture到多个测试文件中的功能,则能够将其移至一个conftest.py文件中。测试中无需在全部文件导入这个fixture,它会被pytest自动发现。夹具功能的发现始于测试类,而后是测试模块,而后是 conftest.py文件,最后是内置插件和第三方插件。
夹具是在测试首次请求时建立的,并根据如下scope的值决定fixture什么时候被销毁:
function:默认范围,fixture在单个测试对象运行结束时被销毁。
class:在class中的最后一个测试对象运行完被销毁。
module:在文件中的最后一个测试对象运行完被销毁。
package:在包中的最后一个测试对象运行完被销毁。
session:在整个测试阶段结束时被销毁。
import pytest # fixtures documentation order example order = [] @pytest.fixture(scope="session") def s1(): order.append("s1") @pytest.fixture(scope="module") def m1(): order.append("m1") @pytest.fixture def f1(f3): order.append("f1") @pytest.fixture def f3(): order.append("f3") @pytest.fixture(autouse=True) def a1(): order.append("a1") @pytest.fixture def f2(): order.append("f2") def test_order(f1, m1, f2, s1): assert order == ["s1", "m1", "a1", "f3", "f1", "f2"]
test_order调用的fixture将按如下顺序实例化:
s1:session是外面一层。
m1:module是第二外面一层。
a1:是一个autouse-fixture:它会在同一范围内的其它fixture以前被实例化。
f3:被同级别调用的比调用者先实例化
f1:同级别按排名顺序调用
f2:同上
经过使用yield
语句代替return
,yield语句以后的全部代码都将用做teardown的功能。
例如登陆和退出
@pytest.fixture(scope='module',autouse=True) def logginandout(self): print('登陆成功') yield print('退出成功')
test_math.py::TestMath::testadd[0.1-0.2] 登陆成功
...
FAILED退出成功
改为scope='function'的话
test_math.py::TestMath::testadd[0.1-0.2] 登陆成功 XXXXXXX PASSED退出成功 test_math.py::TestMath::testadd[1-2] 登陆成功 XXXXXXX PASSED退出成功 test_math.py::TestMath::testminus[0.1-0.2] 登陆成功 {'a': 0.1, 'b': 0.2} {'status': 1, 'message': '请求成功', 'data': -0.1} PASSED退出成功 test_math.py::TestMath::testminus[1-2] 登陆成功 {'a': 1, 'b': 2} {'status': 1, 'message': '请求成功', 'data': -1} PASSED退出成功 test_math.py::TestMath::testchengfa[0.1-0.2] 登陆成功 {'a': 0.1, 'b': 0.2} {'status': 1, 'message': '请求成功', 'data': 0.30000000000000004} FAILED退出成功 test_math.py::TestMath::testchengfa[1-2] 登陆成功 {'a': 1, 'b': 2} {'status': 1, 'message': '请求成功', 'data': 3} FAILED退出成功
能够对fixture功能进行参数设置,在这种状况下,它们将被屡次调用,每次执行一组相关测试,即依赖于该fixture的测试。夹具参数化有助于为组件编写详尽的功能测试,这些组件自己能够经过多种方式进行配置。
@pytest.fixture(params= [(0.1,0.2),(1,2)],ids=['小数','整数']) def gettestdata(self,request): return request.param
加入以上fixture并修改测试方法
# @pytest.mark.parametrize('a,b',[(0.1,0.2),(1,2)]) def testadd(self,gettestdata,mycookie): '''测试加法程序''' print(mycookie.cookies['testcookies']) a,b = gettestdata[0],gettestdata[1] headers = { 'Content-Type': "application/json", } reqdata = {'a':a,'b':b} resp = mycookie.request(method='POST', url='http://127.0.0.1:8000/testapi/add/', verify=False, headers=headers, json=reqdata) resp = json.loads(resp.text) assert resp['status']==1 assert resp['data'] == a + b return resp['data']
...
pytest.main(['-v',''])运行成功
test_math.py::TestMath::testadd[小数] PASSED [ 16%]
test_math.py::TestMath::testadd[整数] PASSED [ 33%]
test_math.py::TestMath::testminus[小数] PASSED [ 50%]
test_math.py::TestMath::testminus[整数] PASSED [ 66%]
test_math.py::TestMath::testchengfa[小数] FAILED [ 83%]
test_math.py::TestMath::testchengfa[整数] FAILED [100%]
注意加入scope='class'顺序不一样
test_math.py::TestMath::testadd[小数] PASSED [ 16%] test_math.py::TestMath::testminus[小数] PASSED [ 33%] test_math.py::TestMath::testchengfa[小数] FAILED [ 50%] test_math.py::TestMath::testadd[整数] PASSED [ 66%] test_math.py::TestMath::testminus[整数] PASSED [ 83%] test_math.py::TestMath::testchengfa[整数] FAILED [100%]
加入scope='function'
test_math.py::TestMath::testadd[小数] PASSED [ 16%] test_math.py::TestMath::testadd[整数] PASSED [ 33%] test_math.py::TestMath::testminus[小数] PASSED [ 50%] test_math.py::TestMath::testminus[整数] PASSED [ 66%] test_math.py::TestMath::testchengfa[小数] FAILED [ 83%] test_math.py::TestMath::testchengfa[整数] FAILED [100%]
有时测试功能不须要直接访问fixture对象。使用@pytest.mark.usefixtures直接调用
# conftest.py @pytest.fixture() def writelog(self): try: self.resultfile = open('testtext.txt', 'w+', encoding='utf-8') except Exception as e: pass if self.resultfile.writable(): self.resultfile.writelines('测试开始!') self.resultfile.writelines('\n') yield self.resultfile.writelines('测试结束!') self.resultfile.writelines('\n') self.resultfile.close()
测试类以前加上@pytest.mark.usefixtures('writelog')就能写入文件
测试开始!
测试结束!
能够指定多个灯具
能够将项目中全部测试所需的灯具放入ini文件中
# content of pytest.ini [pytest] usefixtures = writelog
加入Excel进行测试是比较常规的参数化作法
如
首先加入读取excel方法
def getdata(cls): file = xlrd.open_workbook('test.xlsx') sheet = file.sheet_by_index(0) rownum = file.sheet_by_index(0).nrows ablist = [] for row in range(rownum): if row: rowvalue = sheet.row_values(row) ablist.append((rowvalue[2], rowvalue[3])) return ablist #ablist = [(0.1, 0.2), (1.0, 2.0), (0.1, 2.0)]
而后用fixture调用此方法
@pytest.fixture(params= getdata('TestMath')) def gettestdata(self,request): print('参数' + str(request.param)) return request.param
查看运行结果
test_math.py::TestMath::testadd[gettestdata0] PASSED [ 11%] test_math.py::TestMath::testadd[gettestdata1] PASSED [ 22%] test_math.py::TestMath::testadd[gettestdata2] PASSED [ 33%] test_math.py::TestMath::testminus[gettestdata0] PASSED [ 44%] test_math.py::TestMath::testminus[gettestdata1] PASSED [ 55%] test_math.py::TestMath::testminus[gettestdata2] PASSED [ 66%] test_math.py::TestMath::testchengfa[gettestdata0] FAILED [ 77%] test_math.py::TestMath::testchengfa[gettestdata1] FAILED [ 88%] test_math.py::TestMath::testchengfa[gettestdata2] FAILED [100%]
标签很差看,添加一下ids
def getdata(cls): file = xlrd.open_workbook('test.xlsx') sheet = file.sheet_by_index(0) rownum = file.sheet_by_index(0).nrows title = [] ablist = [] for row in range(rownum): if row: rowvalue = sheet.row_values(row) title.append(rowvalue[1]) ablist.append((rowvalue[2], rowvalue[3])) return (title,ablist)
修改成@pytest.fixture(params= getdata('TestMath')[1],ids=getdata('TestMath')[0],在运行看运行结果
test_math.py::TestMath::testadd[两个小数] PASSED [ 11%] test_math.py::TestMath::testadd[两个整数] PASSED [ 22%] test_math.py::TestMath::testadd[小数和整数] PASSED [ 33%] test_math.py::TestMath::testminus[两个小数] PASSED [ 44%] test_math.py::TestMath::testminus[两个整数] PASSED [ 55%] test_math.py::TestMath::testminus[小数和整数] PASSED [ 66%] test_math.py::TestMath::testchengfa[两个小数] FAILED [ 77%] test_math.py::TestMath::testchengfa[两个整数] FAILED [ 88%] test_math.py::TestMath::testchengfa[小数和整数] FAILED [100%]
漂亮不少
添加参数scope='module'运行查看结果,运行顺序有变化,说明默认为scope='function',pytest框架寻找每一个方法调用参数,scope='class',pytest框架寻找每一个类调用参数,以此类推
test_math.py::TestMath::testadd[两个小数] PASSED [ 11%] test_math.py::TestMath::testminus[两个小数] PASSED [ 22%] test_math.py::TestMath::testchengfa[两个小数] FAILED [ 33%] test_math.py::TestMath::testadd[两个整数] PASSED [ 44%] test_math.py::TestMath::testminus[两个整数] PASSED [ 55%] test_math.py::TestMath::testchengfa[两个整数] FAILED [ 66%] test_math.py::TestMath::testadd[小数和整数] PASSED [ 77%] test_math.py::TestMath::testminus[小数和整数] PASSED [ 88%] test_math.py::TestMath::testchengfa[小数和整数] FAILED [100%]