python+requests接口自动化框架详解,没有比这个更详细的了

news2024/10/7 18:25:14

目录

为什么要做接口自动化框架

正常接口测试的流程是什么?

一、接口框架如下:

二、接口的数据规范设计---Case设计

2.1注册接口用例

2.2登录接口用例

三、创建utils包:用来存放公共的类

3.1 ParseExcel.py 操作封装excel的类(ParseExcel.py)

3.2 封装get/post请求(HttpClient.py)

3.3 封装MD5(md5_encrypt)

3.4 封装Log

3.5 封装发送Email类

四、 创建config包 用来存放公共的参数、配置文件、长时间不变的变量值

五、创建TestData目录,用来存放测试文件

六、创建action包,用来存放关键字函数

6.1 解决数据依赖 (GetRely.py)

6.2 解决数据存储(RelyDataStore.py)

6.3 校验数据结果(CheckResult.py)

6.4 往excel里面写结果

七、创建Log目录用来存放日志

八、主函数

总结:


为什么要做接口自动化框架

1、业务与配置的分离

2、数据与程序的分离;数据的变更不影响程序

3、有日志功能,实现无人值守

4、自动发送测试报告

5、不懂编程的测试人员也可以进行测试

正常接口测试的流程是什么?

确定接口测试使用的工具----->配置需要的接口参数----->进行测试----->检查测试结果----->生成测试报告

测试的工具:python+requests

接口测试用例:excel

一、接口框架如下:

 

1、action包:用来存放关键字函数

2、config包:用来存放配置文件

3、TestData:用来存放测试数据,excel表

4、Log包:用来存放日志文件

5、utils包:用来存放公共的类

6、运行主程序interface_auto_test.py

7、Readme.txt:告诉团队组员使用改框架需要注意的地方

 Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

 

二、接口的数据规范设计---Case设计

一个sheet对应数据库里面一张表

APIsheet存放
编号;从1开始
接口的名称(APIName);
请求的url(RequestUrl);
请求的方法(RequestMethod);
传参的方式(paramsType):post/get请求方法不一样
用例说明(APITestCase)
是否执行(Active)部分接口已测通,下次不用测试,直接把这里设置成N,跳过此接口

post与get的区别

查看post详情

post请求参数一般是json串,参数放在from表单里面;参数一般不可见,相对来说安全性高些

 

查看get详情

get请求参数一般直接放在url里面

 

2.1注册接口用例

RequestData:请求的数据
(开发制定的传参方式)
RelyData:数据依赖
ResponseCode:响应code
ResponseData:响应数据
DataStore:存储的依赖数据;如果存在数据库里面,在表里增加一个字段用来存依赖的数据
(存储的方式是编写接口自动化的人员来设定的存储方式)
CheckPoint:检查点
Active:是否执行
Status:执行用例的状态,方便查看用例是否执行成功
ErrorInfo:case运行失败,失败的错误信息;eg:是也本身的原因还是case设置失败,还是其他原因

2.2登录接口用例

RequestData:请求的数据
(开发制定的传参方式)
RelyData:数据依赖
(存储的方式是编写接口自动化的人员来设定的存储方式)
ResponseCode:响应code
ResponseData:响应数据
DataStore:存储的依赖数据;如果存在数据库里面,在表里增加一个字段用来存依赖的数据
(存储的方式是编写接口自动化的人员来设定的存储方式)
CheckPoint:检查点
Active:是否执行
Status:执行用例的状态,方便查看用例是否执行成功
ErrorInfo:case运行失败,失败的错误信息;eg:是也本身的原因还是case设置失败,还是其他原因

重点说明下RelyData:数据依赖
采取的是字典:key:value来存储数据格式;

{"request":{"username":"register->1","password":"register->1"},"response":{"code":"register->1"}}

格式化之后:

{
    "request":{
        "username":"register->1",
        "password":"register->1"
    },
    "response":{
        "code":"register->1"
    }
}

三、创建utils包:用来存放公共的类

