搭建接口自動化測試框架詳細過程

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

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

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

 

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

接口返回code說明:python

'00' : 成功正則表達式

'01':用戶已存在數據庫

'02':參數不合法json

'03':參數錯誤(一、用戶信息錯誤 二、參數錯誤,數據庫中不存在相應數據)api

'999':未知錯誤,看後臺日誌服務器

 

一、用戶註冊

 

 

參數規則說明:cookie

username:框架

一、必須字母和數字組成dom

二、長度2~20位編輯器

三、字母不區分大小寫

 

password:

一、長度8~20位

二、必須含有字母和數字

 

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用於後續處理博文的用戶標識

二、用戶登陸

 

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等信息

三、新增博文

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

 

 

四、查詢用戶的博文

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

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

 

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

 

 

 

五、修改博文

 

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,表示更新時間

 

六、查詢博文內容

請求地址示例:

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

 

七、批量查詢博文

請求地址示例:

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

 

八、刪除博文

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列,因此刪掉了,以後換種思路時會用到,到時再加上

 

相關文章
相關標籤/搜索