zoukankan      html  css  js  c++  java
  • 搭建接口自动化测试框架详细过程

     搭建接口自动化测试框架(文中接口数据来自于光荣之路)

    在设计接口测试框架前,先来弄清楚接口测试怎么进行的,请求和响应都是什么样的,清楚这些之后再进行下一步的操作。

    步骤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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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:Python27python.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: est_pythoninterfaceFramework>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:Python27python.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: est_pythoninterfaceFramework>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: est_pythoninterfaceFramework>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:Python27python.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:Python27python.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列,所以删掉了,之后换种思路时会用到,到时再加上

     

  • 相关阅读:
    pandas--对axis=0,axis=1的理解
    启动secondarynamenode时报错
    5月27日经历问题(在有框架的情况下从无到有增加一套功能)
    5.21工作记录(修改页面跳转,去掉多余的js;增加图片清除功能)
    工作记录520
    5月14日经历问题
    idea快捷键
    Linux下常用redis指令
    初识lunix
    Redis
  • 原文地址:https://www.cnblogs.com/xiaxiaoxu/p/9523049.html
Copyright © 2011-2022 走看看