3.1 ParseExcel.py 操作封装excel的类(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) # 设置字体的颜色
        # 颜色对应的RGB值
        self.RGBDict = {'red': 'FFFF3030', 'green': 'FF008B00'}

    def loadWorkBook(self, excelPathAndName):
        # 将excel文件加载到内存,并获取其workbook对象
        try:
            self.workbook = openpyxl.load_workbook(excelPathAndName)
        except Exception as err:
            raise err
        self.excelFile = excelPathAndName
        return self.workbook

    def getSheetByName(self, sheetName):
        # 根据sheet名获取该sheet对象
        try:
            # sheet = self.workbook.get_sheet_by_name(sheetName)
            sheet = self.workbook[sheetName]
            return sheet
        except Exception as err:
            raise err

    def getSheetByIndex(self, sheetIndex):
        # 根据sheet的索引号获取该sheet对象
        try:
            # sheetname = self.workbook.get_sheet_names()[sheetIndex]
            sheetname = self.workbook.sheetnames[sheetIndex]
        except Exception as err:
            raise err
        # sheet = self.workbook.get_sheet_by_name(sheetname)
        sheet = self.workbook[sheetname]
        return sheet

    def getRowsNumber(self, sheet):
        # 获取sheet中有数据区域的结束行号
        return sheet.max_row

    def getColsNumber(self, sheet):
        # 获取sheet中有数据区域的结束列号
        return sheet.max_column

    def getStartRowNumber(self, sheet):
        # 获取sheet中有数据区域的开始的行号
        return sheet.min_row

    def getStartColNumber(self, sheet):
        # 获取sheet中有数据区域的开始的列号
        return sheet.min_column

    def getRow(self, sheet, rowNo):
        # 获取sheet中某一行,返回的是这一行所有的数据内容组成的tuple,
        # 下标从1开始,sheet.rows[1]表示第一行
        try:
            rows = []
            for row in sheet.iter_rows():
                rows.append(row)
            return rows[rowNo - 1]
        except Exception as err:
            raise err

    def getColumn(self, sheet, colNo):
        # 获取sheet中某一列,返回的是这一列所有的数据内容组成tuple,
        # 下标从1开始,sheet.columns[1]表示第一列
        try:
            cols = []
            for col in sheet.iter_cols():
                cols.append(col)
            return cols[colNo - 1]
        except Exception as err:
            raise err

    def getCellOfValue(self, sheet, coordinate = None,
                       rowNo = None, colsNo = None):
        # 根据单元格所在的位置索引获取该单元格中的值,下标从1开始,
        # sheet.cell(row = 1, column = 1).value,
        # 表示excel中第一行第一列的值
        if coordinate != None:
            try:
                return sheet[coordinate]
            except Exception as err:
                raise err
        elif coordinate is None and rowNo is not None and \
                        colsNo is not None:
            try:
                return sheet.cell(row = rowNo, column = colsNo).value
            except Exception as err:
                raise err
        else:
            raise Exception("Insufficient Coordinates of cell !")

    def getCellOfObject(self, sheet, coordinate = None,
                        rowNo = None, colsNo = None):
        # 获取某个单元格的对象,可以根据单元格所在位置的数字索引,
        # 也可以直接根据excel中单元格的编码及坐标
        # 如getCellObject(sheet, coordinate = 'A1') or
        # getCellObject(sheet, rowNo = 1, colsNo = 2)
        if coordinate != None:
            try:
                # return sheet.cell(coordinate = coordinate)
                return sheet[coordinate]
            except Exception as err:
                raise err
        elif coordinate == None and rowNo is not None and \
                        colsNo is not None:
            try:
                return sheet.cell(row = rowNo,column = colsNo)
            except Exception as err:
                raise err
        else:
            raise Exception("Insufficient Coordinates of cell !")

    def writeCell(self, sheet, content, coordinate = None,
        rowNo = None, colsNo = None, style = None):
        #根据单元格在excel中的编码坐标或者数字索引坐标向单元格中写入数据,
        # 下标从1开始,参style表示字体的颜色的名字,比如red,green
        if coordinate is not None:
            try:
                # sheet.cell(coordinate = coordinate).value = content
                sheet[coordinate] = content
                if style is not None:
                    sheet[coordinate].\
                        font = Font(color = self.RGBDict[style])
                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e
        elif coordinate == None and rowNo is not None and \
                        colsNo is not None:
            try:
                sheet.cell(row = rowNo,column = colsNo).value = content
                if style:
                    sheet.cell(row = rowNo,column = colsNo).\
                        font = Font(color = self.RGBDict[style])
                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e
        else:
            raise Exception("Insufficient Coordinates of cell !")

    def writeCellCurrentTime(self, sheet, coordinate = None,
                rowNo = None, colsNo = None):
        # 写入当前的时间,下标从1开始
        now = int(time.time())  #显示为时间戳
        timeArray = time.localtime(now)
        currentTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        if coordinate is not None:
            try:
                sheet.cell(coordinate = coordinate).value = currentTime
                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e
        elif coordinate == None and rowNo is not None \
                and colsNo is not None:
            try:
                sheet.cell(row = rowNo, column = colsNo
                        ).value = currentTime
                self.workbook.save(self.excelFile)
            except Exception as e:
                raise e
        else:
            raise Exception("Insufficient Coordinates of cell !")

