1. 程式人生 > 實用技巧 >【介面自動化】Python+Requests介面自動化測試框架搭建【三】

【介面自動化】Python+Requests介面自動化測試框架搭建【三】

經過上兩篇文章的講解,我們已經完成介面自動化的基礎框架,現在開始根據實際專案豐滿起來。

在PyCharm中新建專案,專案工程結構如下:

config:配置資料夾,可以將一些全域性變數放於配置檔案中,方便呼叫。例如:URL地址、埠,開發如經常更換埠在配置檔案中便可修改。

data:測試用例表格資料夾,存放測試用例.xls和讀取寫入excel表的檔案。

demo:程式公共類資料夾,存放程式公共類,例如:POST/GET請求,獲取Token等。

kit:相關測試工具,壓縮、傳送郵件。

main:程式執行主資料夾。

report:測試報告資料夾。

test_case:測試用例。

公司實際開發專案中,存在介面依賴,即Token。Token獲取方法為登入後返回Token值,所以我們編寫一個登入類獲取Token,並將Token放置於config檔案中,成為全域性變數,等其他介面呼叫時,直接引用變數。

在demo中新建DemoMain請求方法公共類。

DemoMain.py

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: DemoMain.py
@time: 2020/7/31 10:58
@desc: 公共方法主類
'''

import requests

class RunMain:
    def __init__(self):
        pass

    @staticmethod
    
def send_post(url,cookies,headers,params=None): try: res = requests.post(url=url,cookies=cookies,headers=headers,data=params) return res.status_code # 返回響應狀態程式碼 except Exception as msg: return msg @staticmethod def send_get(url,cookies,headers,params=None,):
try: res = requests.get(url=url,cookies=cookies,headers=headers,params=params,) return res.status_code # 返回響應狀態程式碼 except Exception as msg: return msg def run_main(self, url,method,cookies=None,headers=None,params=None): if method == 'GET': res = self.send_get(url,cookies,headers,params) return res elif method == 'POST': res = self.send_post(url,cookies,headers,params) return res else: print('不支援的請求方式!')

CaseDemo.py 根據介面分開編寫請求方法

實際開發中遇到的問題(僅為自己記錄):

1.return返回值的問題:實際專案測試中我們不能只返回code狀態碼,因為介面測試中不能只憑返回狀態碼進行斷言,我們測試判定中還應檢查介面返回值,介面返回值應在開發提供介面文件已經註明。所以上述程式碼中我們應將返回值改為res。

2.因為一開始只考慮斷言狀態碼的問題,所以導致多新建一個LoginDemo請求類,如返回值為res,此檔案即可刪除。

3.配置檔案中可以參考Postman中多種引數的方式進行配置,可根據實際專案自己增加,極其方便。還可以配置資料庫等資訊,不再贅述。

data資料夾:

GetExcel.py:獲取測試用例操作類

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: GetExcel.py
@time: 2020/8/12 17:03
@desc:獲取Excel表格資料
'''
import xlrd
def get_excel_data(sheetName,idCol=0,bodyCol=7,repsCol=9): # 獲取資料函式
    dataList = [] # 生成一個空字典
    workSheet = xlrd.open_workbook('../data/JDData.xls', formatting_info=True).sheet_by_name(sheetName) # 獲取表格
    endRow = workSheet.nrows # 獲取有效工作行數
    for one in range(1, endRow): # 迴圈獲取
        if workSheet.cell(one,12).value == 'Yes': # 判斷用例是否執行
            dataList.append((workSheet.cell(one, idCol).value,workSheet.cell(one, bodyCol).value, workSheet.cell(one, repsCol).value)) # 追加dataList
        else:
            pass
    return dataList

固定讀取表格中的資料即:第1列,第8列,第10列資料,所以形參寫死。

SetExcel.py:測試結果寫入Excel表格

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: SetExcel.py
@time: 2020/8/14 17:01
@desc: 寫入Excel
'''
import xlrd
import json
from xlutils import copy
class CSetExcel():
    def SetExcel(self,sheetName,infodata,one,Col=10):
        path = '../data/JDData.xls'
        workSheet = xlrd.open_workbook(path,formatting_info=True)
        New_workSheet = copy.copy(workSheet) # 複製表格
        New_Sheet = New_workSheet.get_sheet(sheetName) # 獲取表格名
        New_Sheet.write(one,Col,json.dumps(infodata,ensure_ascii=False)) # 寫入Excel
        New_workSheet.save(path) # 儲存

此處坑:

1.New_Sheet.write(one,Col,json.dumps(infodata,ensure_ascii=False)) # 寫入Excel

如不加ensure_ascii=False,寫入Excel中中文會被轉義unicode編碼。json.dumps(infodata):介面返回值為字典型別(dict)轉換成字串型別寫入excel。

2.執行方法前,記得關閉Excel表格。

Data.excel模板格式

此處坑:(MD,我也不知道我為啥這麼多坑踩.........心累啊,前人種樹後人乘涼,我先填為敬。)

編號一列單元格格式為文字,不要設定成數值,設定成數值會被Python取出後變為1.0(浮點型),然後導致的結果就是SetExcel.py根據編號寫入資料時,無法識別1.0單元格在哪裡,出現錯誤。

kit資料夾:存放測試報告壓縮工具類以及傳送郵件類

ZipTool.py 壓縮檔案工具類

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: ZipTool.py
@time: 2020/8/19 9:52
@desc: 壓縮資料夾工具
'''
import os
import zipfile
import shutil
class FileZip():
    def File(self,source_dir, output_filename):# 打包目錄為zip檔案(未壓縮)
        if os.path.exists('../report/Report.zip') == True : # 判斷檔案是否存在
            print("報告壓縮檔案存在!正在執行刪除........")
            os.remove('../report/Report.zip') # 刪除檔案
            print("刪除成功!正在執行打包操作........")
            zipf = zipfile.ZipFile(output_filename, 'w')
            pre_len = len(os.path.dirname(source_dir))
            for parent, dirnames, filenames in os.walk(source_dir):
                for filename in filenames:
                    pathfile = os.path.join(parent, filename)
                    arcname = pathfile[pre_len:].strip(os.path.sep)  # 相對路徑
                    zipf.write(pathfile, arcname)
            zipf.close()
            shutil.move('../main/Report.zip', '../report') # 移動檔案
            print('打包完成,正在傳送報告......')
        else:
            print('正在執行打包操作......')
            zipf = zipfile.ZipFile(output_filename, 'w')
            pre_len = len(os.path.dirname(source_dir))
            for parent, dirnames, filenames in os.walk(source_dir):
                for filename in filenames:
                    pathfile = os.path.join(parent, filename)
                    arcname = pathfile[pre_len:].strip(os.path.sep)
                    zipf.write(pathfile, arcname)
            zipf.close()
            shutil.move('../main/Report.zip', '../report')
            print('打包完成,正在傳送報告......')

EmailTool.py 傳送郵件工具類

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: EmailTool.py
@time: 2020/8/19 9:53
@desc: 傳送郵件工具
'''

import smtplib
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
class SendEmail():
    def Email(slef):
        # 第三方 SMTP 服務
        mail_host = "smtp.163.com"  # 設定伺服器
        mail_user = "[email protected]"  # 使用者名稱
        mail_pass = " "  # 口令

        sender = '[email protected]'
        receivers = ['[email protected]','[email protected]']  # 接收郵件,可設定為你的QQ郵箱或者其他郵箱,多郵箱設定為陣列

        message = MIMEMultipart() 
        message['From'] = Header("GongYu", 'utf-8')
        #message['To'] = Header("測試", 'utf-8')
        ReportTime = time.strftime("%Y-%m-%d %H:%M") 
        subject = '['+ReportTime +']介面自動化測試報告'
        message['Subject'] = Header(subject, 'utf-8')

        # 郵件正文內容
        NewTime = time.strftime("%Y-%m-%d %H:%M")
        message.attach(MIMEText('各位領導,同事:附件內容為介面自動化測試報告。測試時間為:'+NewTime+',請下載檢視!', 'plain', 'utf-8'))
        # 附件
        att1 = MIMEText(open('../data/Data.xls', 'rb').read(), 'base64', 'utf-8')
        att1["Content-Type"] = 'application/octet-stream'
        att1["Content-Disposition"] = 'attachment; filename="JDData.xls"'
        message.attach(att1)

        att2 = MIMEText(open('../report/Report.zip', 'rb').read(), 'base64', 'utf-8')
        att2["Content-Type"] = 'application/octet-stream'
        att2["Content-Disposition"] = 'attachment; filename="Report.zip"'
        message.attach(att2)

        try:
            smtpObj = smtplib.SMTP()
            smtpObj.connect(mail_host, 25)  # 25 為 SMTP 埠號
            smtpObj.login(mail_user, mail_pass)
            smtpObj.sendmail(sender, receivers, message.as_string())
            print("郵件傳送成功!")
        except smtplib.SMTPException:
            print("Error: 無法傳送郵件")

下面我們編寫Test_case.py 檔案,放置於test_case資料夾下

Test_case.py

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: Test_test.py
@time: 2020/8/13 9:25
@desc: 測試執行
'''
import json
import pytest
import allure
from data.GetExcel import get_excel_data
from data.SetExcel import CSetExcel
from demo.CaseDemo import addapi


@allure.feature('地址介面測試')
class Testaddapi():

    @allure.story('獲取一級地址')
    @pytest.mark.parametrize('idData,infoData,resultdata',get_excel_data('1-獲取一級地址'))
    def test_getProvince(self,idData,infoData,resultdata):
        Res = addapi().getProvince()
        CSetExcel().SetExcel('1-獲取一級地址', Res.json(), json.loads(idData))
        assert Res.status_code == 200
        assert Res.json()['resultMessage'] == json.loads(resultdata)['resultMessage']
        assert Res.json()['success'] == json.loads(resultdata)['success']

我們採用的是Pytest測試框架,使用allure輸出測試報告。

到這裡我們的測試框架就已經完成了,下面我們編寫一個執行主類:TestMain.py 進行啟動測試。

#!/usr/bin/env python
# encoding: utf-8
'''
@author: GongYu
@license: (C) Copyright 2020
@contact: [email protected]
@software: PyCharm
@file: TestMain.py
@time: 2020/8/13 10:32
@desc: 執行主類
'''
import shutil
import pytest
import os
from kit.ZipTool import FileZip
from kit.EmailTool import SendEmail

if __name__ == '__main__':  # 啟動allure
    if os.path.exists('../report/xml') == True or os.path.exists('../report/html') == True:
        print("報告目錄存在!正在執行刪除........")
        shutil.rmtree(r'../report/xml')
        shutil.rmtree(r'../report/html')
        print("刪除成功!正在執行測試用例........")
        pytest.main(['../test_case/Test_test.py', '-s', '--alluredir', '../report/xml'])  # 生成測試報告檔案
        print('測試報告轉換HTML.....')
        os.system('allure generate ../report/xml -o ../report/html')  # 將測試報告檔案轉化為HTML
        FileZip().File('../report', 'Report.zip')
        SendEmail().Email()
        os.system('allure serve ../report/xml')  # 執行測試報告檔案
    else:
        print('正在執行測試用例........')
        pytest.main(['../test_case/Test_test.py', '-s', '--alluredir', '../report/xml'])
        print('測試報告轉換HTML.....')
        os.system('allure generate ../report/xml -o ../report/html')
        FileZip().File('../report', 'Report.zip')
        SendEmail().Email()
        os.system('allure serve ../report/xml')

下面我們執行試一下:

控制檯輸出:

Allure測試報告:

下面我們登入一下郵箱檢視一下:

我們已經將測試結果加入附件傳送到了負責人的郵箱,到此我們的自動化測試框架已經完成。最後還有一個日誌功能還沒實現,等找個時間再來補充吧。

新手上路,知識不足,如有紕漏錯誤,還請大神們指正,謝謝各位咯~~~