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

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

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

項目說明

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

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

固然,若是感興趣的話,還能夠再對接口自動化進行Jenkins持續集成。sql

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 庫下一些常見的請求方法進行了簡單封裝,以便調用起來更加方便。json

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下的請求。api

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 ,該類主要用於自定義關鍵字返回結果。cookie

class ResultBase():
    pass

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

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

關鍵字封裝

關鍵字應該是具備必定業務意義的,在封裝關鍵字的時候,能夠經過調用多個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

相關文章
相關標籤/搜索