if __name__ == '__main__':
    # 测试代码
    pe = ParseExcel()
    pe.loadWorkBook(r'D:\ProgramSourceCode\Python Source Code\WorkSpace\InterfaceFrame2018\inter_test_data.xlsx')
    sheetObj = pe.getSheetByName(u"API")
    print("通过名称获取sheet对象的名字:", sheetObj.title)
    # print help(sheetObj.rows)
    print("通过index序号获取sheet对象的名字:", pe.getSheetByIndex(0).title)
    sheet = pe.getSheetByIndex(0)
    print(type(sheet))
    print(pe.getRowsNumber(sheet))  #获取最大行号
    print(pe.getColsNumber(sheet))  #获取最大列号
    rows = pe.getRow(sheet, 1)  #获取第一行
    for i in rows:
        print(i.value)
    # # 获取第一行第一列单元格内容
    # print pe.getCellOfValue(sheet, rowNo = 1, colsNo = 1)
    # pe.writeCell(sheet, u'我爱祖国', rowNo = 10, colsNo = 10)
    # pe.writeCellCurrentTime(sheet, rowNo = 10, colsNo = 11)

3.2 封装get/post请求(HttpClient.py)

import requests
import json

class HttpClient(object):
    def __init__(self):
        pass

    def request(self, requestMethod, requestUrl, paramsType,
                requestData, headers =None, **kwargs):
        if requestMethod == "post":
            print("---", requestData, type(requestData))
            if paramsType == "form":
                response = self.__post(url = requestUrl, data = json.dumps(eval(requestData)),
                                  headers = headers, **kwargs)
                return response
            elif paramsType == "json":
                response = self.__post(url = requestUrl, json = json.dumps(eval(requestData)),
                                  headers = headers, **kwargs)
                return response
        elif requestMethod == "get":
            request_url = requestUrl
            if paramsType == "url":
                request_url = "%s%s" %(requestUrl, requestData)
            response = self.__get(url = request_url, params = requestData, **kwargs)
            return response

    def __post(self, url, data = None, json = None, headers=None,**kwargs):
        print("----")
        response = requests.post(url=url, data = data, json=json, headers=headers)
        return response

    def __get(self, url, params = None, **kwargs):
        response = requests.get(url, params = params, **kwargs)
        return response

if __name__ == "__main__":
    hc = HttpClient()
    res = hc.request("get", "http://39.106.41.11:8080/getBlogContent/", "url",'2')
    print(res.json())

3.3 封装MD5(md5_encrypt)

import hashlib

def md5_encrypt(text):
    m5 = hashlib.md5()
    m5.update(text.encode("utf-8"))
    value = m5.hexdigest()
    return value

if __name__ == "__main__":
    print(md5_encrypt("sfwe"))

3.4 封装Log

import logging
import logging.config
from config.public_data import baseDir

# 读取日志配置文件
logging.config.fileConfig(baseDir + "\config\Logger.conf")
# 选择一个日志格式
logger = logging.getLogger("example02")#或者example01

def debug(message):
    # 定义dubug级别日志打印方法
    logger.debug(message)

def info(message):
    # 定义info级别日志打印方法
    logger.info(message)

def warning(message):
    # 定义warning级别日志打印方法
    logger.warning(message)

3.5 封装发送Email类

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from ProjVar.var import *

import os
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from email.utils import formataddr

