Web UI自动化测试之日志收集篇

优采云 发布时间: 2022-05-11 11:05

  Web UI自动化测试之日志收集篇

  本文大纲截图:

  

  1、日志介绍

  日志: 用于记录系统运行时的信息,对一个事件的记录,也称为Log。

  日志作用:

  日志级别:

  日志级别:指日志信息的优先级、重要性或者严重程度。

  常见的日志级别: DEBUG、INFO、WARNING、ERROR、CRITICAL

  import logging<br /><br /><br />logging.debug("这是一条调试信息")<br />logging.info("这是一条普通信息")<br />logging.warning("这是一条警告信息")<br />logging.error("这是一条错误信息")<br />logging.critical("这是一条严重错误信息")<br />

  说明:

  2、日志用法2.1 基本用法

  设置日志级别:

  设置日志格式:

  代码示例:

  import logging<br /><br />fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'<br />logging.basicConfig(level=logging.INFO, format=fmt)<br /><br />logging.debug("调试")<br />logging.info("信息")<br />logging.warning("警告")<br />logging.error("错误")<br />

  将日志信息输出到文件中

  import logging<br /><br />fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'<br />logging.basicConfig(filename="a.log", level=logging.INFO, format=fmt)<br /><br />logging.debug("调试")<br />logging.info("信息")<br />logging.warning("警告")<br />logging.error("错误")<br />

  2.2 高级用法

  logging日志模块四大组件: Logger、Handler、Formatter、Filter

  组件关系:

  Logger类:

  Logger常用的方法:

  设置日志级别:logger.setLevel(),设置日志器将会处理的日志消息的最低严重级别

  添加handler对象:logger.addHandler(),为该logger对象添加一个handler对象

  添加filter对象:logger.addFilter(),为该logger对象添加一个filter对象

  Handler类:

  Handler常用的方法:

  Formatter类:

  将日志信息同时输出到控制台和文件中:

  定义日志格式:

  # 设置日志格式<br />fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'<br /># 创建格式化器对象<br />formatter = logging.Formatter(fmt)<br />

  logger = logging.getLogger()<br />sh = logging.StreamHandler()<br />sh.setFormatter(formatter)<br />logger.addHandler(sh)<br />

  fh = logging.FileHandler("./b.log")<br />fh.setFormatter(formatter)<br />logger.addHandler(fh)<br />

  每日生成一个日志文件:

  fh = logging.handlers.TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0)<br />    # 将日志信息记录到文件中,以特定的时间间隔切换日志文件。<br />    # filename: 日志文件名<br />    # when: 时间单位,可选参数<br />    #     S - Seconds<br />    #     M - Minutes<br />    #     H - Hours<br />    #     D - Days<br />    #     midnight - roll over at midnight<br />    #     W{0-6} - roll over on a certain day; 0 - Monday<br />    # interval: 时间间隔<br />    # backupCount: 日志文件备份数量。<br />    #     如果backupCount大于0,那么当生成新的日志文件时,将只保留backupCount个文件,删除最老的文件。<br />

  import logging.handlers<br /><br /><br />logger = logging.getLogger()<br />logger.setLevel(logging.DEBUG)<br /><br /># 日志格式<br />fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"<br />formatter = logging.Formatter(fmt)<br /><br /># 输出到文件,每日一个文件<br />fh = logging.handlers.TimedRotatingFileHandler("./a.log", when='MIDNIGHT', interval=1, backupCount=3)<br />fh.setFormatter(formatter)<br />fh.setLevel(logging.INFO)<br />logger.addHandler(fh)<br />

  日志封装成工具(tools):

  # 导包<br />import logging.handlers<br /><br /><br /># 定义日志器方法 ,封装日志<br />def get_logger():<br />    # 获取 日志器logger,并设置名称admin<br />    logger = logging.getLogger("admin")<br />    # 设置日志级别为info<br />    logger.setLevel(logging.INFO)<br />    # 获取 控制台处理器<br />    sh = logging.StreamHandler()<br />    # 获取 文件处理器,根据时间分割<br />    th = logging.handlers.TimedRotatingFileHandler(filename="../log/logger.log", when="S",  interval=1, backupCount=2, encoding="utf-8")<br />    # 设置 文件处理器 日志级别<br />    th.setLevel(logging.ERROR)<br />    # 获取 格式器<br />    fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s %(lineno)d)] - %(message)s"<br />    fm = logging.Formatter(fmt)<br />    # 将 格式器 添加到 处理器中<br />    sh.setFormatter(fm)<br />    th.setFormatter(fm)<br />    # 将 处理器 添加到 日志器中<br />    logger.addHandler(sh)<br />    logger.addHandler(th)<br />    # 返回 logger<br />    return logger<br /><br /><br />if __name__ == '__main__':<br />    logger = get_logger()<br />    # 日志器应用<br />    logger.info("这是info信息")<br />    logger.warning("这是warning信息")<br />    logger.error("这是error信息")<br />

  3、日志应用

  日志应用:PO模式中,在base操作层、page对象层、scripts业务层都可添加日志,以及将日志用单例模式封装成工具类放在tools文件夹中。

  import time<br />from time import sleep<br />from selenium.webdriver.support.wait import WebDriverWait<br />from day11_tpshop import page<br />from day11_tpshop.base.get_logger import GetLogger<br /><br /># 获取log日志器<br />log = GetLogger().get_logger()<br /><br /><br />class Base:<br />    def __init__(self, driver):<br />        log.info("[base:]正在获取初始化driver对象:{}".format(driver))<br />        self.driver = driver<br /><br />    # 查找元素方法 封装<br />    def base_find(self, loc, timeout=30, poll=0.5):<br />        log.info("[base]:正在定位:{}元素,默认定位超时时间为:{}".format(loc, timeout))<br />        # 使用显式等待 查找元素<br />        return WebDriverWait(self.driver,<br />                             timeout=timeout,<br />                             poll_frequency=poll).until(lambda x: x.find_element(*loc))<br /><br />    # 点击元素方法 封装<br />    def base_click(self, loc):<br />        log.info("[base]:正在对:{}元素执行点击事件".format(loc))<br />        self.base_find(loc).click()<br /><br />    # 输入元素方法 封装<br />    def base_input(self, loc, value):<br />        log.info("[base]:正在获取:{}元素".format(loc))<br />        # 获取元素<br />        el = self.base_find(loc)<br />        log.info("[base]:正在对:{}元素执行清空操作".format(loc))<br />        # 输入前 清空<br />        el.clear()<br />        log.info("[base]:正在给{}元素输入内容:{}".format(loc, value))<br />        # 输入<br />        el.send_keys(value)<br /><br />    # 获取文本信息方法 封装<br />    def base_get_text(self, loc):<br />        log.info("[base]:正在获取{}元素文本值".format(loc))<br />        return self.base_find(loc).text<br /><br />    # 截图方法 封装<br />    def base_get_img(self):<br />        log.info("[base]:断言出错,调用截图")<br />        self.driver.get_screenshot_as_file("../image/{}.png".format(time.strftime("%Y_%m_%d %H_%M_%S")))<br /><br />    # 判断元素是否存在方法 封装<br />    def base_elememt_is_exist(self, loc):<br />        try:<br />            self.base_find(loc, timeout=2)<br />            log.info("[base]:{}元素查找成功,存在页面".format(loc))<br />            return True  # 代表元素存在<br />        except:<br />            log.info("[base]:{}元素查找失败,不存在当前页面".format(loc))<br />            return False  # 代表元素不存在<br /><br />    # 回到首页(购物车、下订单、支付)都需要用到此方法<br />    def base_index(self):<br />        # 暂停2秒<br />        sleep(2)<br />        log.info("[base]:正在打开首页")<br />        self.driver.get(page.URL)<br /><br />    # 切到frame表单方法 以元素属性切换<br />    def base_switch_frame(self, element):<br />        log.info("[base]:正在切换到frame表单")<br />        self.driver.switch_to.frame(element)<br /><br />    # 回到默认目录方法<br />    def base_default_content(self):<br />        log.info("[base]:正在返回默认目录")<br />        self.driver.switch_to.default_content()<br /><br />    # 切换窗口方法<br />    def base_switch_to_window(self, title):<br />        log.info("正在执行切换title值为:{}窗口".format(title))<br />        self.base_get_title_handle(title)<br />        # self.driver.switch_to.window(self.base_get_title_handle(title))<br /><br />    # 获取指定title页面的handle方法<br />    def base_get_title_handle(self, title):<br />        # 获取当前页面所有的handles<br />        handles = self.driver.window_handles<br />        # 遍历handle<br />        for handle in handles:<br />            log.info("正在遍历handles:{}-->{}".format(handle, handles))<br />            # 切换 handle<br />            self.driver.switch_to.window(handle)<br />            log.info("切换:{}窗口".format(handle))<br />            # 获取当前页面title 并判断 是否等于 指定参数title<br />            log.info("条件成立!返回当前handle{}".format(handle))<br />            if self.driver.title == title:<br />                # 返回 handle<br />                return handle<br />

  from day11_tpshop import page<br />from day11_tpshop.base.base import Base<br />from day11_tpshop.base.get_logger import GetLogger<br /><br /># 获取log日志器<br />log = GetLogger().get_logger()<br /><br /><br />class PageLogin(Base):<br />    # 点击 登录链接<br />    def page_click_login_link(self):<br />        log.info("[page_login]:执行{}元素点击链接操作".format(page.login_link))<br />        self.base_click(page.login_link)<br /><br />    # 输入用户名<br />    def page_input_username(self, username):<br />        log.info("[page_login]:对{}元素 输入用户名{}操作".format(page.login_username, username))<br />        self.base_input(page.login_username, username)<br /><br />    # 输入密码<br />    def page_input_pwd(self, pwd):<br />        log.info("[page_login]:对{}元素 输入密码{}操作".format(page.login_pwd, pwd))<br />        self.base_input(page.login_pwd, pwd)<br /><br />    # 输入验证码<br />    def page_input_verify_code(self, verify_code):<br />        log.info("[page_login]:对{}元素 输入验证码{}操作".format(page.login_verify_code, verify_code))<br />        self.base_input(page.login_verify_code, verify_code)<br /><br />    # 点击 登录<br />    def page_click_login_btn(self):<br />        log.info("[page_login]:执行{}元素点击操作".format(page.login_btn))<br />        self.base_click(page.login_btn)<br /><br />    # 获取 错误提示信息<br />    def page_get_err_info(self):<br />        return self.base_get_text(page.login_err_info)<br /><br />    # 点击 错误提示框 确定按钮<br />    def page_click_error_alert(self):<br />        log.info("[page_login]:执行{}元素点击操作".format(page.login_err_ok_btn))<br />        self.base_click(page.login_err_ok_btn)<br /><br />    # 判断是否登录成功<br />    def page_if_login_success(self):<br />        # 注意 一定要将找元素的结果返回,True:存在<br />        return self.base_elememt_is_exist(page.login_logout_link)<br /><br />    # 点击 安全退出<br />    def page_click_logout_link(self):<br />        self.base_click(page.login_logout_link)<br /><br />    # 判断是否退出成功<br />    def page_if_logout_success(self):<br />        return self.base_elememt_is_exist(page.login_link)<br /><br />    # 组合业务方法 登录业务直接调用<br />    def page_login(self, username, pwd, verify_code):<br />        log.info("[page_login]:正在执行登录操作,用户名:{},密码:{},验证码:{}".format(username, pwd, verify_code))<br />        self.page_input_username(username)<br />        self.page_input_pwd(pwd)<br />        self.page_input_verify_code(verify_code)<br />        self.page_click_login_btn()<br /><br />    # 组合登录业务方法 给(购物车模块、订单模块、支付模块)依赖登录使用<br />    def page_login_success(self, username="13800001111", pwd="123456", verify_code="8888"):<br />        # 点击登录链接<br />        self.page_click_login_link()<br />        log.info("[page_login]:正在执行登录操作,用户名:{},密码:{},验证码:{}".format(username, pwd, verify_code))<br />        self.page_input_username(username)<br />        self.page_input_pwd(pwd)<br />        self.page_input_verify_code(verify_code)<br />        self.page_click_login_btn()<br />

  import unittest<br />from day11_TPshop项目.base.get_driver import GetDriver<br />from day11_TPshop项目.base.get_logger import GetLogger<br />from day11_TPshop项目.page.page_login import PageLogin<br />from day11_TPshop项目.tools.read_txt import read_txt<br />from parameterized import parameterized<br /><br /># 获取log日志器<br />log = GetLogger().get_logger()<br /><br /><br />def get_data():<br />    arrs = []<br />    for data in read_txt("login.txt"):<br />        arrs.append(tuple(data.strip().split(",")))<br />    return arrs[1:]<br /><br /><br /># 新建 登录测试类 并 继承 unittest.TestCase<br />class TestLogin(unittest.TestCase):<br />    # 新建 setUpClass<br />    @classmethod<br />    def setUpClass(cls) -> None:<br />        try:<br />            # 实例化 并获取 driver<br />            cls.driver = GetDriver.get_driver()<br />            # 实例化 PageLogin()<br />            cls.login = PageLogin(cls.driver)<br />            # 点击登录链接<br />            cls.login.page_click_login_link()<br />        except Exception as e:<br />            # 截图<br />            cls.login.base_get_img()<br />            # 日志<br />            log.error("错误:{}".format(e))<br /><br />    # 新建 tearDownClass<br />    @classmethod<br />    def tearDownClass(cls) -> None:<br />        # 关闭driver驱动对象<br />        GetDriver.quit_driver()<br /><br />    # 新建 登录测试方法<br />    @parameterized.expand(get_data())<br />    def test_login(self, username, pwd, verify_code, expect_result, status):<br />        try:<br />            # 调用 登录业务方法<br />            self.login.page_login(username, pwd, verify_code)<br /><br />            # 判断是否为正向<br />            if status == "true":<br />                # 断言是否登录成功<br />                try:<br />                    self.assertTrue(self.login.page_if_login_success())<br />                except Exception as e:<br />                    # 截图<br />                    self.login.base_get_img()<br />                    # 日志<br />                    log.error("出错了:{}".format(e))<br />                # 点击 安全退出<br />                self.login.page_click_logout_link()<br />                # 点击 登录链接<br />                self.login.page_click_login_link()<br />            # 逆向用例<br />            else:<br />                # 获取错误提示信息<br />                msg = self.login.page_get_err_info()<br />                print("msg:", msg)<br />                try:<br />                    self.assertEqual(msg, expect_result)<br />                except Exception as e:<br />                    # 截图<br />                    self.login.base_get_img()<br />                    # 日志<br />                    log.error("出错了:{}".format(e))<br />                # 点击错误提示框 确定按钮<br />                self.login.page_click_error_alert()<br />        except Exception as e:<br />            # 截图<br />            self.login.base_get_img()<br />            # 日志<br />            log.error("出错了:{}".format(e))<br />

  import logging.handlers<br />import time<br /><br /><br />class GetLogger:<br />    logger = None<br /><br />    # 获取logger<br />    @classmethod<br />    def get_logger(cls):<br />        if cls.logger is None:<br />            # 获取 logger 日志器 并设置名称为“admin”<br />            cls.logger = logging.getLogger("admin")<br />            # 设置日志级别<br />            cls.logger.setLevel(logging.INFO)<br />            # 获取 控制台处理器<br />            sh = logging.StreamHandler()<br />            # 获取 文件处理器 根据时间分割<br />            th = logging.handlers.TimedRotatingFileHandler(<br />                filename="../log/{}.log".format(time.strftime("%Y_%m_%d %H_%M_%S")),<br />                when="S",<br />                interval=1,<br />                backupCount=3,<br />                encoding="utf-8")<br />            # 设置 文件处理器 日志级别<br />            th.setLevel(logging.ERROR)<br />            # 获取 格式器<br />            fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s %(funcName)s %(lineno)d] - %(message)s"<br />            fm = logging.Formatter(fmt)<br />            # 将 格式器 添加到 处理器<br />            sh.setFormatter(fm)<br />            th.setFormatter(fm)<br />            # 将 处理器 添加到 日志器<br />            cls.logger.addHandler(sh)<br />            cls.logger.addHandler(th)<br />        # 返回日志器<br />        return cls.logger<br /><br /><br />if __name__ == '__main__':<br />    logger = GetLogger.get_logger()<br />    # 日志器应用<br />    logger.info("这是info日志信息")<br />    logger.debug("这是debug日志信息")<br />    logger.warning("这是warning日志信息")<br />    logger.error("这是error日志信息")<br />

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线