• (转)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("")

    2.  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("")

    3.细心的盆友又可以发现,可以发现,logging有一个日志处理的主对象,其他处理方式都是通过addHandler添加进去,这里采用logging.StreamHandler实现日志输出到流(控制台),也可以用FileHandler实现日志输出到文件

    4.日志回滚:

    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("")

    5.多模块使用

    #主模块
    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'

    6.事实上,纵使有继承配置或者自定义的配置日志功能,但实际中的大项目中还是略麻烦的,这里主要用到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")

    二、异常

    • 异常类型
    1. 内置异常:Python的异常处理能力是很强大的,它有很多内置异常,可向用户准确反馈出错信息。在Python中,异常也是对象,可对它进行操作。BaseException是所有内置异常的基类,但用户定义的类并不直接继承BaseException,所有的异常类都是从Exception继承,且都在exceptions模块中定义。
    2. 自定义异常:可以通过创建一个新的异常类拥有自己的异常,异常应该是通过直接或间接的方式继承自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("你有其它错误")
        elseraise 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

    原文地址:https://www.cnblogs.com/aoaoao/p/9876712.html

  • 相关阅读:
    POJ 1300 Open Door
    POJ 2230 Watchcow
    codevs 1028 花店橱窗布置
    codevs 1021 玛丽卡
    codevs 1519 过路费
    codevs 3287 货车运输
    codevs 3305 水果姐逛水果街二
    codevs 1036 商务旅行
    codevs 4605 LCA
    POJ 1330 Nearest Common Ancestors
  • 原文地址:https://www.cnblogs.com/dydxw/p/11751372.html
Copyright © 2020-2023  润新知