欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python+requests接口自動(dòng)化框架的實(shí)現(xiàn)

 更新時(shí)間:2020年08月31日 09:26:13   作者:風(fēng)聲~~  
這篇文章主要介紹了python+requests接口自動(dòng)化框架的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

為什么要做接口自動(dòng)化框架

1、業(yè)務(wù)與配置的分離

2、數(shù)據(jù)與程序的分離;數(shù)據(jù)的變更不影響程序

3、有日志功能,實(shí)現(xiàn)無(wú)人值守

4、自動(dòng)發(fā)送測(cè)試報(bào)告

5、不懂編程的測(cè)試人員也可以進(jìn)行測(cè)試

正常接口測(cè)試的流程是什么?

確定接口測(cè)試使用的工具----->配置需要的接口參數(shù)----->進(jìn)行測(cè)試----->檢查測(cè)試結(jié)果----->生成測(cè)試報(bào)告

測(cè)試的工具:python+requests

接口測(cè)試用例:excel

一、接口框架如下:

1、action包:用來(lái)存放關(guān)鍵字函數(shù)

2、config包:用來(lái)存放配置文件

3、TestData:用來(lái)存放測(cè)試數(shù)據(jù),excel表

4、Log包:用來(lái)存放日志文件

5、utils包:用來(lái)存放公共的類

6、運(yùn)行主程序interface_auto_test.py

7、Readme.txt:告訴團(tuán)隊(duì)組員使用改框架需要注意的地方

二、接口的數(shù)據(jù)規(guī)范設(shè)計(jì)---Case設(shè)計(jì)

一個(gè)sheet對(duì)應(yīng)數(shù)據(jù)庫(kù)里面一張表

APIsheet存放
編號(hào);從1開始
接口的名稱(APIName);
請(qǐng)求的url(RequestUrl);
請(qǐng)求的方法(RequestMethod);
傳參的方式(paramsType):post/get請(qǐng)求方法不一樣
用例說(shuō)明(APITestCase)
是否執(zhí)行(Active)部分接口已測(cè)通,下次不用測(cè)試,直接把這里設(shè)置成N,跳過(guò)此接口

post與get的區(qū)別

查看post詳情

post請(qǐng)求參數(shù)一般是json串,參數(shù)放在from表單里面;參數(shù)一般不可見,相對(duì)來(lái)說(shuō)安全性高些

查看get詳情

get請(qǐng)求參數(shù)一般直接放在url里面

2.1注冊(cè)接口用例

RequestData:請(qǐng)求的數(shù)據(jù)
(開發(fā)制定的傳參方式)
RelyData:數(shù)據(jù)依賴
ResponseCode:響應(yīng)code
ResponseData:響應(yīng)數(shù)據(jù)
DataStore:存儲(chǔ)的依賴數(shù)據(jù);如果存在數(shù)據(jù)庫(kù)里面,在表里增加一個(gè)字段用來(lái)存依賴的數(shù)據(jù)
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
CheckPoint:檢查點(diǎn)
Active:是否執(zhí)行
Status:執(zhí)行用例的狀態(tài),方便查看用例是否執(zhí)行成功
ErrorInfo:case運(yùn)行失敗,失敗的錯(cuò)誤信息;eg:是也本身的原因還是case設(shè)置失敗,還是其他原因

2.2登錄接口用例

RequestData:請(qǐng)求的數(shù)據(jù)
(開發(fā)制定的傳參方式)
RelyData:數(shù)據(jù)依賴
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
ResponseCode:響應(yīng)code
ResponseData:響應(yīng)數(shù)據(jù)
DataStore:存儲(chǔ)的依賴數(shù)據(jù);如果存在數(shù)據(jù)庫(kù)里面,在表里增加一個(gè)字段用來(lái)存依賴的數(shù)據(jù)
(存儲(chǔ)的方式是編寫接口自動(dòng)化的人員來(lái)設(shè)定的存儲(chǔ)方式)
CheckPoint:檢查點(diǎn)
Active:是否執(zhí)行
Status:執(zhí)行用例的狀態(tài),方便查看用例是否執(zhí)行成功
ErrorInfo:case運(yùn)行失敗,失敗的錯(cuò)誤信息;eg:是也本身的原因還是case設(shè)置失敗,還是其他原因

