测试工具类

测试工具类

1、base

class Base:
    def __init__(self, driver=None):
        if driver is None:
            log.info("正在初始化driver对象:{}".format(driver))
            self.driver = DriverUtils.get_admin_driver()
        else:
            self.driver = driver

    # 定位元素
    def base_find(self, loc, timeout=10, poll=0.5):
        log.info("正在查找元素:{}".format(loc))
        return WebDriverWait(self.driver, timeout, poll).until(EC.presence_of_element_located(loc))

    # 点击方法
    def base_click(self, loc):
        log.info("正在调用点击元素方法:{}".format(loc))
        # 获取元素
        self.base_find(loc).click()

    # 输入方法
    def base_input(self, loc, value):
        log.info("正在调用输入元素方法:{} 输入内容:{}".format(loc, value))
        # 获取元素
        el = self.base_find(loc)
        # 清空元素
        el.clear()
        # 输入
        el.send_keys(value)

    # 获取文本
    def base_text(self, loc):
        log.info("正在调用获取文本方法:{}".format(loc))
        return self.base_find(loc).text

    # 截图
    def base_screenshot(self):
        log.info("正在调用截图方法")
        # os.sep: \
        # img_path = DIR_PATH + os.sep + "img" + os.sep + "{}.png".format(time.strftime("%Y:%m:%d-%H:%M:%S"))
        self.driver.get_screenshot_as_file(DIR_PATH + "/img/{}.png".format(time.strftime("%Y:%m:%d-%H:%M:%S")))

    # 切换frame
    def base_switch_frame(self, loc):
        log.info("正在调用切换frame方法,切换对象:{}".format(loc))
        # 获取元素
        el = self.base_find(loc)
        # 切换
        self.driver.switch_to.frame(el)
    # 返回默认frame
    def base_default_frame(self):
        self.driver.switch_to.default_content()

    # 切换窗口
    def window(self, window_name):
        return self.driver.switch_to.window(window_name)

2、app_start_base

class Start(object):
    def __init__(self):
        # 定义字典变量
        self.desired_caps = {}
        # 字典追加启动参数 设备信息
        self.desired_caps["platformName"] = "Android"
        self.desired_caps["platformVersion"] = "5.1.1"
        self.desired_caps["deviceName"] = "127.0.0.1:62001"
        # app信息
        self.desired_caps["appPackage"] = "com.android.settings"
        self.desired_caps["appActivity"] = ".Settings"
        # 设置中文
        self.desired_caps["nicodeKeyboard"] = True
        self.desired_caps["resetKeyboard"] = True
        # 重置:全新首次使用app;不重置:记录用户之前行为
        self.desired_caps['noReset'] = False
        # toast uiautomator2
        self.desired_caps['automationName'] = 'uiautomator2'
        # 获取driver
        self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", self.desired_caps)
        self.driver.implicitly_wait(10)

3、common_assert

"""
定义 通用的 工具函数,实现断言
"""

def common_assert(resp, status_code, success, code, message):
    assert status_code == resp.status_code
    assert success is resp.json().get("success")
    assert code == resp.json().get("code")
    assert message in resp.json().get("message")

4、config

# 定义全局变量,获取项目路径
BASE_DIR = os.path.dirname(__file__)

5、db_tools

# 定义 数据库工具类
class DBTools(object):
    # 创建连接 - 类方法。可以直接使用类名调用!
    @classmethod
    def __create_conn(cls):
        conn = pymysql.connect(host="211.103.136.244", port=7061, user="student", password="iHRM_student_2021",
                               database="ihrm", charset="utf8")
        # 不能遗漏
        return conn

    # 查一条记录 - 封装为类方法,方便调用
    @classmethod
    def query_one(cls, sql):
        my_conn = None
        my_cursor = None
        res = None
        try:
            # 创建连接, 借助类名,调用 类方法 create_conn
            my_conn = DBTools.__create_conn()
            # 创建游标
            my_cursor = my_conn.cursor()
            # 执行 sql 语句,做查询
            my_cursor.execute(sql)
            # 提取一条记录
            res = my_cursor.fetchone()
        except Exception as err:
            print("执行查询SQL失败:", str(err))
        finally:
            # 关闭游标
            my_cursor.close()
            # 关闭连接
            my_conn.close()
            # 返回查询结果
            return res

    # 增删改记录
    @classmethod
    def db_uid(cls, sql):
        my_conn = None
        my_cursor = None
        try:
            # 创建连接
            my_conn = DBTools.__create_conn()
            # 创建游标
            my_cursor = my_conn.cursor()
            # 执行 增删改 语句
            my_cursor.execute(sql)
            print("Affected rows:", my_conn.affected_rows())
            # 提交事务
            my_conn.commit()
        except Exception as err:
            print("执行 增删改 SQL 失败:", str(err))
            # 回滚事务
            my_conn.rollback()
        finally:
            # 关闭游标
            my_cursor.close()
            # 关闭连接
            my_conn.close()


