基於Python+Requests+Pytest+YAML+Allure實現接口自動化


本項目實現接口自動化的技術選型:Python+Requests+Pytest+YAML+Allure ,主要是針對之前開發的一個接口項目來進行學習,通過 Python+Requests 來發送和處理HTTP協議的請求接口,使用 Pytest 作為測試執行器,使用 YAML 來管理測試數據,使用 Allure 來生成測試報告。

接口項目開發學習:
使用Flask開發簡單接口(1)--GET請求接口
使用Flask開發簡單接口(2)--POST請求接口
使用Flask開發簡單接口(3)--引入MySQL
使用Flask開發簡單接口(4)--借助Redis實現token驗證
使用Flask開發簡單接口(5)--數據加密處理

項目說明

本項目在實現過程中,把整個項目拆分成請求方法封裝、HTTP接口封裝、關鍵字封裝、測試用例等模塊。

首先利用Python把HTTP接口封裝成Python接口,接着把這些Python接口組裝成一個個的關鍵字,再把關鍵字組裝成測試用例,而測試數據則通過YAML文件進行統一管理,然后再通過Pytest測試執行器來運行這些腳本,並結合Allure輸出測試報告。

當然,如果感興趣的話,還可以再對接口自動化進行Jenkins持續集成。

GitHub項目源碼地址:https://github.com/wintests/pytestDemo

項目結構

  • api ====>> 接口封裝層,如封裝HTTP接口為Python接口
  • common ====>> 各種工具類
  • core ====>> requests請求方法封裝、關鍵字返回結果類
  • config ====>> 配置文件
  • data ====>> 測試數據文件管理
  • operation ====>> 關鍵字封裝層,如把多個Python接口封裝為關鍵字
  • pytest.ini ====>> pytest配置文件
  • requirements.txt ====>> 相關依賴包文件
  • testcases ====>> 測試用例

請求方法封裝

core/rest_client.py 文件中,對 Requests 庫下一些常見的請求方法進行了簡單封裝,以便調用起來更加方便。

class RestClient():

    def __init__(self, api_root_url):
        self.api_root_url = api_root_url
        self.session = requests.session()

    def get(self, url, **kwargs):
        return self.request(url, "GET", **kwargs)

    def post(self, url, data=None, json=None, **kwargs):
        return self.request(url, "POST", data, json, **kwargs)

    def put(self, url, data=None, **kwargs):
        return self.request(url, "PUT", data, **kwargs)

    def delete(self, url, **kwargs):
        return self.request(url, "DELETE", **kwargs)

    def patch(self, url, data=None, **kwargs):
        return self.request(url, "PATCH", data, **kwargs)

    def request(self, url, method, data=None, json=None, **kwargs):
        url = self.api_root_url + url
        headers = dict(**kwargs).get("headers")
        params = dict(**kwargs).get("params")
        files = dict(**kwargs).get("params")
        cookies = dict(**kwargs).get("params")
        self.request_log(url, method, data, json, params, headers, files, cookies)
        if method == "GET":
            return self.session.get(url, **kwargs)
        if method == "POST":
            return requests.post(url, data, json, **kwargs)
        if method == "PUT":
            if json:
                # PUT 和 PATCH 中沒有提供直接使用json參數的方法,因此需要用data來傳入
                data = complexjson.dumps(json)
            return self.session.put(url, data, **kwargs)
        if method == "DELETE":
            return self.session.delete(url, **kwargs)
        if method == "PATCH":
            if json:
                data = complexjson.dumps(json)
            return self.session.patch(url, data, **kwargs)

HTTP接口 封裝為 Python接口

api/user.py 文件中,將上面封裝好的HTTP接口,再次封裝為不同的Python接口。不同的Python接口,會處理不同URL下的請求。

class User(RestClient):

    def __init__(self, api_root_url, **kwargs):
        super(User, self).__init__(api_root_url, **kwargs)

    def list_all_users(self, **kwargs):
        return self.get("/users", **kwargs)

    def list_one_user(self, username, **kwargs):
        return self.get("/users/{}".format(username), **kwargs)

    def register(self, **kwargs):
        return self.post("/register", **kwargs)

    def login(self, **kwargs):
        return self.post("/login", **kwargs)

    def update(self, user_id, **kwargs):
        return self.put("/update/user/{}".format(user_id), **kwargs)

    def delete(self, name, **kwargs):
        return self.post("/delete/user/{}".format(name), **kwargs)

關鍵字返回結果類

core/result_base.py 下,定義了一個空類 ResultBase ,該類主要用於自定義關鍵字返回結果。

class ResultBase():
    pass

"""
自定義示例:
result = ResultBase()
result.success = False
result.msg = res.json()["msg"]
result.response = res
"""

在多流程的業務場景測試下,通過自定義期望保存的返回數據值,以便更好的進行斷言。

關鍵字封裝

關鍵字應該是具有一定業務意義的,在封裝關鍵字的時候,可以通過調用多個Python接口來完成。在某些情況下,比如測試一個充值接口的時候,在充值后可能需要調用查詢接口得到最新賬戶余額,來判斷查詢結果與預期結果是否一致,那么可以這樣來進行測試:

  • 1, 首先,可以把 充值-查詢 的操作封裝為一個關鍵字,在這個關鍵字中依次調用充值和查詢的接口,並可以自定義關鍵字的返回結果。
  • 2, 接着,在編寫測試用例的時候,直接調用關鍵字來進行測試,這時就可以拿到關鍵字返回的結果,那么斷言的時候,就可以直接對關鍵字返回結果進行斷言。

