日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

搭建接口自动化测试框架详细过程

發布時間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 搭建接口自动化测试框架详细过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?搭建接口自動化測試框架(文中接口數據來自于光榮之路)

在設計接口測試框架前,先來弄清楚接口測試怎么進行的,請求和響應都是什么樣的,清楚這些之后再進行下一步的操作。

步驟1:新建工程interfaceFramework_practice1,在工程下新建包testScripts用于存放測試腳本文件,在該包下新建testScript.py用戶寫請求代碼

?

按照接口文檔的描述,下面的接口實現了用戶的注冊、登錄、寫博客、修改、刪除博客等功能,先把每一個接口用代碼實現一下。
接口說明:

接口返回code說明:

'00'?:?成功

'01':用戶已存在

'02':參數不合法

'03':參數錯誤(1、用戶信息錯誤?2、參數錯誤,數據庫中不存在相應數據)

'999':未知錯誤,看后臺日志

?

1、用戶注冊

?

?

參數規則說明:

username:

1、必須字母和數字組成

2、長度2~20位

3、字母不區分大小寫

?

password:

1、長度8~20位

2、必須含有字母和數字

?

email:

標準的email規則

?

請求的url: http://39.106.41.29:8080/register/

?

Json串格式參數,請求示例:

{"username": "xufengchai6", "password": "xufengchai121", "email": "xufengchai@qq.com"}

?

響應示例:

{"code": "00", "userid": 48}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

num=random.randint(0,100)

print "register------"

d={"username":"xufengchai%s"%num,"password":"xufengchai121","email":"xufengchai@qq.com"}

print "data before json.dumps:",d

data = json.dumps(d) #

print "data after json.dumps:",data

r = requests.post('http://39.106.41.29:8080/register/', data= data)

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

register------

data before json.dumps: {'username': 'xufengchai6', 'password': 'xufengchai121', 'email': 'xufengchai@qq.com'}

data after json.dumps: {"username": "xufengchai6", "password": "xufengchai121", "email": "xufengchai@qq.com"}

r.status code: 200

r.text: {"code": "00", "userid": 48}

type(r.json()): <type 'dict'>

str(r.json()): {u'code': u'00', u'userid': 48}

?

Process finished with exit code 0

?

可以看到,請求參數包括用戶名,密碼,郵箱,返回的是code和userid,code指明注冊情況,userid用于后續處理博文的用戶標識

2、用戶登錄

?

Json串格式參數,請求示例:

{"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

響應示例:

成功:

{"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

失敗:

{"code": "03", "params": {"username": "xufengchai6", "passwod": "7f73a2e4d8b01b0f0f1062a59d4df635"}}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

md5=hashlib.md5()

md5.update('xufengchai121')

pwd=md5.hexdigest()#轉成16進制

print pwd

?

print "login------"

data=json.dumps({'username':'xufengchai6','password':pwd})

print "data:",data

r=requests.post('http://39.106.41.29:8080/login/',data=data)

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

7f73a2e4d8b01b0f0f1062a59d4df635

login------

data: {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

r.status code: 200

r.text: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

type(r.json()): <type 'dict'>

str(r.json()): {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-05 10:22:05'}

?

Process finished with exit code 0

?

如果登錄成功,會返回token,code,userid等信息

3、新增博文

Json串格式參數,請求示例:

{'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336','title':'practice','content':'interface learn'}

響應示例

{"data": [{"content": "interface learn", "title": "practice"}], "code": "00", "userid": 48}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

md5=hashlib.md5()

md5.update('xufengchai121')

pwd=md5.hexdigest()#轉成16進制

print pwd

?

print "create post------"

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336','title':'practice','content':'interface learn'})

print "data:",data

r=requests.post('http://39.106.41.29:8080/create/',data=data)

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

7f73a2e4d8b01b0f0f1062a59d4df635

create post------

data: {"content": "interface learn", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "title": "practice"}

r.status code: 200

r.text: {"data": [{"content": "interface learn", "title": "practice"}], "code": "00", "userid": 48}

type(r.json()): <type 'dict'>

str(r.json()): {u'userid': 48, u'code': u'00', u'data': [{u'content': u'interface learn', u'title': u'practice'}]}

?

Process finished with exit code 0

?

?

4、查詢用戶的博文

獲取指定用戶的博文(支持偏移量)

Offset與lines結合使用,表示跳過offset條取lines條數據,當不傳offset或lines時,獲取用戶全部博文。

Json串格式參數,請求示例:

{"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

響應示例:

{"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

md5=hashlib.md5()

md5.update('xufengchai121')

pwd=md5.hexdigest()#轉成16進制

print pwd

?

print "query post of user------"

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336'})

print "data:",data

r=requests.post('http://39.106.41.29:8080/getBlogsOfUser/',data=data)

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

7f73a2e4d8b01b0f0f1062a59d4df635

query post of user------

data: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

r.status code: 200

r.text: {"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

type(r.json()): <type 'dict'>

str(r.json()): {u'userid': 48, u'code': u'00', u'data': [{u'update_time': None, u'title': u'practice', u'content': u'interface learn', u'articleId': 2, u'owner': 48, u'posted_on': u'2018-08-05 10:58:58'}, {u'update_time': None, u'title': u'practice', u'content': u'interface learn', u'articleId': 1, u'owner': 48, u'posted_on': u'2018-08-05 10:35:33'}]}

?

Process finished with exit code 0

?

返回的多個博文內容是以一個列表中的多個字典形式存在。

?

?

?

5、修改博文

?

Json串格式參數,請求示例:

{'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336',"articleId":1,"title": "xiaxiaoxu test", "content": "interface learn xia"}

響應示例:

{"articleId": 1, "update_time": "2018-08-05 11:16:05", "code": "00", "userid": 48}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

md5=hashlib.md5()

md5.update('xufengchai121')

pwd=md5.hexdigest()#轉成16進制

print pwd

?

print "update post------"

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336',"articleId":1,"title": "xiaxiaoxu test", "content": "interface learn xia"})

print "data:",data

r=requests.put('http://39.106.41.29:8080/update/',data=data)

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

7f73a2e4d8b01b0f0f1062a59d4df635

update post------

data: {"content": "interface learn xia", "articleId": 1, "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "title": "xiaxiaoxu test"}

r.status code: 200

r.text: {"articleId": 1, "update_time": "2018-08-05 11:16:05", "code": "00", "userid": 48}

type(r.json()): <type 'dict'>

str(r.json()): {u'userid': 48, u'update_time': u'2018-08-05 11:16:05', u'code': u'00', u'articleId': 1}

?

Process finished with exit code 0

?

更新博文后,會返回update_time,表示更新時間

?

6、查詢博文內容

請求地址示例:

http://localhost:8080/getBlogContent/

?

請求示例:

'http://39.106.41.29:8080/getBlogContent/'+str(articleId)

響應示例:

{"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}]}

?

?

代碼:

#encoding=utf-8
import requests
import json
import os
import hashlib
import random


print "query post------"
articleId=1

r=requests.get('http://39.106.41.29:8080/getBlogContent/'+str(articleId))

print "r.status code:",r.status_code
print "r.text:",r.text
print "type(r.json()):",type(r.json())
print "str(r.json()):",str(r.json())

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

query post------

r.status code: 200

r.text: {"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}]}

type(r.json()): <type 'dict'>

str(r.json()): {u'code': u'00', u'data': [{u'update_time': u'2018-08-05 11:16:05', u'title': u'xiaxiaoxu test', u'content': u'interface learn xia', u'articleId': 1, u'owner': 48, u'posted_on': u'2018-08-05 10:35:33'}]}

?

Process finished with exit code 0

?

7、批量查詢博文

請求地址示例:

http://localhost:8080/getBlogsContent/articleIds=1,2,3

響應示例:

{"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}]}

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

print "query posts by blogId------"

?

r=requests.get('http://39.106.41.29:8080/getBlogsContent/'+str('articleIds=1,2'))

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

query posts by blogId------

r.status code: 200

r.text: {"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}]}

type(r.json()): <type 'dict'>

str(r.json()): {u'code': u'00', u'data': [{u'update_time': u'2018-08-05 11:16:05', u'title': u'xiaxiaoxu test', u'content': u'interface learn xia', u'articleId': 1, u'owner': 48, u'posted_on': u'2018-08-05 10:35:33'}, {u'update_time': None, u'title': u'practice', u'content': u'interface learn', u'articleId': 2, u'owner': 48, u'posted_on': u'2018-08-05 10:58:58'}]}

?

Process finished with exit code 0

?

8、刪除博文

Json串格式參數,示例:

{"userid":48, "token": "7f73a2e4d8b01b0f0f1062a59d4df635", "articleId":[2,3,4]}

響應示例:

{"articleId": [2, 3, 4], "code": "00", "userid": 48}

?

刪除之前先查下該用戶下有幾條博文,6條,articleId從1到6

?

?

代碼:

#encoding=utf-8

import requests

import json

import os

import hashlib

import random

?

md5=hashlib.md5()

md5.update('xufengchai121')

pwd=md5.hexdigest()#轉成16進制

print pwd

?

print "delete post------"

data=json.dumps({'userid':48,'token': 7f73a2e4d8b01b0f0f1062a59d4df635,"articleId":[2,3,4]})

print "data:",data

r=requests.delete('http://39.106.41.29:8080/delete/',data=data)

?

print "r.status code:",r.status_code

print "r.text:",r.text

print "type(r.json()):",type(r.json())

print "str(r.json()):",str(r.json())

?

結果:ok

服務器決絕處理刪除請求,可能是服務端針對刪除請求做了設置

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

7f73a2e4d8b01b0f0f1062a59d4df635

delete post------

data: {"articleId": [2, 3, 4], "token": "7f73a2e4d8b01b0f0f1062a59d4df635", "userid": 48}

r.status code: 405

r.text: None

?

Process finished with exit code 0

?

請求和響應參數:

注冊請求和響應參數:

?

請求示例:

{"username": "xufengchai6", "password": "xufengchai121", "email": "xufengchai@qq.com"}

響應示例:

{"code": "00", "userid": 48}

?

登錄的請求和響應參數:

請求示例:

{"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

響應示例:

{"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

?

查詢的請求和響應參數:

請求示例:

{"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

響應示例:

{"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

?

請求的方式:

注冊:

d={"username":"xufengchai%s"%num,"password":"xufengchai121","email":"xufengchai@qq.com"}

data = json.dumps(d)

r = requests.post('http://39.106.41.29:8080/register/', data= data)

?

登錄:

data=json.dumps({'username':'xufengchai6','password':pwd})

r=requests.post('http://39.106.41.29:8080/login/',data=data)

?

新增博文:

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336','title':'practice','content':'interface learn'})

r=requests.post('http://39.106.41.29:8080/create/',data=data)

?

查詢:

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336'})

r=requests.post('http://39.106.41.29:8080/getBlogsOfUser/',data=data)

?

修改:

data=json.dumps({'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336',"articleId":1,"title": "xiaxiaoxu test", "content": "interface learn xia"})

r=requests.put('http://39.106.41.29:8080/update/',data=data)

?

查詢博文內容:

articleId=1

r=requests.get('http://39.106.41.29:8080/getBlogContent/'+str(articleId))

?

批量查詢博文內容:

r=requests.get('http://39.106.41.29:8080/getBlogsContent/'+str('articleIds=1,2'))

?

刪除博文:

data=json.dumps({'userid':48,'token': 7f73a2e4d8b01b0f0f1062a59d4df635,"articleId":[2,3,4]})

r=requests.delete('http://39.106.41.29:8080/delete/',data=data)

?

基于以上對接口的請求和響應的歸類,我們封裝一下http請求的方法

?

步驟2:封裝http請求方法

在工程下新建util包,用于放工具類,在該包下新建HttpClient.py,封裝http請求
HttpClient.py

#encoding=utf-8

import requests

import json

class HttpClient(object):

??? def __init__(self):

??????? pass

?

??? def __post(self,url,data=None,json=None,**kargs):

??????? response=requests.post(url=url,data=data,json=json)

??????? return response

?

??? def __get(self,url,params=None,**kargs):

??????? response=requests.get(url=url,params=params)

?

?

??? def request(self,requestMethod,requestUrl,paramsType,requestData=None,headers=None,cookies=None):

??????? if requestMethod.lower() == "post":

??????????? if paramsType == "form":

????????????? ??response=self.__post(url=requestUrl,data=json.dumps(eval(requestData)),headers=headers,cookies=cookies)

??????????????? return response

??????????? elif paramsType == 'json':

??????????????? response = self.__post(url=requestUrl,json=json.dumps(eval(requestData)),headers=headers,cookies=cookies)

??????????????? return response

??????? elif requestMethod == "get":

??????????? if paramsType == "url":

??????????????? request_url="%s%s" %(requestUrl,requestData)

??????????????? response=self.__get(url=request_url,headers=headers,cookies=cookies)

??????????????? return response

??????????? elif paramsType == "params":

??????????????? response=self.__get(url=requestUrl,params=requestData,headers=headers,cookies=cookies)

??????????????? return response

?

if __name__ == "__main__":

??? hc=HttpClient()

??? response=hc.request("post","http://39.106.41.29:8080/register/","form",'{"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}')

??? print response.text

?

結果:ok

?

C:\Python27\python.exe D:/test/interfaceFramework_practice1/util/httpClient.py

{"username": "xufengchai6", "code": "01"}

?

Process finished with exit code 0

?

在工程下新建testData目錄,存放數據文件
inter_test_data.xlsx

?

?

這個數據文件可以說是本次接口框架的核心,文件中從每個測試用例sheet都代表一個接口,用例中設計了請求數據的格式、請求依賴數據的格式、檢查點、是否需要執行、執行結果、錯誤信息、響應數據、響應狀態碼等。

該文件的結構設計直接決定了框架的邏輯設計,程序首先會遍歷API sheet中的每一行,區分出需要執行的接口用例,然后到對應的接口用例sheet中讀取請求數據,發送http請求,對響應做斷言和存儲并寫入結果,之后再進行下一個接口的處理;其中在處理當前接口用例時會有依賴數據(依賴于上一個接口的請求或響應)的處理,文件中會設置所需依賴數據的格式(模板)和請求數據的格式,程序根據請求數據、依賴數據列存儲的格式獲取到實際用于請求的數據,然后進行發送請求和后續的處理,如何做依賴數據的處理和存儲數據的處理是該框架的難點。

下面就一點一點寫主程序,看看需要做哪些處理,首先要讀取excel文件,需要excel文件的操作,那就把之前封裝的excel操作直接拿過來。

?

步驟3:封裝excel操作方法,讀取excel數據文件

在uti包下新建parseExcel.py

#encoding=utf-8

import openpyxl

from openpyxl.styles import Border,Side,Font

import time

?

class ParseExcel(object):

??? def __init__(self):

??????? self.workbook=None

??????? self.excelFile=None

??????? self.font=Font(color=None)

??????? self.colorDict={'red':'FFFF3030','green':'FF008B00'}

?

??? def loadWorkBook(self,excelPathAndName):

??????? #將excel文件加載到內存,并獲取其workbook對象

??????? try:

??????????? self.workbook=openpyxl.load_workbook(excelPathAndName)

??????? except Exception,e:

??????????? raise e

??????? self.excelFile=excelPathAndName

??????? return self.workbook

??? def getSheetByName(self,sheetName):

??????? try:

??????????? sheet=self.workbook[sheetName]

??????????? return sheet

??????? except Exception,e:

??????????? raise e

?

??? def getSheetByIndex(self,sheetIndex):

??????? try:

??????????? sheetName=self.workbook.sheetnames[sheetIndex]

??????? except Exception,e:

??????????? raise e

??????? sheet=self.workbook[sheetName]

??????? return sheet

?

??? def getTotalRowsNumber(self,sheet):

??????? return sheet.max_row

?

??? def getTotalColsNumber(self,sheet):

??????? return sheet.max_column

?

??? def getStartRowNumber(self,sheet):

??????? return sheet.min_row

?

??? def getStartColNumber(self,sheet):

??????? return sheet.min_column

?

??? def getSingleRow(self,sheet,rowNo):

??????? #獲取sheet中某一行,返回的是這一行所有的數據內容組成的tuple

??????? #下標從1開始,sheet.rows[1]表示第一行

??????? try:

??????????? return list(sheet.rows)[rowNo-1]

??????? except Exception,e:

??????????? raise e

?

??? def getSingleColumn(self,sheet,colNo):

??????? #獲取sheet中某一列,返回的是這一列所有的數據組成的tuple

??????? #下標從1開始,sheet.columns[1]表示第一列

??????? try:

??????????? return list(sheet.columns)[colNo-1]

??????? except Exception,e:

??????????? raise e

?

??? def getValueInCell(self,sheet,coordinate=None,rowNo=None,colNo=None):

??????? #根據單元格所在的位置索引獲取該單元格中的值,下標從1開始

??????? #sheet.cell(row=1,column=1).value,表示excel中第一行第一列的值

??????? if coordinate != None:#coordinate指坐標,如['A2']

??????????? try:

??????????????? return sheet[coordinate].value

??????????? except Exception,e:

??????????????? raise e

??????? elif coordinate is None and rowNo is not None and colNo is not None:

??????????? try:

??????????????? return sheet.cell(row=rowNo,column=colNo).value

??????????? except Exception,e:

??????????????? raise e

??????? else:

??????????? raise Exception("Argument exception! ")

?

??? def writeCell(self,sheet,content,coordinate=None,rowNo=None,colNo=None,color=None):

??????? #根據單元格在excel中的行、列號,或坐標值向單元格中寫入數據

??????? #color標識字體的顏色的名字,如red,green

??????? if coordinate:

??????????? try:

??????????????? sheet[coordinate].value=content

??????????????? if color:

??????????????????? sheet[coordinate].font=Font(color=self.colorDict[color])

??????????????? self.workbook.save(self.excelFile)

??????????? except Exception,e:

??????????????? raise e

??????? elif coordinate == None and rowNo is not None and colNo is not None:

??????????? try:

??????????????? sheet.cell(row=rowNo,column=colNo).value = content

??????????????? if color:

??????????????????? sheet.cell(row=rowNo,column=color).font=Font(color=self.colorDict[color])

??????????????? self.workbook.save(self.excelFile)

??????????? except Exception,e:

??????????????? raise e

??????? else:

??????????? raise Exception("Argument exception!")

?

??? def writeCurrentTimeInCell(self,sheet,coordinate=None,rowNo=None,colNo=None):

??????? #寫入當前時間,下標從1開始,如['A1']

??????? timeArray=time.localtime(time.time())

??????? currentTime=time.strftime("%Y-%m-%d %H:%M:%S",timeArray)

??????? if coordinate is not None:

??????????? try:

??????????????? sheet[coordinate].value=currentTime

??????????????? self.workbook.save(self.excelFile)

??????????? except Exception,e:

??????????????? raise e

??????? elif coordinate == None and rowNo is not None and colNo is not None:

??????????? try:

??????????????? sheet.cell(row == rowNo,column=colNo).value=currentTime

??????????????? self.workbook.save(self.excelFile)

??????????? except Exception,e:

??????????????? raise e

??????? else:

??????????? raise Exception("Argument exception!")

?

if __name__=='__main__':

??? pe=ParseExcel()

??? pe.loadWorkBook(r'd:\\testdata.xlsx')

??? sheetObj=pe.getSheetByName(u"API")

??? print u"用index號獲取sheet對象的名字:",pe.getSheetByIndex(0)

??? sheet=pe.getSheetByIndex(1)

??? print type(sheet)

??? print pe.getTotalRowsNumber(sheetObj)

??? print pe.getTotalColsNumber(sheetObj)

??? print pe.getTotalRowsNumber(sheet)

??? print pe.getTotalColsNumber(sheet)

??? #print list(sheet.rows)[1]

??? rows=pe.getSingleRow(sheet,1)

??? # for i in rows:

??? #???? if i.value:

??? #???????? print i.value

??? print pe.getValueInCell(sheetObj,'A1')

??? pe.writeCell(sheet,"xia","A2")

??? print pe.getValueInCell(sheetObj,"A2")

??? pe.writeCurrentTimeInCell(sheetObj,"A3")

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/util/ParseExcel.py

用index號獲取sheet對象的名字: <Worksheet "API">

<class 'openpyxl.worksheet.worksheet.Worksheet'>

13

13

3

1

a

xia

?

Process finished with exit code 0

?

在工程下新建config包,在該包下新建config.py文件用戶存儲公有變量
config.py:

#encoding=utf-8

import os

#項目的絕對路徑

projectDir=os.path.dirname(os.path.dirname(__file))

?

#數據文件的絕對路徑

file_path=projectDir + "\\testData\\inter_test_data.xlsx"

?

在testScript.py文件中讀取excel的數據
先把API sheet中的信息讀出來:

#encoding=utf-8

import requests

import json

from util.ParseExcel import *

from config.config import *

?

def testInterface():

??? pe=ParseExcel()

??? pe.loadWorkBook(file_path)

??? sheetObj=pe.getSheetByName(u"API")

??? executeList=pe.getSingleColumn(sheetObj,7)

??? #print executeList

??? for idx,cell in enumerate(executeList[1:],2):#第一行標題去掉,idx從2開始

??????? if cell.value == 'y':

??????????? #獲取需要執行的接口所在的行對象

??????????? rowObj=pe.getSingleRow(sheetObj,idx)

??????????? apiName=rowObj[1].value

??????????? requestUrl=rowObj[2].value

??????????? requestMethod=rowObj[3].value

??????????? paramsType=rowObj[4].value

??????????? apiCaseSheetName=rowObj[5].value

??????????? print apiName,requestUrl,requestMethod,paramsType,apiCaseSheetName

?

?

if __name__ == "__main__":

??? testInterface()

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

register http://39.106.41.29:8080/register/ post form 注冊接口用例

login http://39.106.41.29:8080/login/ post form 登錄接口用例

?

Process finished with exit code 0

?

可以看到在讀取需要執行的行中每一列的內容時,用的索引號都是數字,這個不用說,肯定是要在公共變量中存一下的。

?

在config文件中把每個sheet中的列號用變量存起來

#API sheet中所需列號

API_apiName=2

API_requestUrl=3

API_requestMethod=4

API_paramsType=5

API_apiCaseSheetName=6

API_ifExecute=7

?

#接口用例sheet中所需列號

CASE_requestData=1

CASE_relyData=2

CASE_responseCode=3

CASE_responseData=4

CASE_dataStore=5

CASE_checkPoint=6

CASE_ifExecute=7

CASE_result=8

CASE_errorInfo=9

?

接著把caseSheet中的數據讀出來

#下一步讀取用例sheet表,準備執行測試用例

caseSheetObj=pe.getSheetByName(apiCaseSheetName)#獲取用例sheet對象

caseExecuteCol=pe.getSingleColumn(caseSheetObj,CASE_ifExecute)#獲取用例sheet對象中需要執行的列

#遍歷需要執行的列

for c_idx,c_cell in enumerate(caseExecuteCol[1:],2):#標題行忽略,c_idx從2開始

??? if c_cell.value == 'y':

??????? #說明case行需要執行

??????? caseRowObj=pe.getSingleRow(caseSheetObj,c_idx)

??????? requestData=caseRowObj[CASE_requestData-1].value

??????? relyData=caseRowObj[CASE_relyData-1].value

??????? dataStore=caseRowObj[CASE_dataStore-1].value

??????? checkPoint=caseRowObj[CASE_checkPoint-1].value

??????? #print requestData,relyData,dataStore,checkPoint

??????? #if relyData:#relyData列有值的話,需要獲取依賴數據

??????????? #發送接口數據之前,先做依賴數據的處理??????????

?

?

寫到這兒讓我們來分析一下這個框架的結構和邏輯,它是如何對每個接口進行測試和斷言的?這個問題想明白了,這個框架的核心就確定了。
先看下文檔中接口的信息:

在注冊接口中,請求數據RequestData直接給出了,那么把這列數據取出來,直接發送請求就可以了,然后把結果寫在responseData列,注冊接口響應參數有code和userid, userid是一個主鍵,唯一標識一個用戶,在checkPoint列設置檢查點,和響應code做對比,如果匹配00,就說明注冊接口請求成功了,把Result列寫入pass。

?

?

因為請求數據直接給出了,不需要依賴別的數據,那RelyData列置空,然后有個ResponseCode列需要寫一下請求的狀態碼,比如返回200,就寫200,然后看DataStore列,這一列是用來存儲接口請求的信息的,可以寫請求的參數信息,也可以寫響應的參數信息,這個存儲數據是干啥的呢,它是用來為其他接口請求做準備數據的;

比如登錄接口,在登錄之前,需要獲取用戶的用戶名和密碼,那它就需要從注冊接口的信息來獲取,可以在注冊接口的DataStore列把用戶名和密碼信息直接寫進去,如username:xiaxiaoxu,password:ksdfjlks,然后再運行登錄接口請求時,過來把數據取出來,直接發送請求就行了,登錄接口返回的參數有token和userid,這個token是查詢博文接口用的;

接下來我們再把各個接口的請求參數和響應參數列出來,然后來看下下游接口的請求數據是如何依賴上游接口的數據的。

注冊接口:

請求:

{"username": "xufengchai6", "password": "xufengchai121", "email": "xufengchai@qq.com"}

響應:

{"code": "00", "userid": 48}

---------------------------------------------------------------------------------------------------------------------------

登錄接口:

請求:

{"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

這里的username、password依賴于注冊接口中的請求數據

響應:

{"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

---------------------------------------------------------------------------------------------------------------------------

新增博文:

請求:

{'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336','title':'practice','content':'interface learn'}

這里的userid、token依賴于登錄接口中的響應數據

響應:

{"data": [{"content": "interface learn", "title": "practice"}], "code": "00", "userid": 48}

---------------------------------------------------------------------------------------------------------------------------

查詢用戶博文:

請求:

{"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

這里的token、userid可以依賴于新增博文接口的響應數據,也可以依賴登錄于接口的響應數據

響應:

{"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

---------------------------------------------------------------------------------------------------------------------------

修改博文:

請求:

{'userid':48,'token':'290cbf8f1438f3d8f56d9026604de336',"articleId":1,"title": "xiaxiaoxu test", "content": "interface learn xia"}

這里的articleId、title中的可以依賴于查詢用戶博文接口的響應數據,userid、token可以依賴于查詢用戶博文接口的請求數據

響應:

{"articleId": 1, "update_time": "2018-08-05 11:16:05", "code": "00", "userid": 48}

---------------------------------------------------------------------------------------------------------------------------

查詢博文內容:

請求:

'http://39.106.41.29:8080/getBlogContent/'+str(articleId)

這里的articleId可以依賴于查詢用戶博文接口的響應數據,也可以依賴于修改博文的請求數據,但是修改博文接口不一定會運行,依賴于查詢用戶博文接口會穩妥一些

響應:

{"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}]}

---------------------------------------------------------------------------------------------------------------------------

批量查詢博文內容:

請求:

http://localhost:8080/getBlogsContent/articleIds=1,2,3

這里的articleIds可以依賴于查詢用戶博文接口的響應數據

響應:

{"code": "00", "data": [{"update_time": "2018-08-05 11:16:05", "title": "xiaxiaoxu test", "content": "interface learn xia", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}]}

?

通過上邊各個接口的數據依賴關系,可以看出某個接口在請求的之前,要先根據依賴關系到某個上游接口的請求或者響應數據中獲取需要的數據,那么怎么去把這個數據獲取到呢?以什么規則去獲取呢?把這兩個個問題解決了,我認為這個框架就成功了一半了!

為啥呢,因為我一半的時間都用來思考這兩個問題了,雖然事先已經知道了答案,但是為了透徹的理解其中的原理,花了很長時間來推理這個答案的合理性和必然性~~

對于這種框架的原理,我總是嘗試著把所有的細節都揉碎了來重新梳理,推理出每一個步驟的合理性,這樣會理解的更深一些。

?

初步的思路是每個接口在運行的時候把請求數據和響應數據都寫到文件里,然后下一個接口在訪問的時候去依賴接口中讀取請求數據或者響應數據,然后再把請求和響應數據寫到自己的sheet表中,以此類推,接著考慮一下實現的細節,這個框架要兼顧多個接口的運行,每個接口的請求數據、存儲數據的方法需要用封裝的函數來進行處理,這就需要把這些接口的數據信息的獲取抽象出一個公用的方法,這個方法可以實現所有接口的數據處理,比如某個接口在獲取請求數據時,要先根據接口的請求參數設置一個依賴規則,指明每個參數需要到哪個接口的哪個用例的請求數據或者響應數據中,讀取哪個參數的值,每個參數可能需要到不同的接口中獲取數據,這個依賴規則需要給出具體的接口名、用例號(行號)、數據類型是請求的還是響應的,然后根據數據類型到不同的列號取值,取的時候,先找到單元格,把內容讀出來,轉成字典的格式,然后找所需的鍵值對,有的接口字典深度不止一層(如查詢接口),那就要再做一層處理,獲取完請求數據信息,就可以發送請求了,之后再把響應數據寫到文件中,后續接口可能會用到。

?

步驟4:封裝方法獲取請求數據

在action包下新建文件getRequestData.py:
getRequestData.py

# encoding=utf-8

?

from util.ParseExcel import *

import os

from config.config import *

import json

?

?

class GetRequestData(object):

??? def __init__(self):

??????? pass

?

??? @classmethod

??? def getRequestData(cls, relyRule):

??????? pe = ParseExcel()

??????? pe.loadWorkBook(file_path)

??????? requestData = {}

??????? # relySource = {"token": "", "userid": "","articleid":""}

??????? # relyRule = {"token":"userRegister->1->request","userid":"register->1->response","articleid":"userLogin->1->response->['data'][0]"}

??????? interDict = {"userRegister": "register",

???????????????????? "userLogin": "login",

???????????????????? "searchUserBlog": "search",

???????????????????? "modifyBlog": "modify"}

??????? dataTypeColDict = {"request": CASE_requestData,

?????????????????????????? "response": CASE_responseData}

???? ???# 根據接口名映射一個字典,對應接口sheet名稱

??????? # 獲取到依賴接口的sheet頁,case號(行號),請求列或者響應列號,

??????? # 然后到對應單元格取數據,轉成字典格式,

??????? # 取出里面對應層級的數據

??????? for key, value in relyRule.items():? # "articleid":"userLogin->1->response->['data'][0]"

??????????? print "key:value==>", key, ":", value

??????????? rList = value.split("->")

??????????? print "len(rList):", len(rList)

??????????? if len(rList) == 4:

??????????????? # 說明所需數據在依賴數據的第二層

??????????????? interfaceType, caseNo, dataType, dataKey = rList

??????????????? # print "interfaceType,caseNo,dataType,dataKey:",interfaceType,',',caseNo,',',dataType,',',dataKey

??????????????? # print "interDict[interfaceType]:",interDict[interfaceType]

??????????????? # print "dataTypeColDict[dataType]:",dataTypeColDict[dataType]

????????? ??????interSheetObj = pe.getSheetByName(interDict[interfaceType])

??????????????? # print "interSheetObj:",interSheetObj

??????????????? relyContent = json.loads(

??????????????????? pe.getValueInCell(interSheetObj, rowNo=int(caseNo) + 1, colNo=dataTypeColDict[dataType]))

??????????????? # print "relyContent:",relyContent

??????????????? # print "type(relyContent):",type(relyContent)

??????????????? command = "%s%s['%s']" % (relyContent, dataKey, key)

??????????????? # print "command:",command

??????????????? requestData[key] = eval(command)

??????????????? print "requestData-3:",requestData

??????????? elif len(rList) == 3:

??????????????? # 說明所需數據在依賴數據的第一層

??????????????? # "token":"userLogin->1->response"

??????????????? interfaceType, caseNo, dataType = rList

??????????????? # print "interfaceType,caseNo,dataType:",interfaceType,',',caseNo,',',dataType

??????????????? # print "interDict[interfaceType]:",interDict[interfaceType]

??????????????? # print "dataTypeColDict[dataType]:",dataTypeColDict[dataType]

??????????????? interSheetObj = pe.getSheetByName(interDict[interfaceType])

??????????????? # print "interSheetObj:",interSheetObj

??????????????? contentStr = '%s' % pe.getValueInCell(interSheetObj, rowNo=int(caseNo) + 1,

?????????????????? ???????????????????????????????????colNo=dataTypeColDict[dataType])

??????????????? print "contentStr:", contentStr

??????????????? print "type(contentStr):", type(contentStr)

??????????????? relyContent = json.loads(contentStr)

??????????????? print "relyContent:", relyContent

??????????????? # print "type(relyContent):",type(relyContent)

??????????????? command = "%s['%s']" % (relyContent, key)

??????????????? # print "command:",command

??????????????? requestData[key] = eval(command)

??????????????? print "requestData-1:",requestData

??????????? else:

??????????????? requestData[key] = value

??????? return requestData

?

?

if __name__ == "__main__":

??? relyRule = {"articleId": "searchUserBlog->1->response->['data'][0]", "token": "userLogin->1->response",

??????????????? "content": "xiaxiaoxu"}

print GetRequestData.getRequestData(relyRule)

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/action/getRequestData.py

key:value==> content : xiaxiaoxu

len(rList): 1

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-05 10:22:05'}

requestData-1: {'content': 'xiaxiaoxu', 'token': u'290cbf8f1438f3d8f56d9026604de336'}

key:value==> articleId : searchUserBlog->1->response->['data'][0]

len(rList): 4

requestData-3: {'content': 'xiaxiaoxu', 'token': u'290cbf8f1438f3d8f56d9026604de336', 'articleId': 2}

{'content': 'xiaxiaoxu', 'token': u'290cbf8f1438f3d8f56d9026604de336', 'articleId': 2}

?

Process finished with exit code 0

?

這種獲取請求數據方法的思路是,在每個接口中把請求的數據設置一個依賴的規則,用來指明所需的參數來自哪個接口的請求數據還是響應數據,然后程序根據這個依賴規則,去所依賴的地方獲取數據。

例如

relyRule={"articleId":"searchUserBlog->1->response->['data'][0]","token":"userLogin->1->response","content": "xiaxiaoxu"},

這個依賴規則是個json串,用json編輯器可以看到它的結構:

?

可以看到它有三個兄弟節點,代表該接口需要三個請求參數,每個兄弟節點下邊是這個參數所依賴的規則,比如"articleId":"searchUserBlog->1->response->['data'][0]",表示"articleId"這個參數依賴的數據是searchUserBlog接口的數據,具體是在searchUserBlog接口的第一個用例的響應數據中的[‘data’]對應的數據中的第1個articleId字段的值,其所依賴的接口數據存儲的格式也是json串的形式,可以轉成python的字典結構,這樣依賴規則的每一層數據都可以用作為字典的key取出對應的value值,這個value值又作為新一層字典來取值。

下面是searchUserBlog接口的響應數據的例子:

{"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

需要注意的是,在每個接口獲取請求數據時,它所依賴的接口的數據要事先存在,否則就取不到數據了,所以,在處理完每個接口的請求后,需要把請求數據和響應數據寫入文件,以備后續接口使用。

下一步實現寫入文件的方法

?

步驟5:實現寫入文件的方法

在action包下新建write_test_result.py
write_test_result.py

#encoding=utf-8

from config import *

from util.ParseExcel import *

from action.getRequestData import *

import json

?

def write_result(wbObj,sheetObj,rowNum,requestData=None,responseData=None,errorKey = None):

??? try:

??????? if requestData:

??????????? #寫入請求數據

??????????? print "requestData-4:",requestData

??????????? print "type(requestData-4):",type(requestData)

??????????? wbObj.writeCell(sheet=sheetObj,content=requestData,rowNo=rowNum,colNo=CASE_requestData)

??????? if responseData:

??????????? #寫響應body

??????????? wbObj.writeCell(sheet=sheetObj,content=responseData,rowNo=rowNum,colNo=CASE_responseData)

??????? #寫校驗結果狀態列及錯誤信息列

??????? if errorKey:

??????????? wbObj.writeCell(sheet=sheetObj,content="failed",rowNo=rowNum,colNo=CASE_result)

??????????? wbObj.writeCell(sheet=sheetObj,content="%s" %errorKey,rowNo = rowNum,colNo=CASE_errorInfo)

??????? else:

??????????? wbObj.writeCell(sheetObj,content="pass",rowNo=rowNum,colNo=CASE_result)

??? except Exception,e:

??????? raise e

?

在主程序中調用該方法:
testScript.py:

#encoding=utf-8

import requests

import json

from util.ParseExcel import *

from util.httpClient import *

from config.config import *

from action.write_test_result import *

?

def testInterface():

??? parseE = ParseExcel()

??? parseE.loadWorkBook(file_path)

??? sheetObj = parseE.getSheetByName(u"API")

??? activeList = parseE.getSingleColumn(sheetObj, API_ifExecute)

??? for idx, cell in enumerate(activeList[1:], 2):

??????? if cell.value == 'y':

??????????? rowObj = parseE.getSingleRow(sheetObj, idx)

??????????? apiName = rowObj[API_apiName - 1].value

??????????? requestUrl = rowObj[API_requestUrl - 1].value

??????????? requestMethod = rowObj[API_requestMethod - 1].value

??????????? paramsType = rowObj[API_paramsType - 1].value

??????????? apiTestCaseFileName = rowObj[API_apiCaseSheetName - 1].value

??????????? # print apiName,requestUrl,requestMethod,paramsType,apiTestCaseFileName

??????????? # 下一步讀sheet表,準備執行測試用例

??????????? print "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"

??????????? print "apiTestCaseFileName:", apiTestCaseFileName

??????????? caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)

??????????? caseActiveObj = parseE.getSingleColumn(caseSheetObj, CASE_ifExecute)

????????? ??for c_idx, col in enumerate(caseActiveObj[1:], 2):

??????????????? if col.value == 'y':

??????????????????? caseRowObj = parseE.getSingleRow(caseSheetObj, c_idx)

??????????????????? relyRule = caseRowObj[CASE_relyRule - 1].value

??????????????????? print "relyRule:", relyRule

??????????????????? if relyRule:

??????????????????????? # 發送接口請求之前,先獲取請求數據

??????????????????????? requestData = json.dumps(GetRequestData.getRequestData(eval(relyRule)))

??????????????????????? print "requestData-2:", requestData

??????????????????????? write_result(parseE,caseSheetObj,c_idx,requestData=requestData)

??????????????????????? # print "print requestData Done!"

?

?

if __name__ == "__main__":

??? testInterface()

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: register

relyRule: None

relyRule: None

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: login

relyRule: {"username":"userRegister->1->request","password":"userRegister->1->request"}

key:value==> username : userRegister->1->request

len(rList): 3

contentStr: {"username":"srsdcx01","password":"wcx123wac1","email":"wcx@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'srsdcx01', u'password': u'wcx123wac1', u'email': u'wcx@qq.com'}

requestData-1: {'username': u'srsdcx01'}

key:value==> password : userRegister->1->request

len(rList): 3

contentStr: {"username":"srsdcx01","password":"wcx123wac1","email":"wcx@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'srsdcx01', u'password': u'wcx123wac1', u'email': u'wcx@qq.com'}

requestData-1: {'username': u'srsdcx01', 'password': u'wcx123wac1'}

requestData-2: {"username": "srsdcx01", "password": "wcx123wac1"}

requestData-4: {"username": "srsdcx01", "password": "wcx123wac1"}

type(requestData-4): <type 'str'>

relyRule: {"username":"userRegister->2->request","password":"userRegister->2->request"}

key:value==> username : userRegister->2->request

len(rList): 3

contentStr: {"username":"wcd23x","password":"wcx123wac","email":"wcx@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'wcd23x', u'password': u'wcx123wac', u'email': u'wcx@qq.com'}

requestData-1: {'username': u'wcd23x'}

key:value==> password : userRegister->2->request

len(rList): 3

contentStr: {"username":"wcd23x","password":"wcx123wac","email":"wcx@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'wcd23x', u'password': u'wcx123wac', u'email': u'wcx@qq.com'}

requestData-1: {'username': u'wcd23x', 'password': u'wcx123wac'}

requestData-2: {"username": "wcd23x", "password": "wcx123wac"}

requestData-4: {"username": "wcd23x", "password": "wcx123wac"}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: search

relyRule: {"token":"userLogin->1->response","userid":"userLogin->1->response"}

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-05 10:22:05'}

requestData-1: {'token': u'290cbf8f1438f3d8f56d9026604de336'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-05 10:22:05"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-05 10:22:05'}

requestData-1: {'token': u'290cbf8f1438f3d8f56d9026604de336', 'userid': 48}

requestData-2: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

requestData-4: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: modify

relyRule: {"userid":"searchUserBlog->1->response","token":"searchUserBlog->1->request","articleId":"searchUserBlog->1->response->['data'][0]","title":"searchUserBlog->1->response->['data'][0]","content":"interface learn xia"}

key:value==> content : interface learn xia

len(rList): 1

key:value==> articleId : searchUserBlog->1->response->['data'][0]

len(rList): 4

requestData-3: {'content': 'interface learn xia', 'articleId': 2}

key:value==> token : searchUserBlog->1->request

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'userid': 48}

requestData-1: {'content': 'interface learn xia', 'token': u'290cbf8f1438f3d8f56d9026604de336', 'articleId': 2}

key:value==> userid : searchUserBlog->1->response

len(rList): 3

contentStr: {"data": [{"update_time": null, "title": "practice", "content": "interface learn", "articleId": 2, "owner": 48, "posted_on": "2018-08-05 10:58:58"}, {"update_time": null, "title": "practice", "content": "interface learn", "articleId": 1, "owner": 48, "posted_on": "2018-08-05 10:35:33"}], "code": "00", "userid": 48}

type(contentStr): <type 'unicode'>

relyContent: {u'userid': 48, u'code': u'00', u'data': [{u'update_time': None, u'title': u'practice', u'content': u'interface learn', u'articleId': 2, u'owner': 48, u'posted_on': u'2018-08-05 10:58:58'}, {u'update_time': None, u'title': u'practice', u'content': u'interface learn', u'articleId': 1, u'owner': 48, u'posted_on': u'2018-08-05 10:35:33'}]}

requestData-1: {'content': 'interface learn xia', 'userid': 48, 'token': u'290cbf8f1438f3d8f56d9026604de336', 'articleId': 2}

key:value==> title : searchUserBlog->1->response->['data'][0]

len(rList): 4

requestData-3: {'content': 'interface learn xia', 'userid': 48, 'token': u'290cbf8f1438f3d8f56d9026604de336', 'articleId': 2, 'title': u'practice'}

requestData-2: {"content": "interface learn xia", "userid": 48, "token": "290cbf8f1438f3d8f56d9026604de336", "articleId": 2, "title": "practice"}

requestData-4: {"content": "interface learn xia", "userid": 48, "token": "290cbf8f1438f3d8f56d9026604de336", "articleId": 2, "title": "practice"}

type(requestData-4): <type 'str'>

?

Process finished with exit code 0

?

文件中的請求數據已經寫進去了,先忽略響應數據

?

?

發現忘了處理passord的加密過程了,在getRequestdata.py中處理一下
在util包下新建md5_encrypt.py用戶加密處理
md5_encrypt.py:

#encoding=utf-8

import hashlib

?

def md5_encrypt(text):

??? m5 = hashlib.md5()

??? m5.update(text)

??? value = m5.hexdigest()

??? return value

?

if __name__ == "__main__":

print md5_encrypt("xiaxiaoxu")

?

結果:ok

D:\test_python\interfaceFramework>python md5_encrypt.py

a2f93c01757358aa9c3ee4372a2f4eca

修改getRequestData.py文件加入密碼加密處理:

# encoding=utf-8

?

from util.ParseExcel import *

import os

from config.config import *

import json

from util.md5_encrypt import *

?

class GetRequestData(object):

??? def __init__(self):

??????? pass

?

??? @classmethod

??? def getRequestData(cls, relyRule):

??????? pe = ParseExcel()

??????? pe.loadWorkBook(file_path)

??????? requestData = {}

??????? # relySource = {"token": "", "userid": "","articleid":""}

??????? # relyRule = {"token":"userRegister->1->request","userid":"register->1->response","articleid":"userLogin->1->response->['data'][0]"}

??????? interDict = {"userRegister": "register",

???????????? ????????"userLogin": "login",

???????????????????? "searchUserBlog": "search",

???????????????????? "modifyBlog": "modify"}

??????? dataTypeColDict = {"request": CASE_requestData,

?????????????????????????? "response": CASE_responseData}

??????? # 根據接口名映射一個字典,對應接口sheet名稱

??????? # 獲取到依賴接口的sheet頁,case號(行號),請求列或者響應列號,

??????? # 然后到對應單元格取數據,轉成字典格式,

??????? # 取出里面對應層級的數據

??????? for key, value in relyRule.items():? # "articleid":"userLogin->1->response->['data'][0]"

??????????? print "key:value==>", key, ":", value

??????????? rList = value.split("->")

??????????? print "len(rList):", len(rList)

??????????? if len(rList) == 4:

??????????????? # 說明所需數據在依賴數據的第二層

??????????????? interfaceType, caseNo, dataType, dataKey = rList

??????????????? # print "interfaceType,caseNo,dataType,dataKey:",interfaceType,',',caseNo,',',dataType,',',dataKey

??????????????? # print "interDict[interfaceType]:",interDict[interfaceType]

??????????????? # print "dataTypeColDict[dataType]:",dataTypeColDict[dataType]

??????????????? interSheetObj = pe.getSheetByName(interDict[interfaceType])

??????????????? # print "interSheetObj:",interSheetObj

??????????????? relyContent = json.loads(

??????????????????? pe.getValueInCell(interSheetObj, rowNo=int(caseNo) + 1, colNo=dataTypeColDict[dataType]))

??????????????? # print "relyContent:",relyContent

??????????????? # print "type(relyContent):",type(relyContent)

??????????????? command = "%s%s['%s']" % (relyContent, dataKey, key)

??????????????? # print "command:",command

??????????????? requestData[key] = eval(command)

??????????????? print "requestData-3:",requestData

??????????? elif len(rList) == 3:

??????????????? # 說明所需數據在依賴數據的第一層

??????????????? # "token":"userLogin->1->response"

??????????????? interfaceType, caseNo, dataType = rList

??????????????? # print "interfaceType,caseNo,dataType:",interfaceType,',',caseNo,',',dataType

??????????????? # print "interDict[interfaceType]:",interDict[interfaceType]

??????????????? # print "dataTypeColDict[dataType]:",dataTypeColDict[dataType]

??????????????? interSheetObj = pe.getSheetByName(interDict[interfaceType])

??????????????? # print "interSheetObj:",interSheetObj

??????????????? contentStr = '%s' % pe.getValueInCell(interSheetObj, rowNo=int(caseNo) + 1,

????????????????????????????????????????????????????? colNo=dataTypeColDict[dataType])

??????????????? print "contentStr:", contentStr

??????????????? print "type(contentStr):", type(contentStr)

??????????????? relyContent = json.loads(contentStr)

??????? ????????print "relyContent:", relyContent

??????????????? # print "type(relyContent):",type(relyContent)

??????????????? command = "%s['%s']" % (relyContent, key)

??????????????? # print "command:",command

??????????????? print "key:eval(command):",key,eval(command)

??????????????? requestData[key] = md5_encrypt(eval(command)) if key == "password" else eval(command)

??????????????? print "requestData-1:",requestData

??????????? else:

??????????????? requestData[key] = value

??????? return requestData

?

?

if __name__ == "__main__":

??? relyRule = {"articleId": "searchUserBlog->1->response->['data'][0]", "password": "userRegister->1->request",

??????????????? "content": "xiaxiaoxu"}

??? print GetRequestData.getRequestData(relyRule)

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/action/getRequestData.py

key:value==> content : xiaxiaoxu

len(rList): 1

key:value==> password : userRegister->1->request

len(rList): 3

contentStr: {"username":"srsdcx01","password":"wcx123wac1","email":"wcx@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'srsdcx01', u'password': u'wcx123wac1', u'email': u'wcx@qq.com'}

key:eval(command): password wcx123wac1

requestData-1: {'content': 'xiaxiaoxu', 'password': 'd85fb67e312ed3a589951720a6f3b079'}

key:value==> articleId : searchUserBlog->1->response->['data'][0]

len(rList): 4

requestData-3: {'content': 'xiaxiaoxu', 'password': 'd85fb67e312ed3a589951720a6f3b079', 'articleId': 2}

{'content': 'xiaxiaoxu', 'password': 'd85fb67e312ed3a589951720a6f3b079', 'articleId': 2}

?

Process finished with exit code 0

?

至此,已經實現了獲取請求數據,封裝了http請求的方法,那么把請求數據用http請求的方式發送給服務器就完成了接口的請求過程,下面在主程序中加入發送請求和寫入結果的處理

?

步驟 6:處理發送請求和寫入結果

在主程序中添加http請求處理,并把請求數據和響應數據寫入文件
testScript.py:

#encoding=utf-8

import requests

import json

from util.ParseExcel import *

from util.httpClient import *

from config.config import *

from action.write_test_result import *

from action.check_result import *

def testInterface():

??? parseE = ParseExcel()

??? parseE.loadWorkBook(file_path)

??? sheetObj = parseE.getSheetByName(u"API")

??? activeList = parseE.getSingleColumn(sheetObj, API_ifExecute)

??? for idx, cell in enumerate(activeList[1:], 2):

??????? if cell.value == 'y':

??????????? rowObj = parseE.getSingleRow(sheetObj, idx)

???????? ???apiName = rowObj[API_apiName - 1].value

??????????? requestUrl = rowObj[API_requestUrl - 1].value

??????????? requestMethod = rowObj[API_requestMethod - 1].value

??????????? paramsType = rowObj[API_paramsType - 1].value

??????????? apiTestCaseFileName = rowObj[API_apiCaseSheetName - 1].value

??????????? # print apiName,requestUrl,requestMethod,paramsType,apiTestCaseFileName

??????????? # 下一步讀sheet表,準備執行測試用例

??????????? print "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"

??????????? print "apiTestCaseFileName:", apiTestCaseFileName

??????????? caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)

??????????? caseActiveObj = parseE.getSingleColumn(caseSheetObj, CASE_ifExecute)

??????????? for c_idx, col in enumerate(caseActiveObj[1:], 2):

??????????? ????if col.value == 'y':

??????????????????? caseRowObj = parseE.getSingleRow(caseSheetObj, c_idx)

??????????????????? relyRule = caseRowObj[CASE_relyRule - 1].value

??????????????????? checkPoint=caseRowObj[CASE_checkPoint-1].value

??????????????????? print "relyRule:", relyRule

?

??????????????????? if relyRule:

??????????????????????? # 發送接口請求之前,先獲取請求數據

??????????????????????? requestData = json.dumps(GetRequestData.getRequestData(eval(relyRule)))

??????????????????????? print "requestData-2:", requestData

??????????????????? else:

??????????????????????? requestData=caseRowObj[CASE_requestData-1].value

??????????????????????? print "requestData without relyRule:",requestData,type(requestData)

???? ???????????????hc = HttpClient()

??????????????????? print "requestMethod, requestUrl, paramsType, requestData:"

??????????????????? print requestMethod, requestUrl, paramsType, requestData

??????????????????? response = hc.request(requestMethod=requestMethod,

???????????????????????????????????????????? requestUrl=requestUrl,

???????????????????????????????????????????? paramsType=paramsType,

???????????????????????????????????????????? requestData=requestData

???????????????????????????????????????????? )

??????????????????? print "#############response.text##############:",response.text

??????????????????? if response.status_code ==200:

??????????????????????? responseData=response.text

??????????????????????? print "responseData:",responseData

????????? ??????????????write_result(parseE,caseSheetObj,c_idx,requestData=requestData,responseData=responseData)

?

結果: ok

?

D:\test_python\interfaceFramework>python testScript.py

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: searchUserBlog

relyRule: {"token":"userLogin->1->response","userid":"userLogin->1->response"}

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-15 12:20:06"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-15 12:20:06'}

key:eval(command): token 290cbf8f1438f3d8f56d9026604de336

requestData-1: {'token': u'290cbf8f1438f3d8f56d9026604de336'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-15 12:20:06"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-15 12:20:06'}

key:eval(command): userid 48

requestData-1: {'token': u'290cbf8f1438f3d8f56d9026604de336', 'userid': 48}

requestData-2: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/getBlogsOfUser/ form {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

#############response.text##############: {"code": "03", "params": {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}}

responseData: {"code": "03", "params": {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}}

requestData-4: {"token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: addBlog

relyRule: {"userid":"userLogin->1->response","token":"userLogin->1->response","titile":"xiaxiaoxu's blog","content":"keep learning"}

key:value==> content : keep learning

len(rList): 1

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-15 12:20:06"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-15 12:20:06'}

key:eval(command): token 290cbf8f1438f3d8f56d9026604de336

requestData-1: {'content': 'keep learning', 'token': u'290cbf8f1438f3d8f56d9026604de336'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "290cbf8f1438f3d8f56d9026604de336", "code": "00", "userid": 48, "login_time": "2018-08-15 12:20:06"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'290cbf8f1438f3d8f56d9026604de336', u'code': u'00', u'userid': 48, u'login_time': u'2018-08-15 12:20:06'}

key:eval(command): userid 48

requestData-1: {'content': 'keep learning', 'token': u'290cbf8f1438f3d8f56d9026604de336', 'userid': 48}

key:value==> titile : xiaxiaoxu's blog

len(rList): 1

requestData-2: {"content": "keep learning", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "titile": "xiaxiaoxu's blog"}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/create/ form {"content": "keep learning", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "titile": "xiaxiaoxu's blog"}

#############response.text##############: {"code": "03", "params": {"content": "keep learning", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "titile": "xiaxiaoxu's blog"}}

responseData: {"code": "03", "params": {"content": "keep learning", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "titile": "xiaxiaoxu's blog"}}

requestData-4: {"content": "keep learning", "token": "290cbf8f1438f3d8f56d9026604de336", "userid": 48, "titile": "xiaxiaoxu's blog"}

type(requestData-4): <type 'str'>

?

D:\test_python\interfaceFramework>python testScript.py

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: register

relyRule: None

requestData without relyRule: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"} <type 'unicode'>

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/register/ form {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

#############response.text##############: {"code": "00", "userid": 17}

responseData: {"code": "00", "userid": 17}

requestData-4: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(requestData-4): <type 'unicode'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: login

relyRule: {"username":"userRegister->1->request","password":"userRegister->1->request"}

key:value==> username : userRegister->1->request

len(rList): 3

contentStr: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'xufengchai6', u'password': u'xufengchai121', u'email': u'xufengchai@qq.com'}

key:eval(command): username xufengchai6

requestData-1: {'username': u'xufengchai6'}

key:value==> password : userRegister->1->request

len(rList): 3

contentStr: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'xufengchai6', u'password': u'xufengchai121', u'email': u'xufengchai@qq.com'}

key:eval(command): password xufengchai121

requestData-1: {'username': u'xufengchai6', 'password': '7f73a2e4d8b01b0f0f1062a59d4df635'}

requestData-2: {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/login/ form {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

#############response.text##############: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

responseData: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

requestData-4: {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: addBlog

relyRule: {"userid":"userLogin->1->response","token":"userLogin->1->response","titile":"xiaxiaoxu's blog","content":"keep learning"}

key:value==> content : keep learning

len(rList): 1

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'5e546324ba91858b26216d399dee33e1', u'code': u'00', u'userid': 17, u'login_time': u'2018-08-16 12:17:59'}

key:eval(command): token 5e546324ba91858b26216d399dee33e1

requestData-1: {'content': 'keep learning', 'token': u'5e546324ba91858b26216d399dee33e1'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'5e546324ba91858b26216d399dee33e1', u'code': u'00', u'userid': 17, u'login_time': u'2018-08-16 12:17:59'}

key:eval(command): userid 17

requestData-1: {'content': 'keep learning', 'token': u'5e546324ba91858b26216d399dee33e1', 'userid': 17}

key:value==> titile : xiaxiaoxu's blog

len(rList): 1

requestData-2: {"content": "keep learning", "token": "5e546324ba91858b26216d399dee33e1", "userid": 17, "titile": "xiaxiaoxu's blog"}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/create/ form {"content": "keep learning", "token": "5e546324ba91858b26216d399dee33e1", "userid": 17, "titile": "xiaxiaoxu's blog"}

#############response.text##############: {"code": "03", "params": {"content": "keep learning", "token": "5e546324ba91858b26216d399dee33e1", "userid": 17, "titile": "xiaxiaoxu's blog"}}

responseData: {"code": "03", "params": {"content": "keep learning", "token": "5e546324ba91858b26216d399dee33e1", "userid": 17, "titile": "xiaxiaoxu's blog"}}

requestData-4: {"content": "keep learning", "token": "5e546324ba91858b26216d399dee33e1", "userid": 17, "titile": "xiaxiaoxu's blog"}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: searchUserBlog

relyRule: {"token":"userLogin->1->response","userid":"userLogin->1->response"}

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'5e546324ba91858b26216d399dee33e1', u'code': u'00', u'userid': 17, u'login_time': u'2018-08-16 12:17:59'}

key:eval(command): token 5e546324ba91858b26216d399dee33e1

requestData-1: {'token': u'5e546324ba91858b26216d399dee33e1'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "5e546324ba91858b26216d399dee33e1", "code": "00", "userid": 17, "login_time": "2018-08-16 12:17:59"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'5e546324ba91858b26216d399dee33e1', u'code': u'00', u'userid': 17, u'login_time': u'2018-08-16 12:17:59'}

key:eval(command): userid 17

requestData-1: {'token': u'5e546324ba91858b26216d399dee33e1', 'userid': 17}

requestData-2: {"token": "5e546324ba91858b26216d399dee33e1", "userid": 17}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/getBlogsOfUser/ form {"token": "5e546324ba91858b26216d399dee33e1", "userid": 17}

#############response.text##############: {"data": [], "code": "00", "userid": 17}

responseData: {"data": [], "code": "00", "userid": 17}

requestData-4: {"token": "5e546324ba91858b26216d399dee33e1", "userid": 17}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: modify

文件截圖:

?

?

?

至此,實現了獲取請求數據,發送請求,把請求數據和響應數據寫入文件

下一步,處理接口結果的校驗,判斷接口返回數據是否正確

?

步驟7:校驗接口返回結果

在action包下新建check_result.py用于處理結果的校驗
check_result.py:

#encoding=utf-8

import re

?

class CheckResult(object):

??? def __init__(self):

??????? pass

?

??? @classmethod

??? def checkResult(cls,responseData,checkPoint):

??????? # {"code":"00","userid":{"value":"\w+"}, "articleId":{"type":"N"}}

??????? # responseObj ={"code": "01", "userid": 12, "id": "12"}

??????? errorKey={}

??????? for key,value in checkPoint.items():

??????????? if isinstance(value,(str,unicode)):

??????????????? #說明是等值校驗

??????????????? if responseData[key] != value:

??????????????????? errorKey[key] = responseData[key]

??????????? elif isinstance(value,dict):

??????????????? #說明是需要通過正則表達式去校驗

??????????????? sourceData=responseData[key]#接口返回的真實值

??????????????? if value.has_key("value"):

??????????????????? #說明是通過正則校驗

??????????????????? regStr=value["value"]

??????????????????? rg=re.match(regStr,"%s" %sourceData)

??????????????????? if not rg:

??????????????????????? errorKey[key] = sourceData

??????????????? elif value.has_key("type"):

??????????????????? #說明是校驗數據類型

??????????????????? typeStr=value["type"]

??????????????????? if typeStr == "N":

??????????????????????? #說明是整形

??????????????????????? if not isinstance(sourceData,(int,long)):

??????????????????????????? errorKey[key] = sourceData

??????? return errorKey

?

if __name__ == '__main__':

??? resouceData={"code":"01","userid":12,"id":"12"}

??? checkPoint={"code":"00","userid":{"type":"N","id":{"value":"\d+"}}}

??? print CheckResult.checkResult(resouceData,checkPoint)

?

?

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/action/check_result.py

{'code': '01'}

?

Process finished with exit code 0

?

修改主程序,添加寫入校驗結果部分
testScript.py:

#encoding=utf-8

import requests

import json

from util.ParseExcel import *

from util.httpClient import *

from config.config import *

from action.write_test_result import *

from action.check_result import *

def testInterface():

??? parseE = ParseExcel()

??? parseE.loadWorkBook(file_path)

??? sheetObj = parseE.getSheetByName(u"API")

??? activeList = parseE.getSingleColumn(sheetObj, API_ifExecute)

??? for idx, cell in enumerate(activeList[1:], 2):

??????? if cell.value == 'y':

??????????? rowObj = parseE.getSingleRow(sheetObj, idx)

??????????? apiName = rowObj[API_apiName - 1].value

??????????? requestUrl = rowObj[API_requestUrl - 1].value

??????????? requestMethod = rowObj[API_requestMethod - 1].value

??????????? paramsType = rowObj[API_paramsType - 1].value

??????????? apiTestCaseFileName = rowObj[API_apiCaseSheetName - 1].value

??????????? # print apiName,requestUrl,requestMethod,paramsType,apiTestCaseFileName

??????????? # 下一步讀sheet表,準備執行測試用例

??????????? print "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"

??????????? print "apiTestCaseFileName:", apiTestCaseFileName

??????????? caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)

??????????? caseActiveObj = parseE.getSingleColumn(caseSheetObj, CASE_ifExecute)

??????????? for c_idx, col in enumerate(caseActiveObj[1:], 2):

??????????????? if col.value == 'y':

??????????????????? caseRowObj = parseE.getSingleRow(caseSheetObj, c_idx)

??????????????????? relyRule = caseRowObj[CASE_relyRule - 1].value

??????????????????? checkPoint=json.loads(caseRowObj[CASE_checkPoint-1].value)

??????????????????? print "relyRule:", relyRule

?

??????????????????? if relyRule:

??????????????????????? # 發送接口請求之前,先獲取請求數據

??????????????????????? requestData = json.dumps(GetRequestData.getRequestData(eval(relyRule)))

??????????????????????? print "requestData-2:", requestData

?????????? ?????????else:

??????????????????????? requestData=caseRowObj[CASE_requestData-1].value

??????????????????????? print "requestData without relyRule:",requestData,type(requestData)

??????????????????? hc = HttpClient()

??????????????????? print "requestMethod, requestUrl, paramsType, requestData:"

??????????????????? print requestMethod, requestUrl, paramsType, requestData

??????????????????? response = hc.request(requestMethod=requestMethod,

???????????????????????????????????????????? requestUrl=requestUrl,

???????????????????????????????????????????? paramsType=paramsType,

???????????????????????????????????????????? requestData=requestData

???????????????????????????????????????????? )

??????????????????? print "#############response.text##############:",response.text

??????????????????? if response.status_code ==200:

??????????????????????? responseData=response.text

??????????????????????? print "responseData-1,type(responsedata-1):",responseData,type(responseData)

??????????????????????? errorKey=CheckResult.checkResult(json.loads(responseData),checkPoint)

??????????????????????? write_result(parseE,caseSheetObj,c_idx,requestData=str(requestData),responseData=str(responseData),errorKey=errorKey)

?

?

??????????????????? else:

??????????????????????? print "接口請求異常,狀態碼為:",response.status_code

??????????????? else:

??????????????????? print "接口用例被忽略執行"

??????? else:

??????????? print "API測試被忽略"

?

?

?

if __name__ == "__main__":

??? testInterface()

結果:ok

C:\Python27\python.exe D:/test/interfaceFramework_practice1/testScripts/testScript.py

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: register

relyRule: None

requestData without relyRule: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"} <type 'unicode'>

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/register/ form {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

#############response.text##############: {"username": "xufengchai6", "code": "01"}

responseData-1,type(responsedata-1): {"username": "xufengchai6", "code": "01"} <type 'unicode'>

requestData-4: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(requestData-4): <type 'str'>

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: login

relyRule: {"username":"userRegister->1->request","password":"userRegister->1->request"}

key:value==> username : userRegister->1->request

len(rList): 3

contentStr: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'xufengchai6', u'password': u'xufengchai121', u'email': u'xufengchai@qq.com'}

key:eval(command): username xufengchai6

requestData-1: {'username': u'xufengchai6'}

key:value==> password : userRegister->1->request

len(rList): 3

contentStr: {"username":"xufengchai6","password":"xufengchai121","email":"xufengchai@qq.com"}

type(contentStr): <type 'unicode'>

relyContent: {u'username': u'xufengchai6', u'password': u'xufengchai121', u'email': u'xufengchai@qq.com'}

key:eval(command): password xufengchai121

requestData-1: {'username': u'xufengchai6', 'password': '7f73a2e4d8b01b0f0f1062a59d4df635'}

requestData-2: {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/login/ form {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

#############response.text##############: {"token": "c7cf5ab52e674f2449f22579d294426d", "code": "00", "userid": 2, "login_time": "2018-08-17 21:27:10"}

responseData-1,type(responsedata-1): {"token": "c7cf5ab52e674f2449f22579d294426d", "code": "00", "userid": 2, "login_time": "2018-08-17 21:27:10"} <type 'unicode'>

requestData-4: {"username": "xufengchai6", "password": "7f73a2e4d8b01b0f0f1062a59d4df635"}

type(requestData-4): <type 'str'>

API測試被忽略

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

apiTestCaseFileName: searchUserBlog

relyRule: {"token":"userLogin->1->response","userid":"userLogin->1->response"}

key:value==> token : userLogin->1->response

len(rList): 3

contentStr: {"token": "c7cf5ab52e674f2449f22579d294426d", "code": "00", "userid": 2, "login_time": "2018-08-17 21:27:10"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'c7cf5ab52e674f2449f22579d294426d', u'code': u'00', u'userid': 2, u'login_time': u'2018-08-17 21:27:10'}

key:eval(command): token c7cf5ab52e674f2449f22579d294426d

requestData-1: {'token': u'c7cf5ab52e674f2449f22579d294426d'}

key:value==> userid : userLogin->1->response

len(rList): 3

contentStr: {"token": "c7cf5ab52e674f2449f22579d294426d", "code": "00", "userid": 2, "login_time": "2018-08-17 21:27:10"}

type(contentStr): <type 'unicode'>

relyContent: {u'token': u'c7cf5ab52e674f2449f22579d294426d', u'code': u'00', u'userid': 2, u'login_time': u'2018-08-17 21:27:10'}

key:eval(command): userid 2

requestData-1: {'token': u'c7cf5ab52e674f2449f22579d294426d', 'userid': 2}

requestData-2: {"token": "c7cf5ab52e674f2449f22579d294426d", "userid": 2}

requestMethod, requestUrl, paramsType, requestData:

post http://39.106.41.29:8080/getBlogsOfUser/ form {"token": "c7cf5ab52e674f2449f22579d294426d", "userid": 2}

#############response.text##############: {"data": [], "code": "00", "userid": 2}

responseData-1,type(responsedata-1): {"data": [], "code": "00", "userid": 2} <type 'unicode'>

requestData-4: {"token": "c7cf5ab52e674f2449f22579d294426d", "userid": 2}

type(requestData-4): <type 'str'>

API測試被忽略

?

Process finished with exit code 0

?

Excel結果:寫入請求數據、響應數據、結果ok

由于這種方式沒有用到responseCode和dataStore列,所以刪掉了,之后換種思路時會用到,到時再加上

?

?

轉載于:https://www.cnblogs.com/xiaxiaoxu/p/9523049.html

總結

以上是生活随笔為你收集整理的搭建接口自动化测试框架详细过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。