重點(diǎn)說(shuō)明下RelyData:數(shù)據(jù)依賴
采取的是字典:key:value來(lái)存儲(chǔ)數(shù)據(jù)格式;
{"request":{"username":"register->1","password":"register->1"},"response":{"code":"register->1"}}

格式化之后:

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

三、創(chuàng)建utils包:用來(lái)存放公共的類

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) # 設(shè)置字體的顏色
    # 顏色對(duì)應(yīng)的RGB值
    self.RGBDict = {'red': 'FFFF3030', 'green': 'FF008B00'}

  def loadWorkBook(self, excelPathAndName):
    # 將excel文件加載到內(nèi)存,并獲取其workbook對(duì)象
    try:
      self.workbook = openpyxl.load_workbook(excelPathAndName)
    except Exception as err:
      raise err
    self.excelFile = excelPathAndName
    return self.workbook

  def getSheetByName(self, sheetName):
    # 根據(jù)sheet名獲取該sheet對(duì)象
    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):
    # 根據(jù)sheet的索引號(hào)獲取該sheet對(duì)象
    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中有數(shù)據(jù)區(qū)域的結(jié)束行號(hào)
    return sheet.max_row

  def getColsNumber(self, sheet):
    # 獲取sheet中有數(shù)據(jù)區(qū)域的結(jié)束列號(hào)
    return sheet.max_column

  def getStartRowNumber(self, sheet):
    # 獲取sheet中有數(shù)據(jù)區(qū)域的開始的行號(hào)
    return sheet.min_row

  def getStartColNumber(self, sheet):
    # 獲取sheet中有數(shù)據(jù)區(qū)域的開始的列號(hào)
    return sheet.min_column

  def getRow(self, sheet, rowNo):
    # 獲取sheet中某一行,返回的是這一行所有的數(shù)據(jù)內(nèi)容組成的tuple,
    # 下標(biāo)從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中某一列,返回的是這一列所有的數(shù)據(jù)內(nèi)容組成tuple,
    # 下標(biāo)從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):
    # 根據(jù)單元格所在的位置索引獲取該單元格中的值,下標(biāo)從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):
    # 獲取某個(gè)單元格的對(duì)象,可以根據(jù)單元格所在位置的數(shù)字索引,
    # 也可以直接根據(jù)excel中單元格的編碼及坐標(biāo)
    # 如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):
    #根據(jù)單元格在excel中的編碼坐標(biāo)或者數(shù)字索引坐標(biāo)向單元格中寫入數(shù)據(jù),
    # 下標(biāo)從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):
    # 寫入當(dāng)前的時(shí)間,下標(biāo)從1開始
    now = int(time.time()) #顯示為時(shí)間戳
    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__':
  # 測(cè)試代碼
  pe = ParseExcel()
  pe.loadWorkBook(r'D:\ProgramSourceCode\Python Source Code\WorkSpace\InterfaceFrame2018\inter_test_data.xlsx')
  sheetObj = pe.getSheetByName(u"API")
  print("通過(guò)名稱獲取sheet對(duì)象的名字:", sheetObj.title)
  # print help(sheetObj.rows)
  print("通過(guò)index序號(hào)獲取sheet對(duì)象的名字:", pe.getSheetByIndex(0).title)
  sheet = pe.getSheetByIndex(0)
  print(type(sheet))
  print(pe.getRowsNumber(sheet)) #獲取最大行號(hào)
  print(pe.getColsNumber(sheet)) #獲取最大列號(hào)
  rows = pe.getRow(sheet, 1) #獲取第一行
  for i in rows:
    print(i.value)
  # # 獲取第一行第一列單元格內(nèi)容
  # print pe.getCellOfValue(sheet, rowNo = 1, colsNo = 1)
  # pe.writeCell(sheet, u'我愛祖國(guó)', rowNo = 10, colsNo = 10)
  # pe.writeCellCurrentTime(sheet, rowNo = 10, colsNo = 11)

