【Robot Framework 】項目實戰彙總

寫在前面

RF自動化的文章記錄基本完成,建一個彙總目錄,方便查看。html

【Robot Framework 項目實戰】彙總

∮【RF 項目實戰 00】環境搭建 json

∮【RF 項目實戰 01】使用 RequestsLibrary 進行接口測試 安全

∮【RF 項目實戰 02】使用腳本生成統一格式的RF關鍵字 網絡

∮【RF 項目實戰 03】使用腳本自動生成統一格式的RF自動化用例 app

∮【RF 項目實戰 04】基於錄製生成RF關鍵字及基礎自動化用例 測試

腳本優化

上一篇博客咱們編寫了基於錄製生成的RF自動化Demo用例,可是隻是徹底根據抓包數據構造了一條正常的測試用例,其實針對接口的參數校驗這樣的重複性比較強的測試,咱們也能夠把它們腳本化,參數化到RF文件中。優化

接口測試,基本參數校驗範圍

基本參數校驗,是每次接口測試首要考慮的內容,這部分應當是測試工程師的基本能力。編碼

  1. 可選與必選
    • 字段可選,傳與不傳時的區別
    • 字段必選,必選參數缺失時返回什麼錯誤,返回格式是否標準
  • 空值
    • 空值時,返回什麼結果。(如網絡超時未返回,當成空值在處理仍是默認值處理)
  • 默認值
    • 是否有默認值,可選參數和必選參數是否有默認值
  • 類型
    • int,區分32和64位,int類型時,傳str時的錯誤展現
    • string類型,
    • float類型,每每在計算金額時,會用到浮點數
  • 類型長度
    • 超過長度,接口請求是否出錯,若是不出錯,展現是否被截斷
    • 中文跨越邊界時被截斷的問題,如nickname是32字節,共16箇中文,前15是中文,第16是英文,第17是中文,則多出一個字節,最後一箇中文是否被截斷顯示爲亂碼
  • 大小寫
    • 是否大小寫敏感,signkey,等內容,通常大小寫敏感
  • 安全過濾
    • <>是否被過濾掉,是否有直接存寫到DB
    • ' " 是否被轉譯或者使用防SQL注入的ORM組件
  • 編碼類型
    • utf-8,GBK,unicode
    • 特殊字符(空格,換行等),emoji(4個字節),中文,拉丁文,日文等

具體實現

首先咱們定義一批可能須要傳遞的參數,使用常量的方式存儲。url

PARAM_ERR = 10000
OK = 0
BOOL = True  # False
INT = 10
NEG_INT = -1
ZERO = 0
BIG_INT = 99**5
NEG_FLOAT = -1.1
FLOAT = 0.99
EMPTY_STR = ""
INT_STR = "1111"
LETTERS_STR = "ABCabc"
SPACE_STR = " "
EMPTY_LIST = []
STR_LIST = ["a", "b"]
INT_LIST = [10, 20]
BOOL_LIST = [True, False]
MIX_LIST = ["a", True, 10, ["aa"], {"a": "aa"}]
EMPTY_DICT = {}
STR_DICT = {"a": "b"}
INT_DICT = {"d": 11}
BOOL_DICT = {"c": True}
MIX_DICT = {"b": "", "c": True, "d": 11, "e": {"f": [1, 2]}}
...

而後咱們經過原始的請求參數,本身組裝不一樣的請求參數:spa

def gen_req_data(sheet_obj):
    str_params = sheet_obj.cell_value(1, 1)
    str_method = sheet_obj.cell_value(1, 6)
    temp_list = []
    # print(f"str_params:{str_params}")
    if not len(str_params):
        return ""
    try:
        # 轉化 json類型爲Python標準類型
        params = eval(str_params.replace("false", "False").replace("true", "True").replace("null", "None"))
        if not len(params):
            return ""
    except Exception as f:
        logger.warning("====================================================")
        logger.error("=" + str(f))
        logger.warning("====================================================")
        params = ""

    # 正常參數
    temp_list.append(params)

    # 添加異常參數
    for k, v in params.items():
        if isinstance(v, dict):
            for i in [
                BOOL,
                NEG_FLOAT,
                LETTERS_STR,
                MIX_LIST,
                ZERO,
                MIX_DICT
            ]:
                params = copy.deepcopy(params)  # 深拷貝,字典存儲的是內存地址
                params[k] = i  # doc
                temp_list.append(params)
        elif isinstance(v, list):
            for i in [BOOL, NEG_FLOAT, LETTERS_STR, MIX_LIST, ZERO, MIX_DICT]:
                params = copy.deepcopy(params)
                params[k] = i
                temp_list.append(params)
        elif isinstance(v, str):
            for i in [BOOL, NEG_FLOAT, EMPTY_STR, INT_STR, SPACE_STR, MIX_DICT, STR_LIST, EMPTY_DICT]:
                params = copy.deepcopy(params)
                params[k] = i
                temp_list.append(params)
        elif isinstance(v, int):
            for i in [BOOL, NEG_FLOAT, INT_STR, INT_LIST, NEG_INT, ZERO, BIG_INT, NEG_FLOAT, FLOAT, EMPTY_DICT]:
                params = copy.deepcopy(params)
                params[k] = i
                temp_list.append(params)
        elif isinstance(v, bool):
            for i in [True, False, ZERO, FLOAT, NEG_INT, INT_STR, INT_LIST, STR_DICT]:
                params = copy.deepcopy(params)
                params[k] = i
                temp_list.append(params)
    return str_method, temp_list

最後,咱們把不一樣的請求參數轉化爲RF測試用例須要的數據格式,最終生成對應的測試用例:

def gen_testcase(self, sheet_obj, target_robot_name, interface_name):
    """
    :param sheet_obj:
    :param target_robot_name:
    :param interface_name:
    :return:
    """
    method, params_list = self.gen_req_data(sheet_obj)
    with open(target_robot_name, 'a') as f:
        for num, param in enumerate(params_list):
            """
            待辦:動態修改Documentation的信息,異常參數以tuple的形式存儲Documentation,而後解析的時候參數化到文檔中
            """
            f.write(interface_name + f'.Demo_case{num}' + '\n')
            f.write('    [Documentation]    demo' + '\n')
            f.write('    [Tags]    ' + self.tag + '\n')
            params = self._gen_param_data(method, param)
            f.write(params)
            if params:
                f.write('    ${{Resp_data}}    {}'.format(self.project_abbr) + interface_name + '    ${HOST}    ' + "${param}")
            else:
                f.write('    # 未獲取到請求參數數據 \n')
                f.write('    ${{Resp_data}}    {}'.format(self.project_abbr) + interface_name + '    ${HOST}    ' + "${EMPTY}")
            f.write('\n')
            f.write('    Log    ${Resp_data.text}' + '\n')

            # 第一條用例正常斷言,其餘用例標記爲失敗用例
            if num == 0:
                f.write('    Should Be Equal As Strings    ${Resp_data.status_code}    200' + '\n')
                f.write('    ${resp_json}    to json    ${Resp_data.text}' + '\n')
                f.write(self.gen_exp_data(sheet_obj))
            else:
                f.write(f'    Should Be Equal As Strings    ${{Resp_data.status_code}}    {self.error_status_code}' + '\n')
                f.write('    ${resp_json}    to json    ${Resp_data.text}' + '\n')
                f.write(self._format_exp_data(self.param_error_json))  # param_error_json 接口異常返回內容中的公共部分,好比code, result
            f.write('\n')
    logger.info("Demo case保存於:" + target_robot_name)

:⚠️ 部分依賴代碼在上一篇文章中能夠找到。

總結

經過抓包,咱們獲取了原始數據,而後根據抽象異常參數傳遞校驗的方式,把接口測試異經常使用例抽取了出來,這個無論是在手工測試過程當中,仍是在自動化過程當中都很是的有用,能節省大量的人力成本。

固然這個方式也有必定的侷限性,須要整個團隊來配置,好比腳本中使用到的param_error_json就是由於博主所在項目組有比較規範的接口返回定義才能作這樣的統一斷言。

相關文章
相關標籤/搜索