Python自动化测试之异常及日志操作实例分享与用法解析
python自动化测试之异常及日志操作实例分析

更新时间为 2019 年 11 月 09 日 08 时 09 分 00 秒,作者是 Secret608。
这篇文章主要对 python 自动化测试中的异常及日志操作进行了介绍。它以实例形式,分析了在 python 自动化测试中异常捕获与日志记录的相关操作技巧。有需要的朋友可以参考一下。
本文讲述了关于 python 自动化测试中的异常以及日志操作这一实例。将其分享给大家以供参考,具体情况如下:
为了让自动化测试用例保持健壮性,异常的捕获以及处理很重要,日志的记录对于掌握自动化测试执行情况也很重要。这里就详细地介绍在自动化测试中所使用的异常以及日志,并且介绍它们的详细用法。
一、日志
打印日志对于很多程序来说是重要的需求,良好的日志输出能够让我们更便捷地检测程序的运行状态。Python 的标准库具备 logging 模块,需要记住的是 Logger 不能直接进行实例化,其好处是很明显的,接下来会逐步讲解 Logging 模块提供了两种记录日志的方式。
logging之模块级别的函数方式记录日志
import logging
设置日志,其中包含 filename、level、format、filemode、stream 这些元素。format 属性的内容极为丰富,若想详细了解其情况,可查看 API 文档,在此仅做简要的介绍。
设置日志的基本配置,将日志级别设置为 INFO 。
格式为:%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt = "%Y/%m%d %H%M%S",
filename = "log.txt")
#消息级别,五级
logging.debug("芹泽多摩雄")
logging.info("真")
logging.warning("男")
logging.error("人")
logging.critical("!")
日志系统的四大组件分别是日志器、处理器、过滤器和格式器,它们用于记录日志。
import logging
# 生成日志实例,日志器
logger 是获取名为 __name__ 的日志记录器。
#基本单元的配置(LEVER)
logger 把日志的级别设置成 INFO 。
创建了一个名为 formatter 的对象,它是 logging 模块中的 Formatter 类的实例。这个 formatter 用于设置日志的格式,其中包含了时间(%(asctime)s)、日志名(%(name)s)、日志级别(%(levelname)s)和日志消息(%(message)s)。
#生成管道分支,处理器
创建了一个名为 handler_1 的对象,它是 logging.FileHandler 的实例,用于将日志写入到 "log.txt" 文件中。
logging.StreamHandler 被赋值给了 handler_2 。
#自定义格式,格式器
handler_1 设置了格式化器 formatter ,其格式为“%Y-%m-%d %H:%M:%S”
handler_2 设置格式化器为 formatter ,格式化的时间格式为“%Y-%m-%d %H:%M:%S”
#对接分支管道与源头,处理器
logger.addHandler(handler_1)
logger.addHandler(handler_2)
层级结构中,logger 的名称呈现为一个以“.”进行分割的层级结构。每个“.”之后的 logger 都属于“.”之前的 logger 的 children(子项)。通常,它会与过滤器一同被使用。
#过滤器
#。。。。保留
#开始记录
logger.debug("芹泽多摩雄")
logger.info("真")
logger.warning("男")
logger.error("人")
logger.critical("!")
细心的朋友能够发现,logging 存在一个日志处理的主对象,其他的处理方式是通过 addHandler 来添加进去的。在这里,采用 logging.StreamHandler 能够实现将日志输出到流(控制台),同时也可以使用 FileHandler 来实现将日志输出到文件以及进行日志回滚。
import logging
日志处理程序中包含 RotatingFileHandler 类。它来自于 logging.handlers 模块。
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
定义一个 RotatingFileHandler ,它的备份文件数量最多为 3 个 ,并且每个日志文件的最大大小为 1K 。
rHandler 是 RotatingFileHandler,用于处理名为“log.txt”的文件,其最大字节数为 1*1024,备份数量为 3。
rHandler 将日志级别设置为 INFO 。
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rHandler 将 formatter 进行了设置。
console 是 logging 的 StreamHandler 。
console 将日志级别设置为 INFO 。
console 设定了格式化器为 formatter 。
logger.addHandler(rHandler)
logger.addHandler(console)
logger.debug("芹泽多摩雄")
logger.info("真")
logger.warning("男")
logger.error("人")
logger.critical("!")
多模块使用
#主模块
import logging
import subModule
创建一个名为 logger 的对象,该对象是通过调用 logging.getLogger("mainModule") 函数获取到的。
logger.setLevel(level = logging.INFO)
创建了一个名为 handler 的对象,该对象用于将日志记录到名为“log.txt”的文件中。
handler 把日志级别设置为 INFO 。
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler 设定了格式化器 formatter 。
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
#子模块
import logging
logging.getLogger("mainModule.sub") 被赋值给了 module_logger
class SubModuleClass(object):
def __init__(self):
创建了一个名为 self.logger 的日志记录器,它是从 logging.getLogger("mainModule.sub.module") 获取到的。
细心的朋友会再次察觉到,对 logger 的命名其实是很重要的。首先,在主模块中定义了 logger“mainModule”,并且对其进行了配置。子模块能够共享父 logger 的定义和配置。所谓的父子 logger 是通过命名来进行识别的,任意以“mainModule”开头的 logger 都是它的子 logger,比如“mainModule.sub”。
事实上,虽然存在继承配置或者自定义的配置日志功能,但是在实际的大项目中,这还是稍微有些麻烦的。这里主要是通过 JSON 或者 yaml 来进行配置封装,这样一来,加载该文件就能够加载日志的配置了。关于具体操作,下回再进行分解,最后再给出一个实例。
# -*- coding: utf-8 -*-
__author__ = 'Secret608'
import logging
import time
import os
import re
class Log(object):
初始化函数,参数为 loggerName 。
'''
进行日志初始化,包括存储路径、名称、级别、调用文件等
'''
#基本属性
获取名为 loggerName 的日志记录器,并将其赋值给 self.logger 。
self 的日志记录器将日志级别设置为警告级别。
#特有属性(文件地址+日志记录格式)
rq 等于 time.strftime 函数以 '%Y%m%d_%H%M%S' 的格式对 time.localtime(time.time()) 所返回的本地时间进行格式化后的结果
log_path 是通过将当前工作目录的父目录与 'logs' 拼接而得到的。具体来说,先获取当前工作目录的父目录,然后将其与 'logs' 进行拼接,最终得到的结果就是 log_path 。
log_title 是将 log_path 与 loggerName 加上 rq 进行拼接后再加上 ".log"所得到的结果
格式化器 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
创建一个名为 log 的对象,该对象是 logging.FileHandler 的实例,其参数为 log_title
log.setFormatter(formatter)
#加到基本属性中,得到一个完整的初始化对象
self.logger.addHandler(log)
def getLog(self):
return self.logger
def delLog(self, fileName):
log_path 是将当前工作目录的父目录与“logs”拼接而成的路径。即 log_path 等于 os.path.dirname(os.getcwd()) 与“logs”进行拼接后的结果。
使用 re 模块的 compile 函数创建了一个正则表达式对象 regexp,该正则表达式以 fileName 开头,后面跟着任意字符 s 以及任意其他字符。
使用 os.listdir 函数获取 log_path 路径下的文件列表并赋值给 filelist
try:
对于 filelist 中的每个 i,如果 regexp.match(i) 为 None,就执行 os.remove(os.path.join(log_path, i)) 操作。
except WindowsError:
pass
else:
return "ok"
if __name__ == "__main__":
a = Log("hah")
a.delLog("hah")
二、异常
异常捕获
# -*- coding: utf-8 -*-
#异常处理的语法:
try:
#执行可能出现异常的语句
except '异常名字':
#出现异常执行的语句
else:
#执行没有出现异常的语句
finally:
#异常与否都执行的语句
#demo
try:
a = 0
b = 1
c = b/a
print(c)
except ZeroDivisionError:
print("分母不能为0")
except NameError:
print("名称错误")
如果不是 ZeroDivisionError 或者 NameError 这种情况的话。
print("你的分母等于0或者变量名不存在")
except Exception as e:
你的变量名或者分母值本身是正确的,然而却出现了其他的错误,具体情况详见%s %e
d = 1
finally:
print("听说没有错误?不能忍,反正我要让你难受!")
if d == 1:
raise ValueError("你有其它错误")
else:
raise FuckError("开不开心?")
咦?什么是 FuckError 呢?看起来好像没有进行定义呀。现在在这里进行定义一下,之后再把它的位置移动到前面去。
class FuckError(Exception):
在定义的函数内部,通过给定的参数来进行初始化操作,这些参数包括位置参数 *args 和关键字参数 **keargs 。
super(FuckError, self).__int__() # 这是在 Python2 中的调用方式,使用 super 函数调用父类的 __int__ 方法,并传入参数 *args 和 **keargs
self.args = args
print(args)