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 UnicodeEncodeError: 'gbk' codec can't encode character 解决方法
Apr 24 Python
Python多线程下载文件的方法
Jul 10 Python
Queue 实现生产者消费者模型(实例讲解)
Nov 13 Python
Python3中类、模块、错误与异常、文件的简易教程
Nov 20 Python
Pandas之drop_duplicates:去除重复项方法
Apr 18 Python
Python中栈、队列与优先级队列的实现方法
Jun 30 Python
python 随机森林算法及其优化详解
Jul 11 Python
python3.x提取中文的正则表达式示例代码
Jul 23 Python
Python如何访问字符串中的值
Feb 09 Python
Django启动时找不到mysqlclient问题解决方案
Nov 11 Python
pytorch 实现多个Dataloader同时训练
May 29 Python
详解非极大值抑制算法之Python实现
Jun 28 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通过排列组合实现1到9数字相加都等于20的方法
2015/08/03 PHP
PHP PDOStatement::columnCount讲解
2019/01/30 PHP
js prototype 格式化数字 By shawl.qiu
2007/04/02 Javascript
js获取当前日期代码适用于网页头部
2013/06/27 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
解析URI与URL之间的区别与联系
2013/11/22 Javascript
js完美的div拖拽实例代码
2014/01/22 Javascript
javascript屏蔽右键代码
2014/05/15 Javascript
jquery实现仿JqueryUi可拖动的DIV实例
2015/07/31 Javascript
在JavaScript的jQuery库中操作AJAX的方法讲解
2015/08/15 Javascript
浅谈$('div a') 与$('div>a')的区别
2016/07/18 Javascript
使用jQuery实现鼠标点击左右按钮滑动切换
2017/08/04 jQuery
Vue基于NUXT的SSR详解
2017/10/24 Javascript
微信小程序网络封装(简单高效)
2018/08/06 Javascript
vue自定义表单生成器form-create使用详解
2019/07/19 Javascript
nodejs的安装使用与npm的介绍
2019/09/11 NodeJs
JS如何寻找数组中心索引过程解析
2020/06/01 Javascript
浅谈JavaScript 声明提升
2020/09/14 Javascript
python脚本设置系统时间的两种方法
2016/02/21 Python
Python实现字典去除重复的方法示例
2017/07/31 Python
使用pycharm生成代码模板的实例
2018/05/23 Python
Python中存取文件的4种不同操作
2018/07/02 Python
简单了解python协程的相关知识
2019/08/31 Python
记录模型训练时loss值的变化情况
2020/06/16 Python
python openpyxl模块的使用详解
2021/02/25 Python
canvas学习和滤镜实现代码
2018/08/22 HTML / CSS
有影响力的人、名人和艺术家的官方商品:Represent
2019/11/26 全球购物
String是最基本的数据类型吗?
2013/06/13 面试题
地理教师岗位职责
2014/03/16 职场文书
《大江保卫战》教学反思
2014/04/11 职场文书
家长给学校的建议书
2014/05/15 职场文书
水利水电建筑施工应届生求职信
2014/07/04 职场文书
2014年宣传思想工作总结
2014/12/10 职场文书
python爬不同图片分别保存在不同文件夹中的实现
2021/04/02 Python
Django中celery的使用项目实例
2022/07/07 Python
Go语言编译原理之源码调试
2022/08/05 Golang