3.2 封裝get/post請(qǐng)求(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")
# 選擇一個(gè)日志格式
logger = logging.getLogger("example02")#或者example01

def debug(message):
  # 定義dubug級(jí)別日志打印方法
  logger.debug(message)

def info(message):
  # 定義info級(jí)別日志打印方法
  logger.info(message)

def warning(message):
  # 定義warning級(jí)別日志打印方法
  logger.warning(message)

3.5 封裝發(fā)送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.126.com" #設(shè)置服務(wù)器
  mail_user="testman1980"  #用戶名
  mail_pass="wulaoshi1980"  #口令
  sender = 'testman1980@126.com'
  receivers = ['2055739@qq.com',"testman1980@126.com"] # 接收郵件,可設(shè)置為你的QQ郵箱或者其他郵箱
  # 創(chuàng)建一個(gè)帶附件的實(shí)例
  message = MIMEMultipart()
  message['From'] = formataddr(["光榮之路吳老師", "testman1980@126.com"])
  message['To'] = ','.join(receivers)
  subject = '自動(dòng)化測(cè)試執(zhí)行報(bào)告'
  message['Subject'] = Header(subject, 'utf-8')
  message["Accept-Language"]="zh-CN"
  message["Accept-Charset"]="ISO-8859-1,utf-8,gbk"
  # 郵件正文內(nèi)容
  message.attach(MIMEText('最新執(zhí)行的自動(dòng)化測(cè)試報(bào)告,請(qǐng)參閱附件內(nèi)容!', 'plain', 'utf-8'))

  # 構(gòu)造附件1,傳送測(cè)試結(jié)果的excel文件
  att = MIMEBase('application', 'octet-stream')
  att.set_payload(open(ProjDirPath+"\\testdata\\testdata.xlsx", 'rb').read())
  att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', "自動(dòng)化測(cè)試報(bào)告.xlsx"))
  encoders.encode_base64(att)
  message.attach(att)
  """
  # 構(gòu)造附件2,傳送當(dāng)前目錄下的 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("郵件發(fā)送成功")
  except smtplib.SMTPException as e:
    print("Error: 無(wú)法發(fā)送郵件", e)

if __name__ == "__main__":
  send_mail()

四、 創(chuàng)建config包 用來(lái)存放公共的參數(shù)、配置文件、長(zhǎng)時(shí)間不變的變量值

創(chuàng)建public_data.py

import os
# 整個(gè)項(xiàng)目的根目錄絕對(duì)路勁
baseDir = os.path.dirname(os.path.dirname(__file__))

# 獲取測(cè)試數(shù)據(jù)文件的絕對(duì)路徑
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

# 存儲(chǔ)請(qǐng)求參數(shù)里面依賴的數(shù)據(jù)
REQUEST_DATA = {}

# 存儲(chǔ)響應(yīng)對(duì)象中的依賴數(shù)據(jù)
RESPONSE_DATA = {}

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

五、創(chuàng)建TestData目錄,用來(lái)存放測(cè)試文件

inter_test_data.xlsx

六、創(chuàng)建action包,用來(lái)存放關(guān)鍵字函數(shù)

6.1 解決數(shù)據(jù)依賴 (GetRely.py)

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

REQUEST_DATA = {"用戶注冊(cè)":{"1":{"username":"zhangsan", "password":"dfsdf23"},
            "headers":{"cookie":"asdfwerw"}}}
RESPONSE_DATA = {"用戶注冊(cè)":{"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":
        #說(shuō)明應(yīng)該去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":
        # 應(yīng)該去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": "用戶注冊(cè)->1", "password": "用戶注冊(cè)->1"},
      "response":{"code":"用戶注冊(cè)->1"},
      "headers":{"request":{"用戶注冊(cè)":["cookie"]},"response":{"用戶注冊(cè)":["age"]}}
      }
  print(GetRely.get(s, rely, h))

6.2 解決數(shù)據(jù)存儲(chǔ)(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":
        # 說(shuō)明需要存儲(chǔ)的依賴數(shù)據(jù)來(lái)自請(qǐng)求參數(shù),應(yīng)該將數(shù)據(jù)存儲(chǔ)到REQUEST_DATA
        for i in value:
          if i in request_source:
            val = request_source[i]
            if apiName not in REQUEST_DATA:
              # 說(shuō)明存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)還未生成,需要指明數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)
              REQUEST_DATA[apiName]={str(caseId): {i: val}}
            else:
              #說(shuō)明存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)中最外層結(jié)構(gòu)已存在
              if str(caseId) in REQUEST_DATA[apiName]:
                REQUEST_DATA[apiName][str(caseId)][i] = val
              else:
                # 說(shuō)明內(nèi)層結(jié)構(gòu)不完整,需要指明完整的結(jié)構(gòu)
                REQUEST_DATA[apiName][str(caseId)] = {i: val}
          else:
            print("請(qǐng)求參數(shù)中不存在字段" + i)
      elif key == "response":
        #說(shuō)明需要存儲(chǔ)的依賴數(shù)據(jù)來(lái)自接口的響應(yīng)body,應(yīng)該將數(shù)據(jù)存儲(chǔ)到RESPONSE_DATA
        for j in value:
          if j in response_source:
            val = response_source[j]
            if apiName not in RESPONSE_DATA:
              # 說(shuō)明存儲(chǔ)數(shù)據(jù)的結(jié)構(gòu)還未生成,需要指明數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)
              RESPONSE_DATA[apiName]={str(caseId): {j: val}}
            else:
              #說(shuō)明存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)中最外層結(jié)構(gòu)已存在
              if str(caseId) in RESPONSE_DATA[apiName]:
                RESPONSE_DATA[apiName][str(caseId)][j] = val
              else:
                # 說(shuō)明內(nèi)層結(jié)構(gòu)不完整,需要指明完整的結(jié)構(gòu)
                RESPONSE_DATA[apiName][str(caseId)] = {j: val}
          else:
            print("接口的響應(yīng)body中不存在字段" + j)
      elif key == "headers":
        for k, v in value.items():
          if k == "request":
            # 說(shuō)明需要往REQUEST_DATA變量中寫入存儲(chǔ)數(shù)據(jù)
            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":
            # 說(shuō)明需要往RESPONSE_DATA變量中寫入存儲(chǔ)數(shù)據(jù)
            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 校驗(yàn)數(shù)據(jù)結(jié)果(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)):
          # 等值校驗(yàn)
          if responseBody[key] != value:
            errorKey[key] = responseBody[key]
        elif isinstance(value, dict):
          sourceData = responseBody[key]
          if "value" in value:
            # 模糊匹配校驗(yàn)
            regStr = value["value"]
            rg = re.match(regStr, "%s" %sourceData)
            if not rg:
              errorKey[key] = sourceData
          elif "type" in value:
            # 數(shù)據(jù)類型校驗(yàn)
            typeS = value["type"]
            if typeS == "N":
              # 說(shuō)明是整形校驗(yà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里面寫結(jié)果

from config.public_data import *

def write_result(wbObj, sheetObj, responseData, errorKey, rowNum):
  try:
    # 寫響應(yīng)body
    wbObj.writeCell(sheetObj, content="%s" %responseData,
            rowNo = rowNum, colsNo=CASE_responseData)
    # 寫校驗(yàn)結(jié)果狀態(tài)及錯(cuò)誤信息
    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

七、創(chuàng)建Log目錄用來(lái)存放日志

八、主函數(shù)

#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":
      #需要被執(zhí)行
      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表,準(zhǔn)備執(zhí)行測(cè)試用例
      caseSheetObj = parseE.getSheetByName(apiTestCaseFileName)
      caseActiveObj = parseE.getColumn(caseSheetObj, CASE_active)
      for c_idx, col in enumerate(caseActiveObj[1:], 2):
        if col.value == "y":
          #需要執(zhí)行的用例
          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

          #發(fā)送接口請(qǐng)求之前需要做一下數(shù)據(jù)依賴的處理
          if relyData:
            logging.info("處理第%s個(gè)接口的第%s條用例的數(shù)據(jù)依賴!")
            requestData = GetRely.get(eval(requestData), eval(relyData))
          httpC = HttpClient()
          response = httpC.request(requestMethod=requestMethod,
                       requestData=requestData,
                       requestUrl=requestUrl,
                       paramsType=paramsType
                       )
          # 獲取到響應(yīng)結(jié)果后,接下來(lái)進(jìn)行數(shù)據(jù)依賴存儲(chǔ)邏輯實(shí)現(xiàn)
          if response.status_code == 200:
            responseData = response.json()
            # 進(jìn)行依賴數(shù)據(jù)存儲(chǔ)
            if dataStore:
              RelyDataStore.do(eval(dataStore), apiName, c_idx - 1, eval(requestData), responseData)
            # 接下來(lái)就是校驗(yàn)結(jié)果
            else:
              logging.info("接口【%s】的第【%s】條用例,不需要進(jìn)行依賴數(shù)據(jù)存儲(chǔ)!" %(apiName, c_idx))
            if checkPoint:
              errorKey = CheckResult.check(response, eval(checkPoint))
              write_result(parseE, caseSheetObj, responseData, errorKey, c_idx)
          else:
            logging.info("接口【%s】的第【%s】條用例,執(zhí)行失敗,接口協(xié)議code非200!" %(apiName, c_idx))
        else:
          logging.info("第%s個(gè)接口的第%s條用例,被忽略執(zhí)行!" %(idx -1, c_idx-1))
    else:
      logging.info("第%s行的接口被忽略執(zhí)行!" %(idx -1))


if __name__=="__main__":
  main()

框架待完善~~請(qǐng)各路神仙多多指教~~

到此這篇關(guān)于python+requests接口自動(dòng)化框架的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)python requests接口自動(dòng)化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python3實(shí)現(xiàn)163郵箱SMTP發(fā)送郵件

    python3實(shí)現(xiàn)163郵箱SMTP發(fā)送郵件

    這篇文章主要為大家詳細(xì)介紹了Python3實(shí)現(xiàn)163郵箱SMTP發(fā)送郵件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • python測(cè)試框架unittest和pytest區(qū)別

    python測(cè)試框架unittest和pytest區(qū)別

    這篇文章主要介紹了python測(cè)試框架unittest和pytest區(qū)別,幫助大家更好的理解和學(xué)習(xí)使用python進(jìn)行自動(dòng)化測(cè)試,感興趣的朋友可以了解下
    2021-04-04
  • numpy給array增加維度np.newaxis的實(shí)例

    numpy給array增加維度np.newaxis的實(shí)例

    今天小編就為大家分享一篇numpy給array增加維度np.newaxis的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • python3 numpy中數(shù)組相乘np.dot(a,b)運(yùn)算的規(guī)則說(shuō)明

    python3 numpy中數(shù)組相乘np.dot(a,b)運(yùn)算的規(guī)則說(shuō)明

    這篇文章主要介紹了python3 numpy中數(shù)組相乘np.dot(a,b)運(yùn)算的規(guī)則說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • django之狀態(tài)保持-使用redis存儲(chǔ)session的例子

    django之狀態(tài)保持-使用redis存儲(chǔ)session的例子

    今天小編就為大家分享一篇django之狀態(tài)保持-使用redis存儲(chǔ)session的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • 調(diào)整Jupyter notebook的啟動(dòng)目錄操作

    調(diào)整Jupyter notebook的啟動(dòng)目錄操作

    這篇文章主要介紹了調(diào)整Jupyter notebook的啟動(dòng)目錄操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • Python Pandas中創(chuàng)建Series的三種方法總結(jié)

    Python Pandas中創(chuàng)建Series的三種方法總結(jié)

    這篇文章主要介紹了Python Pandas中創(chuàng)建Series的三種方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • python中isdigit() isalpha()用于判斷字符串的類型問(wèn)題

    python中isdigit() isalpha()用于判斷字符串的類型問(wèn)題

    這篇文章主要介紹了python中isdigit() isalpha()用于判斷字符串的類型問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • python BeautifulSoup使用方法詳解

    python BeautifulSoup使用方法詳解

    Beautiful Soup 是用Python寫的一個(gè)HTML/XML的解析器,它可以很好的處理不規(guī)范標(biāo)記并生成剖析樹(parse tree)。 它提供簡(jiǎn)單又常用的導(dǎo)航(navigating),搜索以及修改剖析樹的操作。它可以大大節(jié)省你的編程時(shí)間,下面我們就看看他是如何使用
    2013-11-11
  • Python中shape[0]、shape[1]和shape[-1]分別的意思詳解(附代碼)

    Python中shape[0]、shape[1]和shape[-1]分別的意思詳解(附代碼)

    剛開始使用python做東西,總是不太理解矩陣、數(shù)組相關(guān)的問(wèn)題,所以在此記錄shape方面的總結(jié),下面這篇文章主要給大家介紹了關(guān)于Python中shape[0]、shape[1]和shape[-1]分別是什么意思的相關(guān)資料,需要的朋友可以參考下
    2022-11-11

最新評(píng)論