def send_mail():
    mail_host="smtp.qq.com"  #设置服务器
    mail_user="xiangxiang"    #用户名
    mail_pass="cmxx"   #口令
    sender = 'cm2019@126.com'
    receivers = ['672014873@qq.com',"cm2019@126.com"] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
    # 创建一个带附件的实例
    message = MIMEMultipart()
    message['From'] = formataddr(["自动化测试", "cm2019@126.com"])
    message['To'] = ','.join(receivers)
    subject = '自动化测试执行报告'
    message['Subject'] = Header(subject, 'utf-8')
    message["Accept-Language"]="zh-CN"
    message["Accept-Charset"]="ISO-8859-1,utf-8,gbk"
    # 邮件正文内容
    message.attach(MIMEText('最新执行的自动化测试报告,请参阅附件内容!', 'plain', 'utf-8'))

    # 构造附件1,传送测试结果的excel文件
    att = MIMEBase('application', 'octet-stream')
    att.set_payload(open(ProjDirPath+"\\testdata\\testdata.xlsx", 'rb').read())
    att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', "自动化测试报告.xlsx"))
    encoders.encode_base64(att)
    message.attach(att)
    """
    # 构造附件2,传送当前目录下的 runoob.txt 文件
    att2 = MIMEText(open('e:\\a.py','rb').read(), 'base64', 'utf-8')
    att2["Content-Type"] = 'application/octet-stream'
    att2["Content-Disposition"] = 'attachment; filename="a.py"'
    message.attach(att2)
    """
    try:
        smtpObj = smtplib.SMTP(mail_host)
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, message.as_string())
        print("邮件发送成功")
    except smtplib.SMTPException as e:
        print("Error: 无法发送邮件", e)

if __name__ == "__main__":
    send_mail()

 Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

        

 

四、 创建config包 用来存放公共的参数、配置文件、长时间不变的变量值

创建public_data.py

import os
# 整个项目的根目录绝对路劲
baseDir = os.path.dirname(os.path.dirname(__file__))

# 获取测试数据文件的绝对路径
file_path = baseDir + "/TestData/inter_test_data.xlsx"

API_apiName = 2
API_requestUrl = 3
API_requestMothod = 4
API_paramsType = 5
API_apiTestCaseFileName = 6
API_active = 7

CASE_requestData = 1
CASE_relyData = 2
CASE_responseCode = 3
CASE_responseData = 4
CASE_dataStore = 5
CASE_checkPoint = 6
CASE_active = 7
CASE_status = 8
CASE_errorInfo = 9

# 存储请求参数里面依赖的数据
REQUEST_DATA = {}

# 存储响应对象中的依赖数据
RESPONSE_DATA = {}

if __name__=="__main__":
    print(file_path)
    print(baseDir)

五、创建TestData目录,用来存放测试文件

inter_test_data.xlsx

六、创建action包,用来存放关键字函数

6.1 解决数据依赖 (GetRely.py)

from config.public_data import REQUEST_DATA, RESPONSE_DATA
from utils.md5_encrypt import md5_encrypt

REQUEST_DATA = {"用户注册":{"1":{"username":"zhangsan", "password":"dfsdf23"},
                        "headers":{"cookie":"asdfwerw"}}}
RESPONSE_DATA = {"用户注册":{"1":{"code":"00"}, "headers":{"age":2342}}}

class GetRely(object):
    def __init__(self):
        pass

    @classmethod
    def get(self, dataSource, relyData, headSource = {}):
        print(type(dataSource))
        print(dataSource)
        data = dataSource.copy()
        for key, value in relyData.items():
            if key == "request":
                #说明应该去REQUEST_DATA中获取
                for k, v in value.items():
                    interfaceName, case_idx = v.split("->")
                    val = REQUEST_DATA[interfaceName][case_idx][k]
                    if k == "password":
                        data[k] = md5_encrypt(val)
                    else:
                        data[k] = val
            elif key == "response":
                # 应该去RESPONSE_DATA中获取
                for k, v in value.items():
                    interfaceName, case_idx = v.split("->")
                    data[k] = RESPONSE_DATA[interfaceName][case_idx][k]
            elif key == "headers":
                if headSource:
                    for key, value in value.items():
                        if key == "request":
                            for k, v in value.items():
                                for i in v:
                                    headSource[i] = REQUEST_DATA[k]["headers"][i]
                        elif key == "response":
                            for i, val in value.items():
                                for j in val:
                                    headSource[j] = RESPONSE_DATA[i]["headers"][j]
        return "%s" %data

