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%]