python自动化测试之异常及日志操作实例分析


Posted in Python onNovember 09, 2019

本文实例讲述了python自动化测试之异常及日志操作。分享给大家供大家参考,具体如下:

为了保持自动化测试用例的健壮性,异常的捕获及处理,日志的记录对掌握自动化测试执行情况尤为重要,这里便详细的介绍下在自动化测试中使用到的异常及日志,并介绍其详细的用法。

一、日志

打印日志是很多程序的重要需求,良好的日志输出可以帮我们更方便的检测程序运行状态。Python标准库提供了logging模块,切记Logger从来不直接实例化,其好处不言而喻,接下来慢慢讲解Logging模块提供了两种记录日志的方式。

  1. logging之模块级别的函数方式记录日志
import logging
#设置日志,包括filename、level、format、filemode、stream,其中format属性极其丰富,详情可查看API文档,这里只做简要介绍
logging.basicConfig(level = logging.INFO,
format = '%(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("!")
  1.   logging之日志系统的四大组件(日志器、处理器、过滤器、格式器)方式记录日志
import logging
# 生成日志实例,日志器
logger = logging.getLogger(__name__)
#基本单元的配置(LEVER)
logger.setLevel(level = logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
#生成管道分支,处理器
handler_1 = logging.FileHandler("log.txt")
handler_2 = logging.StreamHandler()
#自定义格式,格式器
handler_1.setFormater(formatter, “%Y-%m-%d %H:%M:%S”)
handler_2.setFormater(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("!")
  1. 细心的盆友又可以发现,可以发现,logging有一个日志处理的主对象,其他处理方式都是通过addHandler添加进去,这里采用logging.StreamHandler实现日志输出到流(控制台),也可以用FileHandler实现日志输出到文件
  2. 日志回滚
import logging
from logging.handlers import RotatingFileHandler
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
#定义一个RotatingFileHandler,最多备份3个日志文件,每个日志文件最大1K
rHandler = RotatingFileHandler("log.txt",maxBytes = 1*1024,backupCount = 3)
rHandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
rHandler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(rHandler)
logger.addHandler(console)
logger.debug("芹泽多摩雄") 
logger.info("真")
logger.warning("男")
logger.error("人")
logger.critical("!")
  1. 多模块使用
#主模块
import logging
import subModule
logger = logging.getLogger("mainModule")
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler("log.txt")
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(console)
#子模块
import logging
module_logger = logging.getLogger("mainModule.sub")
class SubModuleClass(object):
  def __init__(self):
    self.logger = logging.getLogger("mainModule.sub.module")

细心的盆友会再次发现其实对logger的命名很重要,首先在主模块定义了logger'mainModule',并对它进行了配置,子模块可以共享父logger的定义和配置,所谓的父子logger是通过命名来识别,任意以'mainModule'开头的logger都是它的子logger,例如'mainModule.sub'

  1. 事实上,纵使有继承配置或者自定义的配置日志功能,但实际中的大项目中还是略麻烦的,这里主要用到JSON或者yaml进行配置封装,这样加载该文件即可加载日志的配置,下回分解具体操作,最后来一发实例。
# -*- coding: utf-8 -*-
__author__ = 'Secret608'
import logging
import time
import os
import re
class Log(object):
  def __init__(self, loggerName):
      '''
      进行日志初始化,包括存储路径、名称、级别、调用文件等
      '''
      #基本属性
      self.logger = logging.getLogger(loggerName)
      self.logger.setLevel(logging.WARNING)
      #特有属性(文件地址+日志记录格式)
      rq = time.strftime('%Y%m%d_%H%M%S', time.localtime(time.time()))
      log_path = os.path.join(os.path.dirname(os.getcwd()), 'logs')
      log_title = os.path.join(log_path, loggerName + '_'+ rq) + ".log"
      formatter = 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 = os.path.join(os.path.dirname(os.getcwd()), 'logs')
    regexp = re.compile('^'+fileName+'s.*')
    filelist = os.listdir(log_path)
    try:
      [os.remove(os.path.join(log_path, i)) for i in filelist if regexp.match(i) == None]
    except WindowsError:
      pass
    else:
      return "ok"
if __name__ == "__main__":
  a = Log("hah")
  a.delLog("hah")

二、异常

  • 异常类型
    • 内置异常:Python的异常处理能力是很强大的,它有很多内置异常,可向用户准确反馈出错信息。在Python中,异常也是对象,可对它进行操作。BaseException是所有内置异常的基类,但用户定义的类并不直接继承BaseException,所有的异常类都是从Exception继承,且都在exceptions模块中定义。
    • 自定义异常:可以通过创建一个新的异常类拥有自己的异常,异常应该是通过直接或间接的方式继承自Exception类。比如创建了一个MyError类,基类为Exception,用于在异常触发时输出更多的信息。
  • 异常捕获
    • 发生异常时,我们就需要对异常进行捕获,然后进行相应的处理。python的异常捕获常用try...except...结构,把可能发生错误的语句放在try模块里,用except来处理异常,每一个try,都必须至少对应一个except。此外,与python异常相关的关键字主要有:try/except、pass、as(定义异常实例)、else、finally、raise。
    • 捕获所有异常:
# -*- 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("名称错误")
except (ZeroDivisionError, NameError):
  print("你的分母等于0或者变量名不存在")
except Exception as e:
  print("你的变量名或者分母值确实没错,但是出现了其他的错误,详见%s" %e)
  d = 1  
finally:
  print("听说没有错误?不能忍,反正我要让你难受!")
  if d == 1:
    raise ValueError("你有其它错误")
  else:
    raise FuckError("开不开心?")
  #咦? FuckError是啥?貌似没有定义啊,这里定义一波,届时位置移动到前面去
  class FuckError(Exception):
    def __int__(self,*args,**keargs):
      super(FuckError,self).__int__(*args,**keargs)#python2
      self.args = args
      print(args)

更多的异常可参看API(https://docs.python.org/3/library/exceptions.html#base-classes)

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python使用正则匹配实现抓图代码分享
Apr 02 Python
python查看FTP是否能连接成功的方法
Jul 30 Python
Python Socket实现简单TCP Server/client功能示例
Aug 05 Python
python3+PyQt5实现拖放功能
Apr 24 Python
python指定写入文件时的编码格式方法
Jun 07 Python
详解Python用户登录接口的方法
Apr 17 Python
python pandas写入excel文件的方法示例
Jun 25 Python
kafka-python 获取topic lag值方式
Dec 23 Python
Python3.7.0 Shell添加清屏快捷键的实现示例
Mar 23 Python
python3 deque 双向队列创建与使用方法分析
Mar 24 Python
Python paramiko使用方法代码汇总
Nov 20 Python
python实现企业微信定时发送文本消息的示例代码
Nov 24 Python
Python多线程模块Threading用法示例小结
Nov 09 #Python
Python for循环及基础用法详解
Nov 08 #Python
python常用排序算法的实现代码
Nov 08 #Python
python分布式编程实现过程解析
Nov 08 #Python
详解mac python+selenium+Chrome 简单案例
Nov 08 #Python
python manage.py runserver流程解析
Nov 08 #Python
详解python中docx库的安装过程
Nov 08 #Python
You might like
测试PHP连接MYSQL成功与否的代码
2013/08/16 PHP
ThinkPHP采用GET方式获取中文参数查询无结果的解决方法
2014/06/26 PHP
php采集中国代理服务器网的方法
2015/06/16 PHP
thinkPHP连接sqlite3数据库的实现方法(附Thinkphp代码生成器下载)
2016/05/27 PHP
zend framework重定向方法小结
2016/05/28 PHP
Yii框架常见缓存应用实例小结
2019/09/09 PHP
用Javascript读取中文COOKIE的解决办法
2007/02/15 Javascript
javascript新手语法小结
2008/06/15 Javascript
图片无缝滚动代码(向左/向下/向上)
2013/04/10 Javascript
jQuery中$this和$(this)的区别介绍(一看就懂)
2015/07/06 Javascript
JS打开摄像头并截图上传示例
2017/02/18 Javascript
ES6中Proxy与Reflect实现重载(overload)的方法
2017/03/30 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
ES6 中可以提升幸福度的小功能
2018/08/06 Javascript
使用puppeteer爬取网站并抓出404无效链接
2018/12/20 Javascript
深入探讨JavaScript的最基本部分之执行上下文
2019/02/12 Javascript
layui form.render('select', 'test2') 更新渲染的方法
2019/09/27 Javascript
基于JavaScript实现控制下拉列表
2020/05/08 Javascript
windows系统中python使用rar命令压缩多个文件夹示例
2014/05/06 Python
python迭代器与生成器详解
2016/03/10 Python
Python实现批量更换指定目录下文件扩展名的方法
2016/09/19 Python
python实现list元素按关键字相加减的方法示例
2017/06/09 Python
Python 中pandas.read_excel详细介绍
2017/06/23 Python
使用Python的package机制如何简化utils包设计详解
2017/12/11 Python
Python实现的合并两个有序数组算法示例
2019/03/04 Python
Python matplotlib画图与中文设置操作实例分析
2019/04/23 Python
pyqt5 实现多窗口跳转的方法
2019/06/19 Python
TensorFlow保存TensorBoard图像操作
2020/06/23 Python
FitFlop澳大利亚官网:英国符合人体工学的鞋类品牌
2017/06/05 全球购物
一套带答案的C++笔试题
2014/01/10 面试题
校园网站的创业计划书范文
2013/12/30 职场文书
房地产融资计划书
2014/01/10 职场文书
解决mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO/YES)
2021/06/26 MySQL
深入浅出讲解Java8函数式编程
2022/01/18 Java/Android
使用Redis实现点赞取消点赞的详细代码
2022/03/20 Redis
instantclient客户端 连接oracle数据库
2022/04/26 Oracle