基於Python+requests編寫的自動化測試項目-實現流程化的接口串聯


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

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

老規矩,上圖:

這個不直觀,下面我來展示這個抽象的圖片(美術功底差,見諒):

怎么,是不是有一種UI自動化里面的POM思想?沒錯,這正是這個思路在API自動化里里面的一個體現。

畢竟服務間的調用是復雜的,將各個接口封裝起來,對應的py文件里面創一個main方法,用於單個接口入參以及返回值之間的驗證,至於接口之間的串聯,那就放到下面(regression_test里面,每一個case相當於一個過程,如:上傳習題、選題、組卷分發、上傳試卷、批閱等流程),輔以邏輯處理,大部分的流程還是可以自動化實現的(ps:對於前后端聯調加改bug用了兩個月時間才圓滿搞定的過程,我沒敢嘗試將這個給自動化實現了,還是留待后人吧)。

 

 

 

 

getpathInfo.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。

對於同一個系統中需要多個用戶參與的過程,這時候就需要配置文件里面再多一位用戶的賬號密碼了,再加一個login()方法並賦值,下面的對應的基礎請求封裝里面要再多一個參數:is_other_one,默認為false,一但給true,下面headers就要換參數中的值;

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了”)

是不是也發現了,少了很多東西?寫個裝飾器(用於統計時間),接口請求超時也要打印出來;

 

 

 其實還有一個文件夾,用來寫壓測腳本(基於locust的FasthttpUser),log文件夾中的path以及data都是直接可以在locust中使用的,省了構造數據的時間;

locust腳本如下(部分),更詳細的可以看看httprunner的實現思路,大神寫的比我強太多了,還是得學啊。

 

  

參考文獻:

自動化測試框架:

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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM