123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- # -*- coding: utf-8 -*-
- """
- 这是接口关键字驱动类,用于提供自动化接口测试的关键字方法。
- 主要是实现常用的关键字内容,并定义好所有的参数内容即可
- 接口中常用关键字:
- 1.各种模拟请求方法:Post/get/put/delete/header/....
- 2.根据需求进行断言封装:jsonpath、数据库断言
- 3.集合Allure,可添加@allure.step,这样在自动化执行的时候
- Allure报告可以直接捕捉相关的执行信息,让测试报告更详细
- """
- import json
- import random
- from apirun.Log.Log import logger
- import allure
- import requests
- import jsonpath
- from apirun.core.globalContext import g_context
- from deepdiff import DeepDiff
- from Crypto.Cipher import AES
- from Crypto.Util.Padding import pad, unpad
- import base64
- class KeyWords:
- request = None
- @allure.step("参数数据:发送Post请求")
- def request_post(self, **kwargs):
- response = requests.post(**kwargs)
- # TODO: 扩展- 把对应的响应数据写到变量渲染中
- g_context().set_dict("current_response", response) # 默认设置成变量渲染
- return response
- @allure.step("参数数据:发送Get请求")
- def request_get(self, **kwargs):
- url = kwargs.get("URL", None)
- params = kwargs.get("PARAMS", None)
- headers = kwargs.get("HEADERS", None)
- request_data = {
- "url": url,
- "params": params,
- "headers": headers,
- }
- response = requests.get(**request_data)
- g_context().set_dict("current_response", response)
- return response
- @allure.step("参数数据:发送Post请求-form_urlencoded")
- def request_post_form_urlencoded(self, **kwargs):
- """
- 发送Post请求
- """
- url = kwargs.get("URL", None)
- params = kwargs.get("PARAMS", None)
- headers = kwargs.get("HEADERS", None)
- data = kwargs.get("DATA", None)
- request_data = {
- "url": url,
- "params": params,
- "headers": headers,
- "data": data,
- }
- response = requests.post(**request_data)
- g_context().set_dict("current_response", response)
- return response
- @allure.step("参数数据:发送Post请求-row_json")
- def request_post_row_json(self, **kwargs):
- """
- 发送Post请求
- """
- url = kwargs.get("URL", None)
- params = kwargs.get("PARAMS", None)
- headers = kwargs.get("HEADERS", None)
- data = kwargs.get("DATA", None)
- request_data = {
- "url": url,
- "params": params,
- "headers": headers,
- "json": data,
- }
- response = requests.post(**request_data)
- g_context().set_dict("current_response", response) # 默认设置成全局变量
- return response
- @allure.step("参数数据:发送Post请求-form_data")
- def request_post_form_data(self, **kwargs):
- """
- 发送Post请求
- """
- url = kwargs.get("URL", None)
- files = kwargs.get("FILES", None)
- params = kwargs.get("PARAMS", None)
- headers = kwargs.get("HEADERS", None)
- data = kwargs.get("DATA", None)
- request_data = {
- "url": url,
- "params": params,
- "headers": headers,
- "data": data,
- "files": eval(files) # 变成字典格式
- }
- response = requests.post(**request_data)
- g_context().set_dict("current_response", response) # 默认设置成全局变量
- return response
- @allure.step("参数数据:发送Delete请求")
- def request_delete(self, **kwargs):
- """
- 发送Post请求
- """
- url = kwargs.get("URL", None)
- params = kwargs.get("PARAMS", None)
- headers = kwargs.get("HEADERS", None)
- data = kwargs.get("DATA", None)
- request_data = {
- "url": url,
- "params": params,
- "headers": headers,
- "json": data,
- }
- response = requests.delete(**request_data)
- g_context().set_dict("current_response", response) # 默认设置成全局变量
- return response
- # TODO: 扩展 - JAONPATH提取的方法
- @allure.step("参数数据:提取响应数据并存储")
- def ex_jsonData(self, **kwargs):
- """
- 提取json数据
- EXVALUE:提取josn的表达式
- INDEX: 非必填,默认为0,all代表所有
- VARNAME:存储的变量名,方便后面使用
- """
- # 获取JsonPath的值
- EXPRESSION = kwargs.get("EXVALUE", None)
- # 获取对应的下标,非必填,默认为0
- INDEX = kwargs.get("INDEX", 0)
- if INDEX is None:
- INDEX = 0
- # 获取响应数据
- response = g_context().get_dict("current_response").json()
- if INDEX == "all":
- ex_data = jsonpath.jsonpath(response, EXPRESSION)
- else:
- ex_data = jsonpath.jsonpath(response, EXPRESSION)[INDEX] # 通过JsonPath进行提取
- g_context().set_dict(kwargs["VARNAME"], ex_data) # 根据变量名设置成变量渲染
- return ex_data
- # TODO: 扩展 - 数据库提取的方法
- @allure.step("参数数据:提取数据库数据并存储")
- def ex_mysqlData(self, **kwargs):
- """
- 数据库 : 数据库的名称
- 引用变量:数据库要存储的变量名,列表格式
- 存储到全局变量:{“变量名_下标”:数据}
- """
- import pymysql
- from pymysql import cursors
- config = {"cursorclass": cursors.DictCursor}
- # 读取全局变量 - 根据选择的数据 读取指定的数据库配置 连接对应的数据库
- db_config = g_context().get_dict("_database")[kwargs["数据库"]]
- config.update(db_config)
- con = pymysql.connect(**config)
- cur = con.cursor()
- cur.execute(kwargs["SQL"])
- rs = cur.fetchall()
- cur.close()
- con.close()
- logger.info("数据库查询结果:", rs)
- var_names = kwargs["引用变量"].split(",")
- result = {}
- for i, data in enumerate(rs, start=1):
- for j, value in enumerate(var_names):
- result[f'{var_names[j]}_{i}'] = data.get(var_names[j]) # 根据变量名称找读取出来的内容
- g_context().set_by_dict(result)
- # TODO: 扩展 - 文本断言方法
- @allure.step("参数数据:断言当前文本内容")
- def assert_text_comparators(self, **kwargs):
- """
- 封装断言以进行不同的比较操作。
- 参数:
- value (Any): 要比较的值。
- expected (Any): 预期的值。
- op_str (str): 操作符的字符串表示(如 '>', '<', '==' 等)。
- message (str, optional): 自定义的错误消息。
- 返回:
- None: 如果断言成功,则不返回任何内容。
- 引发:
- AssertionError: 如果断言失败。
- """
- comparators = {
- '>': lambda a, b: a > b,
- '<': lambda a, b: a < b,
- '==': lambda a, b: a == b,
- '>=': lambda a, b: a >= b,
- '<=': lambda a, b: a <= b,
- '!=': lambda a, b: a != b,
- }
- message = kwargs.get("MESSAGE", None)
- if kwargs["OP_STR"] not in comparators:
- raise ValueError(f"没有该操作方式: {kwargs['OP_STR']}")
- if not comparators[kwargs['OP_STR']](kwargs['VALUE'], kwargs["EXPECTED"]):
- if message:
- raise AssertionError(message)
- else:
- raise AssertionError(f"{kwargs['VALUE']} {kwargs['OP_STR']} {kwargs['EXPECTED']} 失败")
- # TODO: 扩展 - 全量断言-对比两个Json的差异
- @allure.step("参数数据:全量断言-对比两个Json的差异")
- def assert_json_DeepDiff(self, **kwargs):
- """
- 对比两个json的差异
- :param json1: 期望结果
- :param json2: 实际结果
- :param exclude_paths:需要排除的字段,集合的类型,比如{“id”,...}
- :param ignore_order: 忽略顺序,一般用户有序数据类型,比如列表
- :param ignore_string_case:忽略值的大小写,False
- :return: 当数据没有差异则返回空集合
- """
- json1 = kwargs["json1"]
- json2 = kwargs["json2"]
- exclude_paths = kwargs.get("过滤字段", None)
- ignore_order = kwargs.get("忽略顺序", None)
- ignore_string_case = kwargs.get("忽略大小写", False)
- screen_data = {"exclude_paths": exclude_paths, "ignore_order": ignore_order,
- "ignore_string_case": ignore_string_case}
- diff = DeepDiff(json1, json2, **screen_data)
- assert not diff, f"全量断言失败:{diff}"
- # TODO: 扩展 - 加密处理
- @allure.step("参数数据:对数据进行AES加密处理")
- def encrypt_aes(self, **kwargs):
- """
- 对数据进行AES加密
- :param data: 需要加密的数据
- :param VARNAME: 存储到全局变量的名称
- :return:
- """
- key = b"1234567812345678" # key 密码
- data = kwargs["data"].encode('utf-8')
- cipher = AES.new(key, AES.MODE_ECB) # 使用ECB模式
- ct_bytes = cipher.encrypt(pad(data, AES.block_size)) # 使用PKCS7填充,初始化数据块大小, 16位
- encrypt_data = base64.b64encode(ct_bytes).decode('utf-8')
- g_context().set_dict(kwargs["VARNAME"], encrypt_data) # 根据变量名设置成变量
- # ----------------------实战扩展方法------------------------------
- @allure.step("参数数据:对数据进行AES加密处理")
- def generate_name(self, **kwargs):
- data = "hami" + str(random.randint(0, 9999))
- g_context().set_dict(kwargs["VARNAME"], data) # 根据变量名设置成变量
- # TODO: 扩展 - JSOND断言方法
- @allure.step("参数数据:JSOND断言文本内容")
- def assert_json_comparators(self, **kwargs):
- """
- 封装断言以进行不同的比较操作。
- 参数:
- value (Any): 要比较的jsonPath值。
- expected (Any): 预期的值。
- op_str (str): 操作符的字符串表示(如 '>', '<', '==' 等)。
- message (str, optional): 自定义的错误消息。
- 返回:
- None: 如果断言成功,则不返回任何内容。
- 引发:
- AssertionError: 如果断言失败。
- """
- comparators = {
- '>': lambda a, b: a > b,
- '<': lambda a, b: a < b,
- '==': lambda a, b: a == b,
- '>=': lambda a, b: a >= b,
- '<=': lambda a, b: a <= b,
- '!=': lambda a, b: a != b,
- }
- message = kwargs.get("MESSAGE", None)
- if kwargs["OP_STR"] not in comparators:
- raise ValueError(f"没有该操作方式: {kwargs['OP_STR']}")
- # 通过jsonpath获取对应的数据
- # 获取响应数据
- response = g_context().get_dict("current_response").json()
- ex_data = jsonpath.jsonpath(response, kwargs['VALUE'])[0] # 默认就取第一个
- if not comparators[kwargs['OP_STR']](ex_data, kwargs["EXPECTED"]):
- if message:
- raise AssertionError(message)
- else:
- raise AssertionError(f"{ex_data} {kwargs['OP_STR']} {kwargs['EXPECTED']} 失败")
|