if __name__ == "__main__":
    s = {"username": "", "password": "","code":""}
    h = {"cookie":"123", "age":332}
    rely = {"request": {"username": "用户注册->1", "password": "用户注册->1"},
            "response":{"code":"用户注册->1"},
            "headers":{"request":{"用户注册":["cookie"]},"response":{"用户注册":["age"]}}
            }
    print(GetRely.get(s, rely, h))

6.2 解决数据存储(RelyDataStore.py)

from config.public_data import RESPONSE_DATA, REQUEST_DATA

class RelyDataStore(object):
    def __init__(self):
        pass

    @classmethod
    def do(cls, storePoint, apiName, caseId, request_source = {}, response_source = {}, req_headers={}, res_headers = {}):
        for key, value in storePoint.items():
            if key == "request":
                # 说明需要存储的依赖数据来自请求参数,应该将数据存储到REQUEST_DATA
                for i in value:
                    if i in request_source:
                        val = request_source[i]
                        if apiName not in REQUEST_DATA:
                            # 说明存储数据的结构还未生成,需要指明数据存储结构
                            REQUEST_DATA[apiName]={str(caseId): {i: val}}
                        else:
                            #说明存储数据结构中最外层结构已存在
                            if str(caseId) in REQUEST_DATA[apiName]:
                                REQUEST_DATA[apiName][str(caseId)][i] = val
                            else:
                                # 说明内层结构不完整,需要指明完整的结构
                                REQUEST_DATA[apiName][str(caseId)] = {i: val}
                    else:
                        print("请求参数中不存在字段" + i)
            elif key == "response":
                #说明需要存储的依赖数据来自接口的响应body,应该将数据存储到RESPONSE_DATA
                for j in value:
                    if j in response_source:
                        val = response_source[j]
                        if apiName not in RESPONSE_DATA:
                            # 说明存储数据的结构还未生成,需要指明数据存储结构
                            RESPONSE_DATA[apiName]={str(caseId): {j: val}}
                        else:
                            #说明存储数据结构中最外层结构已存在
                            if str(caseId) in RESPONSE_DATA[apiName]:
                                RESPONSE_DATA[apiName][str(caseId)][j] = val
                            else:
                                # 说明内层结构不完整,需要指明完整的结构
                                RESPONSE_DATA[apiName][str(caseId)] = {j: val}
                    else:
                        print("接口的响应body中不存在字段" + j)
            elif key == "headers":
                for k, v in value.items():
                    if k == "request":
                        # 说明需要往REQUEST_DATA变量中写入存储数据
                        for item in v:
                            if item in req_headers:
                                header = req_headers[item]
                                if "headers" in REQUEST_DATA[apiName]:
                                    REQUEST_DATA[apiName]["headers"][item] = header
                                else:
                                    REQUEST_DATA[apiName]["headers"] = {item: header}
                    elif k == "response":
                        # 说明需要往RESPONSE_DATA变量中写入存储数据
                        for it in v:
                            if it in res_headers:
                                header = res_headers[it]
                                if "headers" in RESPONSE_DATA[apiName]:
                                    RESPONSE_DATA[apiName]["headers"][it] = header
                                else:
                                    RESPONSE_DATA[apiName]["headers"] = {item: header}
        print(REQUEST_DATA)
        print(RESPONSE_DATA)

if __name__ == "__main__":
    r = {"username": "srwcx01", "password": "wcx123wac1", "email": "wcx@qq.com"}
    req_h = {"cookie":"csdfw23"}
    res_h = {"age":597232}
    s = {"request": ["username", "password"], "response": ["userid"],"headers":{"request":["cookie"],
        "response":["age"]}}
    res = {"userid": 12, "code": "00"}
    RelyDataStore.do(s, "register", 1, r, res, req_headers=req_h, res_headers=res_h)
    print(REQUEST_DATA)
    print(RESPONSE_DATA)

6.3 校验数据结果(CheckResult.py)

import re

class CheckResult(object):
    def __init__(self):
        pass

    @classmethod
    def check(self, responseObj, checkPoint):
        responseBody = responseObj.json()
        # responseBody = {"code": "", "userid": 12, "id": "12"}
        errorKey = {}
        for key, value in checkPoint.items():
            if key in responseBody:
                if isinstance(value, (str, int)):
                    # 等值校验
                    if responseBody[key] != value:
                        errorKey[key] = responseBody[key]
                elif isinstance(value, dict):
                    sourceData = responseBody[key]
                    if "value" in value:
                        # 模糊匹配校验
                        regStr = value["value"]
                        rg = re.match(regStr, "%s" %sourceData)
                        if not rg:
                            errorKey[key] = sourceData
                    elif "type" in value:
                        # 数据类型校验
                        typeS = value["type"]
                        if typeS == "N":
                            # 说明是整形校验
                            if not isinstance(sourceData, int):
                                errorKey[key] = sourceData
            else:
                errorKey[key] = "[%s] not exist" %key
        return errorKey

if __name__ == "__main__":
    r = {"code": "00", "userid": 12, "id": 12}
    c = {"code": "00", "userid": {"type": "N"}, "id": {"value": "\d+"}}
    print(CheckResult.check(r, c))

6.4 往excel里面写结果

from config.public_data import *

def write_result(wbObj, sheetObj, responseData, errorKey, rowNum):
    try:
        # 写响应body
        wbObj.writeCell(sheetObj, content="%s" %responseData,
                        rowNo = rowNum, colsNo=CASE_responseData)
        # 写校验结果状态及错误信息
        if errorKey:
            wbObj.writeCell(sheetObj, content="%s" %errorKey,
                        rowNo=rowNum, colsNo=CASE_errorInfo)
            wbObj.writeCell(sheetObj, content="faild",
                            rowNo=rowNum, colsNo=CASE_status, style="red")
        else:
            wbObj.writeCell(sheetObj, content="pass",
                            rowNo=rowNum, colsNo=CASE_status, style="green")
    except Exception as err:
        raise err

如果对软件测试、接口测试、自动化测试、面试经验交流。感兴趣可以加软件测试交流:1085991341,还会有同行一起技术交流。

七、创建Log目录用来存放日志

八、主函数

#encoding=utf-8
import requests
import json
from action.get_rely import GetRely
from config.public_data import *
from utils.ParseExcel import ParseExcel
from utils.HttpClient import HttpClient
from action.data_store import RelyDataStore
from action.check_result import CheckResult
from action.write_result import write_result
from utils.Log import *

def main():
    parseE = ParseExcel()
    parseE.loadWorkBook(file_path)
    sheetObj = parseE.getSheetByName("API")
    activeList = parseE.getColumn(sheetObj, API_active)
    for idx, cell in enumerate(activeList[1:], 2):
        if cell.value == "y":
            #需要被执行
            RowObj = parseE.getRow(sheetObj, idx)
            apiName = RowObj[API_apiName -1].value
            requestUrl = RowObj[API_requestUrl - 1].value
            requestMethod = RowObj[API_requestMothod - 1].value
            paramsType = RowObj[API_paramsType - 1].value
            apiTestCaseFileName = RowObj[API_apiTestCaseFileName - 1].value

            # 下一步读取用例sheet表,准备执行测试用例
            caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)
            caseActiveObj = parseE.getColumn(caseSheetObj, CASE_active)
            for c_idx, col in enumerate(caseActiveObj[1:], 2):
                if col.value == "y":
                    #需要执行的用例
                    caseRowObj = parseE.getRow(caseSheetObj, c_idx)
                    requestData = caseRowObj[CASE_requestData - 1].value
                    relyData = caseRowObj[CASE_relyData - 1].value
                    responseCode = caseRowObj[CASE_responseCode - 1].value
                    responseData = caseRowObj[CASE_responseData - 1].value
                    dataStore = caseRowObj[CASE_dataStore -1].value
                    checkPoint = caseRowObj[CASE_checkPoint - 1].value

                    #发送接口请求之前需要做一下数据依赖的处理
                    if relyData:
                        logging.info("处理第%s个接口的第%s条用例的数据依赖!")
                        requestData = GetRely.get(eval(requestData), eval(relyData))
                    httpC = HttpClient()
                    response = httpC.request(requestMethod=requestMethod,
                                             requestData=requestData,
                                             requestUrl=requestUrl,
                                             paramsType=paramsType
                                             )
                    # 获取到响应结果后,接下来进行数据依赖存储逻辑实现
                    if response.status_code == 200:
                        responseData = response.json()
                        # 进行依赖数据存储
                        if dataStore:
                            RelyDataStore.do(eval(dataStore), apiName, c_idx - 1, eval(requestData), responseData)
                        # 接下来就是校验结果
                        else:
                            logging.info("接口【%s】的第【%s】条用例,不需要进行依赖数据存储!" %(apiName, c_idx))
                        if checkPoint:
                            errorKey = CheckResult.check(response, eval(checkPoint))
                            write_result(parseE, caseSheetObj, responseData, errorKey, c_idx)
                    else:
                        logging.info("接口【%s】的第【%s】条用例,执行失败,接口协议code非200!" %(apiName, c_idx))
                else:
                    logging.info("第%s个接口的第%s条用例,被忽略执行!" %(idx -1, c_idx-1))
        else:
            logging.info("第%s行的接口被忽略执行!" %(idx -1))

if __name__=="__main__":
    main()

总结:

感谢每一个认真阅读我文章的人!!!

我个人整理了我这几年软件测试生涯整理的一些技术资料,包含:电子书,简历模块,各种工作模板,面试宝典,自学项目等。欢迎大家点击下方名片免费领取,千万不要错过哦。

 Python自动化测试学习交流群:全套自动化测试面试简历学习资料获取点击链接加入群聊【python自动化测试交流】:http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DhOSZDNS-qzT5QKbFQMsfJ7DsrFfKpOF&authKey=eBt%2BF%2FBK81lVLcsLKaFqnvDAVA8IdNsGC7J0YV73w8V%2FJpdbby66r7vJ1rsPIifg&noverify=0&group_code=198408628

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/662993.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI工具】-Stable Diffusion本地化部署教程

前言 今天我们要介绍的是时下最流行的AI绘图软件Stable Diffusion,虽然Diffusion.ai已经开放api,但是长时间的商业化调用我们需要购买很多的金币。所以我们需要找一个平替的AI绘图平台,现在主流市场中AI绘图软件主要就是OpenAI的DALLE、midj…

SSM会议管理系统

SSM会议管理系统 后端基于SSM、前端基于Freemarker写的会议管理系统、使用JDK8、mysql使用5.7版本 技术栈 Spring SpringMVC MyBatis Mysql Freemarker jqueryajax[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGo0luHu-1687163482019)(img.png)] …

【Python 随练】打印水仙花数

题目: 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数 简介: 在本篇博客中,我们将解决一个经典的数学问题:打印出所有的水仙花数。水仙花数是指一…

Unity核心5——Tilemap

Tilemap 一般称之为瓦片地图或者平铺地图,是 Unity2017 中新增的功能,主要用于快速编辑 2D 游戏中的场景,通过复用资源的形式提升地图多样性 ​ 工作原理就是用一张张的小图排列组合为一张大地图 ​ 它和 SpriteShape 的异同 共同点&#x…

浅析GPT2中的autoregressive和BERT的autoencoding源码实现

经常使用BERT来做研究,因此对Encoder的架构较为熟悉,但是从来没有了解过GPT这样的Decoder架构,尤其对自回归的形式不知道源码是如何实现的。 为了方便对比和讨论,接来下所探讨的源码都是基于HuggingFace这个框架的。 Bert注意力…

基于亚马逊云科技Serverless,朝夕光年和Second Dinner携手打造年度手游

经典的漫威IP,酷炫的卡牌对战,丰富的故事情节,这款移动游戏《MARVEL SNAP》一经上线就深得全球玩家喜爱。在The Game Awards 2022的年度颁奖典礼上,它更是以出色的表现,一举斩获最佳移动游戏奖项。 其研发公司Second …

【ElasticSearch】中文分词器

ES默认的analyzer(分词器),对英文单词比较友好,对中文分词效果不好。不过ES支持安装分词插件,增加新的分词器。 1、如何指定analyzer? 默认的分词器不满足需要,可以在定义索引映射的时候&#…

Python自动办公之合并多个PDF文件

本文基于使用pycharm平台,使用glob库和PyPDF2库实现 首先将需要合并的文件放于一个文件中 如下图 addpdf文件夹为需要合并的文件位置 good.py为代码块 代码如下 print(这个小代码仅仅用于合并pdf文件数量小于10的情况) print() from PyPDF2 import PdfMerger,P…

深度解析DuckDB的ScheduleEvents

