(转)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("你有其它错误")
    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

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

原文地址:https://www.cnblogs.com/dydxw/p/11751372.html

时间: 2024-10-09 14:28:19

(转)python自动化测试之异常及日志的相关文章

python 自动化之路 logging日志模块

logging 日志模块 http://python.usyiyi.cn/python_278/library/logging.html 中文官方http://blog.csdn.net/zyz511919766/article/details/25136485 清晰明了,入门必备http://my.oschina.net/leejun2005/blog/126713 继承讲的很棒http://my.oschina.net/u/126495/blog/464892 实例分析 一:概述 在实际项目

selenium2 python自动化测试之利用AutoIt工具实现本地文件上传

本人在学习基于python语言的selenium2自动测试方法的过程中,发现涉及本地上传文件的测试时,selenium2在定位本地window窗口的对象(元素)上能力有限.当上传按钮使用的是input标签时,可以使用send_keys()方法添加本地文件路径轻松实现,但有的上传控件使用的不是input元素,这个时候send_keys()方法是行不通的.经过网上搜索加上自己实践,总结出一个非常简单而有效的方法--借用AutoIt工具实现自动化本地上传文件,在此与大家分享. 1.AutoIt介绍及安

Python自动化测试之selenium从入门到精通

1. 安装selenium 首先确保python安装成功,输入python -V 这里使用pip安装selenium,详情如图所示:

python自动化测试之appium环境安装

1.安装client pip install Appium-Python-Clinet  若有两个版本的python则使用(python3 pip install Appium-Python-Clinet) pip install selenium -U 2.安装Appium server https://github.com/appium/appium-desktop/releases/latest 3.安装Android Sdk https://developer.android.googl

Appium+Python 自动化测试之二:启动APP(Android篇)

前一篇写了环境安装,这篇记录是记录如何启动APP以及启动APP之前要做哪些事. Appium 启动APP至少需要5个参数,分别是'platformName','platformVersion','deviceName'.'appPackage'.'appActivity' 这几个参数如何得来的呢,下面一步一步为大家讲解 platformName,我们不是要玩Android app自动化测试吗,所以这个platformName值就是android: platformVersion就是Android

python自动化测试之函数(匿名函数lambda和三目运算等(高级用法))

''' 匿名函数: lambda ''' def Add(a,b): print(a+b) Add(2,3) per = lambda a,b:a+b print(per(2,3)) ''' 三目运算 ''' a = 20 print("True") if a >10 else print("False") ''' 匿名函数+三目运算 ''' login = lambda username,password:print('登录成功') if username

python接口测试之日志功能

之前在简书中看了一篇关于日志功能的文档,供大家参考:https://www.jianshu.com/p/62f7b49b41e7 Python通过logging模块提供日志功能,所以直接导入即可 import logging 1.定义日志收集器,指定收集器的名称,返回logging对象 case_logger = logging.getLogger('case') 2.指定日志收集器的日志等级,NOTEST(0) DEBUG(10) INFO(20) WARNING(30) ERROR(40)

Selenium2+python自动化47-判断弹出框存在(alert_is_present)

前言 系统弹窗这个是很常见的场景,有时候它不弹出来去操作的话,会抛异常.那么又不知道它啥时候会出来,那么久需要去判断弹窗是否弹出了. 本篇接着Selenium2+python自动化42-判断元素(expected_conditions)讲expected_conditions这个模块 一.判断alert源码分析 class alert_is_present(object):    """ Expect an alert to be present.""&q

selenium3+python自动化50-环境搭建(firefox)

前言 有不少小伙伴在安装selenium环境后启动firefox报错,因为现在selenium升级到3.0了,跟2.0的版本还有有一点区别的. 安装环境过程中主要会遇到三个坑: 1.'geckodriver' executable needs to be in PATH 2.Expected browser binary location, but unable to find binary in default location 3.Unsupported Marionette protoco