if __name__ == '__main__':
    # result = DBTools.query_one("select * from t_hero;")
    # print("查询语句的结果:", result)

    # DBTools.db_uid("update t_book set `read` = 100 where id = 3;")

6、日志

def init_log_config(filename, when='midnight', interval=1, backup_count=7):
    """
    功能:初始化日志配置函数
    :param filename: 日志文件名
    :param when: 设定日志切分的间隔时间单位
    :param interval: 间隔时间单位的个数,指等待多少个 when 后继续进行日志记录
    :param backup_count: 保留日志文件的个数
    :return:
    """
    # 1. 创建日志器对象
    logger = logging.getLogger()

    # 2. 设置日志打印级别
    logger.setLevel(logging.DEBUG)
    # logging.DEBUG 调试级别
    # logging.INFO 信息级别
    # logging.WARNING 警告级别
    # logging.ERROR 错误级别
    # logging.CRITICAL 严重错误级别

    # 3. 创建处理器对象
    # 控制台对象
    st = logging.StreamHandler()
    # 日志文件对象
    fh = logging.handlers.TimedRotatingFileHandler(filename,
                                                   when=when,
                                                   interval=interval,
                                                   backupCount=backup_count,
                                                   encoding='utf-8')

    # 4. 日志信息格式
    fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
    formatter = logging.Formatter(fmt)

    # 5. 给处理器设置日志信息格式
    st.setFormatter(formatter)
    fh.setFormatter(formatter)

    # 6. 给日志器添加处理器
    logger.addHandler(st)
    logger.addHandler(fh)


if __name__ == '__main__':
    # 初始化日志
    init_log_config(BASE_DIR + '/log/sh27.log', interval=3, backup_count=5)

    # 打印输出日志信息
    logging.debug('我是一个调试级别的日志')
    logging.info("AAA BBB CCC")
    logging.error("xxxx 错误。。")

7、read_json

# 定义工具函数,读取json文件中的数据,转换成 [(),(),()] 格式数据
def read_json_data(filename):
    with open(filename, "r", encoding="utf8") as f:
        json_data = json.load(f)
        login_list = []
        for data in json_data:
            tmp = tuple(data.values())
            login_list.append(tmp)

        return login_list

if __name__ == '__main__':
    # res = read_json_data("../data/login_data.json")
    filename = BASE_DIR + "/data/login_data.json"
    res = read_json_data(filename)
    print(res)

8、write_json

def write_json(value):
    file_path = DIR_PATH + "/data/" + "expect.json"
    with open(file_path, "w", encoding="utf-8") as f:
        data = {"expect": [{"desc": "app订单编号", "order_no": value}]}
        json.dump(data, f)

9、get_el_text

# 函数: 公用的获取任意元素文本
def get_el_text(driver, xpath_str):
    # 获取元素文本
    try:
        msg = WebDriverWait(driver, 10, 1). \
            until(lambda x: x.find_element(By.XPATH, xpath_str).text)
        print(msg)
    except Exception as e:
        logging.error(f"没有获取到{xpath_str}的元素对象文本!")
        msg = None
    # 返回获取的文本
    return msg

10、el_is_exist_by_text

# 函数: 根据文本判断当前页面是否有对应的元素对象
def el_is_exist_by_text(driver, is_app, key_text):
    """
    :param driver: 浏览器对象
    :param is_app: 判断是否是app
    :param key_text: 要判断的文本
    :return:
    """
    # 判断是否是app
    if is_app:
        xpath_str = f"//*[@text='{key_text}']"
    else:
        xpath_str = f"//*[text()='{key_text}']"
    # 根据本次新增的联系人信息的文本, 到界面上找元素,如能找到则代表新增成功找不到则失败截图
    try:
        # 如找到元素对象则把元素对象赋值给is_suc
        is_suc = WebDriverWait(driver, 10, 1). \
            until(lambda x: x.find_element(By.XPATH, xpath_str))
    except Exception as e:
        # 找不到则给is_suc赋值为False
        is_suc = False
        # 截图
        driver.get_screenshot_as_file(f"{key_text}未找到.png")
        logging.error(f"未找到文本为{key_text}的元素对象!")
    # 返回是否找到结果
    return is_suc
posted @ 2025-07-01 11:31  MGLblog  阅读(17)  评论(0)    收藏  举报