日誌分級;log分級&全部用py實現
阿新 • • 發佈:2018-12-01
日誌分級;log分級
正常執行的時候,不需要很詳細的日誌
log是網磁盤裡面寫的,自動化測試還好,如果對於開發一個web服務的話,日誌就會太多了。io是很慢的,所以說,出現了問題之後,才需要很詳細的日誌。有問題的時候才需要詳細的日誌。
rf中有專門的日誌模組,讓我們分級打印出內容
from robot.api import logger
開發的時候儘量不用rf的語法:
能不能不用rf語法,全部用py實現,是可以的
完整程式碼截圖:
目錄結構
py關鍵字
程式碼:
import requests from cfg import g_vcode from pprint import pprint from robot.api import logger class SchoolClassLib: #通常用類實現關鍵字型檔,類名和檔名相同 URL = "http://ci.ytesting.com/api/3school/school_classes" #可以寫在類的靜態屬性裡面,也可以寫在cfg的變數檔案裡面 def __init__(self): #定義一個初始化方法 self.vcode = g_vcode #也可以直接用全域性的變數g_vcode def set_vcode(self,vcode): self.vcode = vcode def delete_school_class(self,classid): #刪除班級 payload = { 'vcode' : self.vcode, } url = '{}/{}'.format(self.URL,classid) #url加上id,這裡是這樣構建一下 response = requests.delete(url,data=payload) return response.json() def list_school_class(self,gradeid=None): #列出班級 if gradeid != None: #gradeid是可填可不填的,預設是none params = { #如果傳gradeid 'vcode':self.vcode, 'action':'list_classes_by_schoolgrade', 'gradeid':int(gradeid) } else: params = { 'vcode':self.vcode, #如果不傳 'action':'list_classes_by_schoolgrade' } response = requests.get(self.URL,params=params) #params就是url請求的引數 bodyDict = response.json() #文件裡規定響應是json格式的訊息體。.json可以把json字串轉化為py中的物件。得到的是一個字典 # pprint (bodyDict,indent=2) #indent引數就是指定pprint打印出來的引數是兩個 logger.debug(f"ret:\n{bodyDict}") #通常的執行就不顯示了,報錯的時候顯示所有 return bodyDict def add_school_class(self,gradeid,name,studentlimit): #新增班級 payload = { 'vcode' : self.vcode, 'action' : 'add', 'grade' : int(gradeid), 'name' : name, 'studentlimit' : int(studentlimit), } response = requests.post(self.URL,data=payload) bodyDict = response.json() # pprint (bodyDict,indent=2) logger.debug(f"ret:\n{bodyDict}") #通常的執行就不顯示了,報錯的時候顯示所有 return bodyDict def delete_all_school_classes(self): #初始化清除,要刪除所有的用例 # 先列出所有班級 rd = self.list_school_class() pprint(rd, indent=2) # 刪除列出的所有班級 for one in rd['retlist']: #文件裡面“retlist”:[{},{}] {}裡面是一個個班級,id也在裡面 self.delete_school_class(one['id']) #獲取到id,傳給delete #再列出所有班級 rd = self.list_school_class() pprint (rd,indent=2) # 如果沒有刪除乾淨,通過異常報錯給RF # 參考http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#reporting-keyword-status if rd['retlist'] != []: raise Exception("cannot delete all school classes!!") # def classlist_should_contain(self, # classlist, # classname, # gradename, # invitecode, # studentlimit, # studentnumber, # classid): # item = { # "name":classname, # "grade__name":gradename, # "invitecode":invitecode, # "studentlimit":int(studentlimit), # "studentnumber":int(studentnumber), # "id":classid, # "teacherlist":[] # } # if item not in classlist: # #在rf裡面如果要實現一個檢查點關鍵字,怎麼表示檢查點不通過???就是丟擲異常。 # raise Exception("class list dose not contain your class info") # #裡面的東西隨便寫的 #classlist_should_contain增強版:可能會新增一門課程,多了兩條課程,為了解決這種情況。可以加一個引數指定它包含多少次 def classlist_should_contain(self, classlist, classname, gradename, invitecode, studentlimit, studentnumber, classid, expectedtimes=1): #可以設定一個預設值,不寫的話只應該包含一次 item = { "name":classname, "grade__name":gradename, "invitecode":invitecode, "studentlimit":int(studentlimit), "studentnumber":int(studentnumber), "id":classid, "teacherlist":[] } occurTimes = classlist.count(item) #看occurTimes在列表裡面出現多少次 if occurTimes != expectedtimes: #實際出現的次數和預期的次數是否相等 #在rf裡面如果要實現一個檢查點關鍵字,怎麼表示檢查點不通過???就是丟擲異常。 raise Exception(f"班級列表包含了{occurTimes}次指定資訊,期望包含{expectedtimes}!!") #裡面的東西隨便寫的 def classlist_should_not_contain(self, classlist, classname, gradename, invitecode, studentlimit, studentnumber, classid): item = { "name":classname, "grade__name":gradename, "invitecode":invitecode, "studentlimit":int(studentlimit), "studentnumber":int(studentnumber), "id":classid, "teacherlist":[] } if item in classlist: #如果在裡面的話就會丟擲異常 #在rf裡面如果要實現一個檢查點關鍵字,怎麼表示檢查點不通過???就是丟擲異常。 raise Exception("class list contain your class info") #裡面的東西隨便寫的 if __name__ == '__main__': #除錯用 scm = SchoolClassLib() #ret = scm.list_school_class(2) # ret = scm.add_school_class(1,'新測試',77) # print(json.dumps(ret, indent=2)) # #ret = scm.delete_school_class(63630) # pprint(ret) # print(json.dumps(ret, indent=2)) # # ret = scm.list_school_class(1) # print(json.dumps(ret, indent=2)) # # #scm.delete_all_school_classes() #scm.classlist_should_contain() """ 實現一些個關鍵字 """
程式碼:
from pylib.SchoolClassLib import SchoolClassLib sc = SchoolClassLib() #定義一個類的例項 class c000002: #類名和用例名是一致的 def steps(self): print('''\n\n***** step 1 **** 新增 7年級2班 \n''') self.ret1 = sc.add_school_class(1, '2班', 60) #新增一個班級 if self.ret1['retcode'] != 0: raise Exception('返回值非0') print('''\n\n***** step 2 **** 列出班級,檢驗一下\n''') ret = sc.list_school_class(1) sc.classlist_should_contain(ret['retlist'], #也可以不用這個關鍵字,直接用in '2班', '七年級', self.ret1['invitecode'], 60, 0, self.ret1['id']) def setup(self): #定義一個初始化,這裡沒有就不需要 pass def teardown(self): #定義一個清楚,是在關鍵字檔案裡面實現的。 sc.delete_school_class(self.ret1['id'])
程式碼:
from pylib.SchoolClassLib import SchoolClassLib sc = SchoolClassLib() class c000003: def steps(self): print('''\n\n***** step 1 **** 新增 7年級1班 \n''') self.ret1 = sc.add_school_class(1, '1班', 60) if self.ret1['retcode'] != 1: raise Exception('返回值非1') #檢查狀態 if self.ret1['reason'] != 'duplicated class name': raise Exception('錯誤嗎不對') #檢查資訊 print('''\n\n***** step 2 **** 列出班級,檢驗一下\n''') ret = sc.list_school_class(1) sc.classlist_should_not_contain(ret['retlist'], '1班', '七年級', self.ret1['invitecode'], 60, 0, self.ret1['id']) def setup(self): pass def teardown(self): pass
程式碼:
*** Settings ***
Library pylib.SchoolClassLib
Suite Setup add_school_class 1 1班 60
#這個檔案裡面是實現新增一個7年級1班的初始化
#實現的用例是建立一個班級,系統中不存在同年級的同名班級
#1是代表7年級,1班,上限不超過60人
程式碼:
*** Settings ***
Library pylib.SchoolClassLib
*** Test Cases ***
#新增班級2 - tc000002
# ${ret1}= add school class 1 2班 60
# should be true $ret1['retcode']==0
#
##列出班級,和新增的班級檢驗一下,id一致,邀請碼一致
# ${ret2}= list school class 1
# should be true {'name': '2班', 'grade__name': '七年級', 'invitecode': $ret1['invitecode'], 'studentlimit': 60, 'studentnumber': 0, 'id': $ret1['id'], 'teacherlist': []}in $ret2['retlist']
##列出班級的響應是這樣的:(見圖文件規定)
##rf的寫法實在不是容易的事情,rf不擅長處理複雜的資料,不能換行。
##最好是通過其他的方法來實現
# [Teardown] delete_school_class &{ret1}[id]
##&{ret1}是新增課程產生的字典,取出id刪掉
#第二種簡單,方便,基於py的寫法,用關鍵字實現。
新增班級2 - tc000002
${ret1}= add school class 1 2班 60
should be true $ret1['retcode']==0
#驗證狀態碼是不是0
#列出班級,檢驗一下
${ret2}= list school class 1
${retlist}= evaluate $ret2['retlist']
#把響應裡面的retlist取出來,賦值到變數裡面
classlist should contain ${retlist}
... 2班 七年級 &{ret1}[invitecode] 60 0 &{ret1}[id]
#...是換行,後面傳的都是引數,$ret1['invitecode']不是py表示式,所以裡面不能加引號,從字典裡面取資料用&
#實現一個關鍵字,判斷${retlist}裡面是否包含2班,七年級。。。這些內容。
[Teardown] delete_school_class &{ret1}[id]
#&{ret1}是新增課程產生的字典,取出id刪掉
新增班級3 - tc000003
${ret1}= add school class 1 1班 60
#這裡建立的和資料環境裡面的是一樣的,滿足建立一個已有的同名的課程
#should be true $ret1=={"retcode":1,"reason":"duplicated class name"}
#根據文件判斷返回值,可以向上面一樣寫,不能有兩個以上的空行,安全起見,也可以分開寫
should be true $ret1["retcode"]==1
should be true $ret1["reason"]=="duplicated class name"
#列出班級,檢驗一下
${ret2}= list school class 1
${retlist}= evaluate $ret2['retlist']
#實現關鍵字classlist should not contain ,列出的列表裡面不包含下面的資訊(就是新增的資訊)
classlist should not contain ${retlist}
... 1班 七年級 &{ret1}[invitecode] 60 0 &{ret1}[id]
#[Teardown]清除的操作就不要了,應該是新增不成功的。也沒法根據id來刪除
程式碼:
*** Settings ***
Library cases/c000002.py WITH NAME C000002
Library cases/c000003.py WITH NAME C000003
#用的是斜槓,這樣申明的話,可以到當前目錄(套件檔案)下直接去找,找不到再去py模組裡面找
#with name給匯入的庫重新起一個名字,指定庫的名字。方便下面呼叫函式的時候不會錯亂
*** Test Cases ***
新增班級22 - tc0000022
[Setup] C000002.setup
C000002.steps #兩個用例裡面都是有steps的,匯入的時候,要寫上庫名
[Teardown] C000002.teardown
新增班級33 - tc0000033
[Setup] C000003.setup
C000003.steps
[Teardown] C000003.teardown
#這種方法寫用例,不用考慮rf的變態語法。不需要動腦筋嗎,所有的邏輯,判斷都在py裡面
#用的只是rf的
程式碼:
*** Settings ***
Library pylib.SchoolClassLib
Suite Setup delete all school classes
程式碼:
*** Settings ***
Library pylib.SchoolClassLib
*** Test Cases ***
新增班級1 - tc000001
${ret1}= add school class 1 1班 60
should be true $ret1['retcode']==0
#列出班級,和新增的班級檢驗一下,id一致,邀請碼一致
${ret2}= list school class 1
${fc}= evaluate $ret2['retlist'][0]
should be true $fc['id']==$ret1['id']
should be true $fc['invitecode']==$ret1['invitecode']
#將垃圾資料清除掉,不要破壞空白資料環境
[Teardown] delete_school_class &{ret1}[id]
#&{ret1}是新增課程產生的字典,取出id刪掉
解釋的圖片: