💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 一、日志 ``` 1.1 什么是日志 说明:记录系统运行程序一些步骤,对一个事件(点击事件)也称为日志(Log) 1.2 特点 1.调试程序 2.定位跟踪bug 3.根据日志,查看系统运行是否出错 4.分析用户行为,与数据统计 1.3 级别 1.debug调 # 调试级别 2.info # 信息级别 3.warning # 警告 4.error # 错误级别 5.critica1 # 严重 提示: 1.开发常用以上 debug、info、warning、error 2.测试常用级别:info、error 1.4 Logging基本使用 步骤: 1. 导包 如: import 1ogging 2. 调用相应的级别方法,记录日志信息 1ogging.debug("debug...") 设置级别: logging.basicconfig(level=logging.DEBUG) 提示: 1. 默认级别为:1ogging.WARNING 2. 设置级别时调用的是1ogging文件夹下面的常量,而不是调用的小写方法; 3. 切记:设置级别以后,日志信息只会记录大于等于此级别的信息; ``` 实例: <details> <summary>test01_logging01.py</summary> ``` import logging # 设置日志级别 logging.basicConfig(level=logging.DEBUG) # 调用 指定级别,输入日志信息 logging.debug("this is a debug...") logging.info("this is a info...") logging.warning("this is a warning...") logging.error("this is a error...") logging.critical("this is a critical") ``` </details> <br /> <details> <summary>test02_logging02.py</summary> ``` import logging # 设置日志级别 # logging.basicConfig(level=logging.DEBUG) # 设置修改morning的输入日志格式 fm = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d] - %(message)s" # 设置日志保存到指定文件中 logging.basicConfig(level=logging.DEBUG, format=fm, filename="../log/log01.log") # 调用 指定级别,输入日志信息 logging.debug("this is a debug...") logging.info("this is a info...") logging.warning("this is a warning...") logging.error("this is a error...") logging.critical("this is a critical") ``` </details> <br /> ``` 1.5 1ogging 高级用法 1).为什么要使用高阶用法??? 1.中文乱码 2.无法同时输入到文件和控制台 2).1ogging组成 1. Logger 日志器 2. handler 处理器 3. formatter 格式器 4. fi1ter 过滤器 3).模块关系 日志器:提供了,记录日志的入口,如:1og.info("") 处理器:真正将日志器内容发送到控制台还是文件或网络,都是处理器干的;每个日志器都可以添加多个不同的处理器; 格式器:处理器可以设置不同的格式,就需要使用格式器; 过滤器:处理器需要过滤日志信息;就需要设置过滤器; ``` 实例: <details> <summary>test03_logger.py</summary> ``` import logging ''' 目标:logging底层 模块实现 1.logger ''' # 获取logger logger = logging.getLogger() # 设置级别 logger.setLevel(logging.INFO) # 获取控制台 处理器 sh = logging.StreamHandler() # 将处理器添加到 logger logger.addHandler(sh) # 输入信息 logger.info("info") logger.debug("debug") ``` </details> <br /> <details> <summary>test04_TimeRotatingFileHandler.py</summary> ``` ''' 目标:logging底层 模块实现 1.logger ''' # 注意:以后导logging包,不再使用此方式 # import logging # 导包时 导入import logging.handlers 推荐 # 原因:logging是包名,导入包名时会自动执行下面的 __init__文件,所以这样导入,相当于导入 logging # handlers是模块名 import logging.handlers from time import sleep # 获取logger logger = logging.getLogger("admin") # 设置级别 logger.setLevel(logging.INFO) # 获取控制台 处理器 sh = logging.StreamHandler() # 到文件 根据时间切割 th = logging.handlers.TimedRotatingFileHandler(filename="../log/logtime.log", when="M", interval=1, backupCount=3) # 添加格式器 fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d)] - %(message)s" fm = logging.Formatter(fmt) # 设置 处理器 级别 扩展 设置未error级别,那么只有error级别信息才会写入文件 th.setLevel(logging.ERROR) # 将格式器 添加到处理器中 sh.setFormatter(fm) th.setFormatter(fm) # 将控制台处理器添加到 logger logger.addHandler(sh) logger.addHandler(th) # while True: # sleep(1) # # 输入信息 # logger.info("info") # logger.debug("debug") logger.info("info") logger.debug("debug") logging.warning("warning") ``` </details> <br /> ``` 日志封装: # 定义获取日之类 # 定义类属性 1ogger = None @classemethod # 定义获取1ogger日志器的类方法 if c1s.1ogger is None: # 判断类属性1ogger是否还是为空,如果为空,就执行以下操作 # 获取日志器对象 # 设置日志器级别 # 获取控制台处理器 # 获取文件处理器 # 获取格式器 # 将格式器添加到处理器中 # 将处理器添加到日志器中 return 类属性1ogger 注意: 1.以上条件无论是否成立,最后都会返回类属性1ogger; 2.当第一次调用时,条件一定成立,将类属性1ogge设置不为空; 3.当第二次以上调用时,永远返回第一次设置的类属性对象。 ``` 实例: <details> <summary> test05_logger.py</summary> ``` # 日志封装 import logging.handlers class GetLogger: logger = None @classmethod def get_logger(cls): if cls.logger is None: # 获取 日志器 cls.logger = logging.getLogger("admin") # 设置级别 cls.logger.setLevel(logging.INFO) # 获取控制台 处理器 sh = logging.StreamHandler() # 到文件 根据时间切割 th = logging.handlers.TimedRotatingFileHandler(filename="../log/logtime.log", when="M", interval=1, backupCount=3, encoding="utf-8") # 设置格式器 fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d)] - %(message)s" fm = logging.Formatter(fmt) # 将格式器添加到 处理器 控制台 sh.setFormatter(fm) # 将格式器 添加到 处理器文 th.setFormatter(fm) # 将控制台处理器添加到 logger cls.logger.addHandler(sh) cls.logger.addHandler(th) return cls.logger if __name__ == '__main__': logger = GetLogger().get_logger() logger.info("info信息被执行") logger.debug("debug信息被执行") ``` </details> <br /> ## 二、项目 ``` 2.1自动化测试流程 1.将功能用例转化自动化用例(在功能用例模板新增一列是否自动化) 2.搭建自动化测试环境(本机依赖的环境: python、 pycharm、浏览器、浏览器驱动、se1enium、 parameterized 3.搭建自动化框架(po模式+数据驱动+1og+报告) 4.编写代码 5.执行用例 6.生成报告\分析1og 2.2自动化涉及的模块 1.登录 2.购物车 3.订单 4.支付 2.3自动化测试结构 1.base(基类) 2.page(页面对象) 3.scripts(业务脚本) 4.too1(工具类) 5.data(存储测试数据文件) 6.1og(日志) 7.image(失败截图) 8.report(测试报告) 2.4 base公共方法封装实现 # 查找元素方法 # 点击元素方法 # 输入元素方法 # 获取元素文本方法 # 截图方法 # 判断元素是否存在方法封 2.5 登录分析 0. 正确用户名+正确密码+正确验证码 预期:登录成功并跳转到个人主页 1. 用户名为空+正确密码+正确验证码 预期:用户名不能空 2. 正确用户名+空密码+正确验证码 预期:密码不能为空! 3. 正确用户名+正确密码+空验证码 预期:验证码不能为空 4. 用户名不存在+正确密码+正确验证码 预期:账号不存在 5. 用户名格式不正确+正确密码+正确验证码 预期:账号格式不匹配! 6. 正确用户名+错误密码+正确验证码 预期:密码错误! 7. 正确用户名+正确密码+错误验证码 预期:验证码错误! ``` ![DC57998D-AD59-468B-930F-EBFD833B4DC8.jpg](https://i.loli.net/2021/01/31/BJfvrcOH89sQtED.jpg) <details> <summary>base/base.py</summary> ``` from selenium.webdriver.support.wait import WebDriverWait import time class Base: def __init__(self, driver): self.driver = driver # 查找元素方法 封装 def base_find(self, loc, timeout=30, poll=0.5): # 使用显示等待 查找元素 WebDriverWait(self.driver, timeout=timeout, poll_frequency=poll).\ until(lambda x:x.find_element(*loc)) # 点击元素 方法封装 def base_click(self, loc): self.base_click(loc).click() # 输入元素 方法封装 def base_input(self, loc, value): # 获取元素 el = self.base_find(loc) el.clear() el.send_keys(value) # 获取文本信息 方法封装 def base_get_text(self, loc): return self.base_find(loc).text # 截图 方法封装 def base_get_image(self): self.driver.get_screenshot_as_file("../image{}.png". format(time.strftime("%Y_%m_%d %H_%M_%S"))) # 判断元素是否存在 方法封装 def base_element_is_exist(self, loc): try: self.base_find(loc, timeout=2) return True # 代表元素存在 except: return False # 代表元素不存在 ``` </details> <br />