深度解析DuckDB的ScheduleEvents 1.ScheduleEventData2.ScheduleEventsInternal3.SchedulePipeline 3.1 Event3.2 PipelineEventStack3.3 主逻辑4.可视化总结 书接上回熬夜三晚之深度解析DuckDB MetaPipeline,MetaPipeline在初始化的时候会构建出下面几个&#xff1…

【ARMv8/v9 异常模型入门及渐进2 - 系统控制寄存器 SCTRL_ELx 介绍】

文章目录 SCTRL_ELx 介绍背景ARMv8 SCTLR_ELx 介绍ARMv9 SCTLR_ELx 介绍 SCTRL_ELx 介绍背景 由于在做DFD 测试过程中需要测试 EL1 状态下的 self-hosted trace 功能,但是这个测试是在UEFI中做的,在开发验证阶段UEFI默认是运行在EL3 下的,所…

mac安装VsCode遇到的问题

万事开头难,头一次在安装生产工具的时候,就遇到了这么棘手的问题。百度和Google都试过了,网上的所有方式对我都没效果。最终自己阴差阳错解决了,我看内外网反馈这个问题的还挺多,在这里记录一下,希望可以帮…

Docker专题系列之十三:docker容器内安装vim编辑器

在使用docker时,有时候我们需要编辑配置文件,需要使用vim或者vi命令,但是会发现: root20ab69bedcdb:/etc/mysql# vim my.cnf bash: vim: command not found这是因为vim没有安装,使用如下命令安装: apt-ge…

Tomcat架构设计

Servlet规范 Servlet是JavaEE规范中的一种,主要是为了扩展Java作为Web服务的功能,统一定义了对应的接口,如Servlet接口,HttpRequest接口,HttpResponse接口,Filter接口。然后由具体的服务厂商来实现这些接口…

adroit java反编译

环境准备 靶机链接:百度网盘 请输入提取码 提取码:4e5y 虚拟机网络链接模式:桥接模式 攻击机系统:kali linux 2021.1 信息收集 1.探测目标靶机ip地址 arp-scan -l 2.用nmap探测靶机开放端口和服务情况 nmap -p- -A -T4 19…

二分类结局变量Logistic回归临床模型预测—— 模型评价(一)

本节讲的是二分类结局变量的临床模型预测,与之前讲的Cox回归不同,https://lijingxian19961016.blog.csdn.net/article/details/124088364https://lijingxian19961016.blog.csdn.net/article/details/124088364https://lijingxian19961016.blog.csdn.net/article/details/1240…

基于springboot+Redis的前后端分离项目(二)-【黑马点评】

🎁🎁资源文件分享 链接:https://pan.baidu.com/s/1189u6u4icQYHg_9_7ovWmA?pwdeh11 提取码:eh11 商户查询缓存,缓存更新策略,缓存穿透 商户查询缓存a.什么是缓存1.为什么要使用缓存2.如何使用缓存 b.添加商…

一文读懂ISM频段

ISM(工业、科学、医疗)频段为国际电信联盟(ITU)《无线电规则》定义的指定无线电频段。这些频段是为电信之外的其他射频用途挪出的频段。因此, ISM频段虽然理论上可用于电信用途,但使用ISM频段的电信设备必须…

南卡OE Pro开放式耳机开售,将音质和舒适度提升至行业巅峰!

随着科技的不断发展和创新,开放式耳机作为一种全新的音频体验方式正逐渐走红。而在这个充满竞争的市场上,南卡品牌的最新款OE Pro开放式耳机如今上市,以其出色的表现和全能的功能成为行业的颠覆者。 南卡品牌在骨传导耳机音频技术领域有着超过…

【系统开发】尚硅谷 - 谷粒商城项目笔记(三):OSS阿里云存储

文章目录 OSS阿里云存储OSS基础配置OSS跨域设置原生sdk方式上传阿里云sdk方式上传将oss配置加入nacos加入网关的路由分发和前端整合测试 OSS阿里云存储 OSS基础配置 上传的账号信息存储在应用服务器 上传前先找应用服务器要一个policy上传策略,生成防伪签名 OSS跨…

帮助中心的设计指南

帮助中心是一个网站或应用程序的重要组成部分,因为它可以让用户轻松找到他们需要的信息。正确设计和实施一个高效的帮助中心可以确保用户满意度提高,并增加品牌忠诚度。本文将介绍如何设计一个优秀的帮助中心。 确定帮助中心的目标 在设计帮助中心之前&…