1. 程式人生 > 實用技巧 >基於Python+requests搭建的自動化框架-實現流程化的介面串聯

基於Python+requests搭建的自動化框架-實現流程化的介面串聯

框架產生目的:公司走的是敏捷開發模式,編寫這種框架是為了能夠滿足當前這種發展模式,用於前後端聯調之前(後端開發完介面,前端還沒有將業務處理完畢的時候)以及日後迴歸階段,方便為自己騰出學(mo)習(yu)時間。

鄙人一介小測試,一手承接產品,一手面對開發(4個後端,3個web前端,外加不知道幾個的乙方),專案經手了5批人,鄙人是第5批的測試,規範沒有,前人積累沒有,天崩開局/(ㄒoㄒ)/~~。

老規矩,上圖:

getparhInfo.py:獲取autoapi資料夾所在的目錄,便於專案換家,有沒有其實無所謂的;

import os


def get_path():
    path = os.path.split(os.path.realpath(__file__
))[0] return path if __name__ == '__main__': print('測試路徑是否OK,路徑為:', get_path())

readConfig.py

import os
import configparser
import getpathInfo

path = getpathInfo.get_path()  
config_path = os.path.join(path, 'config')  
config = configparser.ConfigParser()  # 呼叫外部的讀取配置檔案的方法
config.read(config_path, encoding='
utf-8') class ReadConfig(): def get_http(self, name): value = config.get('HTTP', name) return value def get_email(self, name): value = config.get('EMAIL', name) return value def get_account(self, name): value = config.get('ACCOUNT', name)
return value environment = ReadConfig().get_http('environment') # 切換環境 mobile_phone = ReadConfig().get_account('mobile_phone') password = ReadConfig().get_account('password') parent_username = ReadConfig().get_account('parent_phone') parent_pwd = ReadConfig().get_account('parent_pwd')

common:公共方法資料夾,最省事配置:日誌封裝(中文日誌在這裡要留意,有坑),請求封裝(如果有token之類的限制的話)

logs.py

import logging
import time

from getpathInfo import get_path


class Log(object):
    def __init__(self, logger=None):
        """
        指定儲存日誌的檔案路徑,日誌級別,以及呼叫檔案
        將日誌存入到指定的檔案中
        """

        # 建立一個logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)
        # 建立一個handler,用於寫入日誌檔案
        self.log_time = time.strftime('%Y-%m_%d_')
        self.log_path = get_path()+'\\log\\'
        self.log_name = self.log_path + self.log_time + 'test.log'
        fh = logging.FileHandler(self.log_name, 'a', encoding='utf-8')  # 追加模式,防止中文亂碼
        fh.setLevel(logging.INFO)

        # 再建立一個handler,用於輸出到控制檯
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)

        # 定義一個handler的輸出樣式
        formatter = logging.Formatter(
            '[%(asctime)s] %(filename)s->%(funcName)s line:%(lineno)d [%(levelname)s]%(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)

        # 給logger新增handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)

        #  新增下面一句,在記錄日誌之後移除控制代碼
        fh.close()
        ch.close()

    def getLog(self):
        return self.logger


log = Log().getLog()
if __name__ == '__main__':
    log.info('日誌')  # 抄過來的程式碼一定要進行測試

configHttp.py

這裡是預設加上token的,但是並不是所有介面都是需要token,解決思路:再加個configHttpNormal.py,或者run_main()裡再加個入參。

import json
import requests

from common.logs import log
from readConfig import environment,mobile_phone,password
from case.api.User import login
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  # 如果有抓包需求,需要把verify設定成False,這行程式碼忽略系統之後的警告
"""
這個檔案主要來通過get、post等方法來進行http請求,並拿到請求響應
"""

token = login(mobile_phone,password) # 登入方法
headers = {'Authorization': token,
           "Content-Type": 'application/json;charset=UTF-8',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36'}


class RunMain():
    def send_post(self, path, data):
        response = requests.post(url=environment+path,data=json.dumps(data,ensure_ascii=False,separators=(',',':')).encode('utf-8'), headers=headers,verify=False)
        log.info(path)  # path
        log.info(data)  # 請求,便於復現
        log.info(response.status_code)  # 請求狀態碼
        return response

    def send_get(self, path, data):
        response = requests.get(url=environment+path, data=data, headers=headers,verify=False)
        log.info(path)
        log.info(data)
        log.info(response.status_code)
        return response

    def run_main(self, method, path=None, data=None):
        result = None
        if method.lower() == 'post':
            result = self.send_post(path, data)
        elif method.lower() == 'get':
            result = self.send_get(path, data)
        else:
            print("method值錯誤!!!")
        return result


if __name__ == '__main__':
    result1 = RunMain().run_main('get', '/v1/wrong-work/info?type=1').json()
    result2 = RunMain().run_main('Get', '/v1/wrong-work/info?type=2').json()
    print(result1)
    print(result2)

case:用例資料夾,敏捷模式中開發提測基本上都是單介面提測,而且同一個模組下的介面分給了不同的開發,為了方便定位到開發,所以我將平臺所有的介面都寫了過來╮(╯▽╰)╭,

老規矩,下方直接執行,可以進行單介面的相關驗證。

相信各位也看了很多的介面自動化測試框架,我上面的應該沒有多少新意,下面就是不同點;

regression_testing 顧名思義,迴歸測試ing,只有進行時,沒有完成時……

鄙人將前端的業務邏輯通過介面層模擬了過來,做了許久之後,不禁產生了懷疑:這都是哪位鬼才設計的?沒有被開發XX了嗎?

上圖是使用unittest框架進行的,用例之間傳參用法其實就是我上面展示的一部分;

其實這個資料夾下不適合使用unittest框架,因為通過用例之間的巧妙設計,雖然可以將業務之間的呼叫狀態都模擬出來,但是由於髒資料的存在,某些bug沒有在這些測試過程中表示出來。

哎,苦命啊,前端趕緊進行插樁操作,報錯日誌上傳起來;鄙人只能放大招了,拾起了爬蟲思路,自動遍歷吧(窮舉);

放程式碼片段,哎,遍歷一時爽,重構火葬場(json目錄深了之後,是真的不想看)。

之後優化思路:將regression_testing裡面的方法改成test_*,寫一個run方法,加上測試報告,郵件通知(ps:但鄙人不用啊,就十個人,遇到bug,tapd複製上引數,“老哥,出bug了”)

參考文獻:

自動化測試框架:

https://blog.csdn.net/songlh1234/article/details/84317617 # 框架主體都是這位老哥的,文抄公的水平您還滿意?

https://www.jianshu.com/p/9d3f991c901a

https://www.cnblogs.com/peter200-OK/p/9086087.html # 這個慎重,或許是鄙人太菜了,沒有抄好這個作業

框架期間問題解決:

unittest用例間傳參:

【python介面自動化框架-unittest】如何傳引數到下一個case - WANG-X - 部落格園 (cnblogs.com)

部分請求如: /v1/verify?clazz=1,2,3,4,5 解決方案如下:

python-map的用法 - lincappu - 部落格園 (cnblogs.com)