測試用例層

根據用例名分配測試數據

測試數據位於 data 文件夾下,在這里使用 YAML 來管理測試數據,同時要求測試數據中第一層的名稱,需要與測試用例的方法名保持一致,如 test_get_all_user_infotest_delete_user

test_get_all_user_info:
  # 期望結果,期望返回碼,期望返回信息
  # except_result, except_code, except_msg
  - [True, 0, "查詢成功"]
省略
test_delete_user:
  # 刪除的用戶名,期望結果,期望返回碼,期望返回信息
  # username, except_result, except_code, except_msg
  - ["測試test", True, 0, "刪除用戶信息成功"]
  - ["wintest3", False, 3006, "該用戶不允許刪除"]

這里借助 fixture 方法,我們就能夠通過 request.function.__name__ 自動獲取到當前執行用例的函數名 testcase_name ,當我們傳入測試數據 api_data 之后,接着便可以使用 api_data.get(testcase_name) 來獲取到對應用例的測試數據。

import pytest
from testcases.conftest import api_data

@pytest.fixture(scope="function")
def testcase_data(request):
    testcase_name = request.function.__name__
    return api_data.get(testcase_name)

數據准備和清理

在接口自動化中,為了保證用例可穩定、重復地執行,我們還需要有測試前置操作和后置操作,即數據准備和數據清理工作。

@pytest.fixture(scope="function")
def delete_register_user():
    """注冊用戶前,先刪除數據,用例執行之后,再次刪除以清理數據"""
    del_sql = base_data["init_sql"]["delete_register_user"]
    db.execute_db(del_sql)
    logger.info("注冊用戶操作:清理用戶--准備注冊新用戶")
    logger.info("執行前置SQL:{}".format(del_sql))
    yield # 用於喚醒 teardown 操作
    db.execute_db(del_sql)
    logger.info("注冊用戶操作:刪除注冊的用戶")
    logger.info("執行后置SQL:{}".format(del_sql))

在這里,以用戶注冊用例為例。對於前置操作,我們應該准備一條刪除SQL,用於將數據庫中已存在的相同用戶刪除,對於后置操作,我們應該再執行刪除SQL,確保該測試數據正常完成清理工作。

在測試用例中,我們只需要在用例上傳入 fixture 的函數參數名 delete_register_user ,這樣就可以調用 fixture 實現測試前置及后置操作。當然,也可以使用pytest裝飾器 @pytest.mark.usefixtures() 來完成,如:

@pytest.mark.usefixtures("delete_register_user")

Allure用例描述

在這里,我們結合 Allure 來實現輸出測試報告,同時我們可以使用其裝飾器來添加一些用例描述並顯示到測試報告中,以便報告內容更加清晰、直觀、可讀。如使用 @allure.title() 自定義報告中顯示的用例標題,使用 @allure.description() 自定義用例的描述內容,使用 @allure.step() 可在報告中顯示操作步驟,使用 @allure.issue() 可在報告中顯示缺陷及其鏈接等。

@allure.step("步驟1 ==>> 注冊用戶")
def step_1(username, password, telephone, sex, address):
    logger.info("步驟1 ==>> 注冊用戶 ==>> {}, {}, {}, {}, {}".format(username, password, telephone, sex, address))

@allure.severity(allure.severity_level.NORMAL)
@allure.epic("針對單個接口的測試")
@allure.feature("用戶注冊模塊")
class TestUserRegister():
    """用戶注冊"""
    @allure.story("用例--注冊用戶信息")
    @allure.description("該用例是針對獲取用戶注冊接口的測試")
    @allure.issue("https://www.cnblogs.com/wintest", name="點擊,跳轉到對應BUG的鏈接地址")
    @allure.testcase("https://www.cnblogs.com/wintest", name="點擊,跳轉到對應用例的鏈接地址")
    @allure.title(
        "測試數據:【 {username},{password},{telephone},{sex},{address},{except_result},{except_code},{except_msg}】")
    @pytest.mark.single
    @pytest.mark.parametrize("username, password, telephone, sex, address, except_result, except_code, except_msg",
                             api_data["test_register_user"])
    @pytest.mark.usefixtures("delete_register_user")
    def test_delete_user(self, login_fixture, username, except_result, except_code, except_msg):
省略

項目部署

首先,下載項目源碼后,在根目錄下找到 requirements.txt 文件,然后通過 pip 工具安裝 requirements.txt 依賴,執行命令:

pip3 install -r requirements.txt

接着,修改 config/setting.ini 配置文件,在Windows環境下,安裝相應依賴之后,在命令行窗口執行命令:

pytest

注意:因為我這里是針對自己的接口項目進行測試,如果想直接執行我的測試用例來查看效果,需要提前部署上面提到的接口項目。

測試報告效果展示

在命令行執行命令:pytest 運行用例后,會得到一個測試報告的原始文件,但這個時候還不能打開成HTML的報告,還需要在項目根目錄下,執行命令啟動 allure 服務:

# 需要提前配置allure環境,才可以直接使用命令行
allure serve ./report

最終,可以看到測試報告的效果圖如下:

image.png


免責聲明!

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



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