3分钟通过日志定位bug,这个技能测试人必须会!

news2024/11/16 9:58:15

♥  前  言

软件开发中通过日志记录程序的运行情况是一个开发的好习惯,对于错误排查和系统运维都有很大帮助。

Python 标准库自带了强大的 logging 日志模块,在各种 python 模块中得到广泛应用。

一、简单使用

1. 入门小案例

import logging
logging.basicConfig(level=logging.DEBUG,  #设置级别,根据等级显示
    format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s')  # 设置输出格式
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')

2. 日志级别

根据不同情况设置了五种日志等级,不同情况输出不同等级的日志。

日志等级

(level)

描述

DEBUG 

调试信息,通常在诊断问题的时候用得着 

INFO

普通信息,确认程序按照预期运行 

WARNING 

警告信息,表示发生意想不到的事情,或者指示接下来可能会出现一些问题,但是程序还是继续运行 

ERROR 

错误信息,程序运行中出现了一些问题,程序某些功能不能执行 

CRITICAL

危险信息,一个严重的错误,导致程序无法继续运行 

如果你想学习自动化测试,我这边给你推荐一套视频,这个视频可以说是B站播放全网第一的接口自动化测试教程,同时在线人数到达1000人,并且还有笔记可以领取及各路大神技术交流:798478386   

【已更新】B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)_哔哩哔哩_bilibili【已更新】B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)共计200条视频,包括:1、接口自动化之为什么要做接口自动化、2、接口自动化之request全局观、3、接口自动化之接口实战等,UP主更多精彩视频,请关注UP账号。https://www.bilibili.com/video/BV17p4y1B77x/?spm_id_from=333.337.search-card.all.click日志器设置的级别会过滤掉低于这个级别的日志

import logging
logging.basicConfig(level=logging.WARNING,  #设置级别,根据等级显示
    format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s')  # 设置输出格式
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')

 2020-09-11 17:39:26,667-WARNING-This is a warning log

2020-09-11 17:39:26,669-ERROR-This is a error log

2020-09-11 17:39:26,669-CRITICAL-This is a critical log

3. 配置

basicConfig 方法支持一下关键字参数进行配置。

参数

描述

filename 

使用指定的文件名而不是 StreamHandler 创建 FileHandler。 

filemode

如果指定了 filename,则用此 模式 打开该文件。默认模式为 'a'。 

format 

处理器使用的指定格式字符串。 

datefmt 

使用指定的日期/时间格式,与 time.strftime() 所接受的格式相同。 

style 

如果指定了 format,将为格式字符串使用此风格。'%', '{' 或 '$' 分别对应于 printf 风格,str.format() 或 string.Template。默认为 '%'。 

level 

设置根记录器级别去指定 level。

stream 

使用指定的流初始化 StreamHandler。请注意此参数与 filename 是不兼容的 - 如果两者同时存在,则会引发 ValueError。 

handlers 

 如果指定,这应为一个包含要加入根日志记录器的已创建处理程序的可迭代对象。任何尚未设置格式描述符的处理程序将被设置为在此函数中创建的默认格式描述符。请注意此参数与 filename 或 stream 不兼容 —— 如果两者同时存在,则会引发 ValueError。 

force 

如果将此关键字参数指定为 true,则在执行其他参数指定的配置之前,将移除并关闭附加到根记录器的所有现有处理器。 

常用格式:%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s

import logging
logging.basicConfig(level=logging.DEBUG,  #设置级别,根据等级显示
    format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s')  # 设置输出格式
logging.debug('This is a debug log')

[DEBUG]-2020-09-11 17:36:50,125--4:This is a debug log

5.日志写到文件

只需要配置 filename 参数即可

import logging
logging.basicConfig(
    level=logging.WARNING,  #设置级别,根据等级显示
    filename='example.log'
    format='%(asctime)s-[%(filename)s-->line:%(lineno)d]-%(levelname)s:% (message)s')  # 设置输出格式
logging.debug('This is a debug log')
logging.info('This is a info log')
logging.warning('This is a warning log')
logging.error('This is a error log')
logging.critical('This is a critical log')

注意,配置了 fielname 后,日志将不会输出在控制台。

二、高级用法

简单的代码通过 logging 直接使用即可,如果要深入使用需要按照面向对象的方式使用 logging。

1. 日志组件

logging 模块包含一下几个组件。

组件

说明

Loggers(日志记录器) 

提供程序直接使用的接口 

Handlers(日志处理器) 

将记录的日志发送到指定的位置 

Filters(日志过滤器) 

用于过滤特定的日志记录 

Formatters(日志格式器) 

用于控制日志信息的输出格式 

2.步骤

2.1 创建日志记录器

import logging
#  第一步创建一个logger,用来产生日志
logger = logging.getLogger('%s_log' % __name__)
logger.setLevel(logging.DEBUG)  # 设置日志等级

 

通过 getLogger 这个方法可以创建一个日志记录器,注意要给名字否则返回根日志记录器。

通过 setLevel 设置日志记录器的等级。

2.2 创建日志处理器

# 创建一个文本处理器用来将日志写入到文件
file_handler = logging.FileHandler(filename='py34.log',encoding='utf-8')
file_handler.setLevel('WARNING')  # 设置处理器的日志等级
# 创建一个控制台处理器用来将日志输出到控制台
console_handler = logging.StreamHandler()
console_handler.setLevel('INFO')  # 设置控制台处理器的日志等级

日志处理器就是将日志发送到指定的位置。

  • FileHandler 将日志发送到文件 

  • StreaHandler 将它可将日志记录输出发送到数据流例如 sys.stdout, sys.stderr 或任何文件类对象默认 sys.stdout 即控制台。 

  • RotatingFileHandler 支持根据日志文件大小进行轮转 

  • TimedRotatingFileHandler 支持根据时间进行轮转日志文件 

更多详情见官方文档

(https://docs.python.org/zh-cn/3/library/logging.handlers.html?utm_source=testingpai.com#module-logging.handlers)

2.3 创建格式化器

formatter = logging.Formatter(fmt='%(levelname)s %(asctime)s [%(filename)s-->line:%(lineno)d]:%(message)s')

格式化器需要设置到处理器上

file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

2.4 创建过滤器

过滤器用来过滤指定日志。具体使用略,一般用不到。

详情见官方文档

(https://docs.python.org/zh-cn/3/howto/logging-cookbook.html?utm_source=testingpai.com#filters-contextual)

2.5 将处理器添加到记录器上

logger.addHandler(file_handler)
logger.addHandler(console_handler)

2.6 记录日志

logger.info('This is a info')

2020-09-11 22:22:44,095-[-->line:1]-INFO:This is a info

logger.warning('This is a warning')

2020-09-11 22:23:20,337-[-->line:1]-WARNING:This is a warning

三、日志模块封装

1. 功能分析

  1. 能够自定义日志器名 

  2. 能够自定义日志文件名和路径 

  3. 能够自定义日志文件编码方式 

  4. 能够自定义日志格式 

  5. 使用时间轮转处理器,并能够配置 

2.封装成函数

在 common 目录下创建模块 log_handler.py 在其中创建如下函数。


import logging
from logging.handlers import TimedRotatingFileHandler


def get_logger(name, filename, encoding='utf-8', fmt=None, when='d', interval=1, backup_count=7, debug=False):
    """

    :param name: 日志器的名字
    :param filename: 日志文件名(包含路径)
    :param encoding: 字符编码
    :param fmt: 日志格式
    :param when: 日志轮转时间单位
    :param interval: 间隔
    :param backup_count: 日志文件个数
    :param debug: 调试模式
    :return:
    """
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    # 文件处理器的等级一般情况一定比控制台要高
    if debug:
        file_level = logging.DEBUG
        console_level = logging.DEBUG
    else:
        file_level = logging.WARNING
        console_level = logging.INFO

    if fmt is None:
        fmt = '%(levelname)s %(asctime)s [%(filename)s-->line:%(lineno)d]:%(message)s'

    file_handler = TimedRotatingFileHandler(
        filename=filename, when=when, interval=interval, backupCount=backup_count, encoding=encoding)
    file_handler.setLevel(file_level)

    console_handler = logging.StreamHandler()
    console_handler.setLevel(console_level)

    formatter = logging.Formatter(fmt=fmt)
    file_handler.setFormatter(formatter)
    console_handler.setFormatter(formatter)

    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

    return logger


if __name__ == '__main__':
    log = get_logger(name='py41', filename='py41.log', debug=True, when='s')
    log.info('我是普通信息')
    import time
    time.sleep(3)
    log.warning('我是警告信息')

四、应用到项目中

1. 导入

日志器生成函数的导入不能像 Excel 数据读取函数一样,每个用例模块里都导入一遍。因为它返回一个日志器对象,当多次调用日志器生成函数,且日志器名称相同时,会给同一个日志器添加多个日志处理器,从而出现重复记录日志器的问题。

为了解决上面的问题,在 common 文件夹下创建一个名为 __init__.py 的文件,在 common 模块被导入时会自动执行这个文件里的代码,且只会执行一次。

在 __init__.py 文件编写如下代码:

from .log_handler import get_logger
logger = get_logger('py41', 'py38.log')

那么在项目中的其他模块中就可以通过如下代码导入

from common import logger

从而可以保证在项目执行过程中,get_logger 方法只会执行一遍。

2. 记录日志

日志的作用是记录程序的运行状态和当程序出现问题时能提供定位分析错误的依据。

什么时候需要记录日志,记录什么日志,根据每个人对程序的理解,以及经验。

我们的项目中,在用例执行的过程是核心,所以我们的日志也是围绕着用例的执行。

使用日志记录每个用例的测试数据,和测试结果,代码如下:

...
@list_data(*cases)
    def test_login(self, case):
        """
        登陆测试
        """
        logger.info('测试用例【{}】开始测试'.format(case['title']))
        # 1. 测试数据
        # 传入进来的case参数
        logger.info('测试用例【{}】的测试数据是:{}'.format(case['title'], case))
        # 2. 测试步骤
        res = login_check(case['username'], case['password'])
        logger.info('测试用例【{}】的测试结果是:{}'.format(case['title'], res))
        # 3. 断言
        try:
            self.assertEqual(res, case['expect'])
        except AssertionError as e:
            logger.error('测试用例【{}】断言失败'.format(case['title']))
            raise e
        else:
            logger.info('测试用例【{}】断言成功'.format(case['title']))
        finally:
            logger.info('测试用例【{}】测试结束')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/909023.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

sync修饰符(重要)

作用:可以实现 子组件 与 父组件 数据的双向绑定 简化代码 特点:prop属性名,可以自定义,非固定为value 场景:封装弹框类的基础组件,visible属性 true显示 false隐藏 本质:就是 :属性名 和 updat…

SpringBoot 配置优先级

一般而言,SpringBoot支持配置文件进行配置,即在resources下的application.properties或application.yml。 关于配置优先级而言, application.properties>application.yml>application.yaml 另外JAVA程序程序还支持java系统配置和命令行…

lombok启动不生效(什么方法都试了,可还是不生效怎么办 ?! 救救我)

使用IntelliJ IDEA 2021.1.3&#xff08;Ultimate Edition&#xff09;时提示Lombok不生效 java: You aren’t using a compiler supported by lombok, so lombok will not work and has been disabled. 方式一&#xff1a;我们手动更新一下版本到以下版本 <!--Lombok--&…

水果音乐制作软件fl studio v21.1.0.3713 中文特别版

水果音乐制作软件fl studio v21.1.0.3713 中文特别版是一个功能完备的音乐制作环境&#xff0c;能够进行多轨道音频录制、音序处理和混音&#xff0c;可以帮助用户创作专业质量的音乐轨道。 借助 VST 托管、灵活的混音器、高级 MIDI 和 ReWire 支持&#xff0c;您将轻松驾驭各种…

第14章——FreeRTOS信号量

1.信号量的简介 信号量是一种解决同步问题的机制&#xff0c;可以实现对共享资源的有序访问。 信号量&#xff1a;用于传递状态&#xff08;区别于队列传递消息&#xff09; 信号量的计数值都有限制&#xff1a;限定最大值。 如果最大值被限定为1&#xff0c;那么它就是二值…

多种编程语言运行速度排名-10亿次除7求余数为0的数量

最佳方式是运行10次&#xff0c;取平均数&#xff0c;用时秒数显示3位小数。 因为第一次打开&#xff0c;可能CPU还没优化好&#xff0c;多次取平均&#xff0c;比较准确 第1次共10次&#xff0c;用时3秒&#xff0c;平均3秒 第2次共10次&#xff0c;用时4秒&#xff0c;平均3.…

搭建开发环境-操作系统篇(一键搭建开发环境)

概述 所谓工欲善其事必先利其器&#xff0c;搭环境往往是开发过程中卡出很多初学者的拦路虎。 对于很多老鸟来说&#xff0c;很多东西都已经习惯成自然&#xff0c;也就没有刻意和初学者说。但对于很多初学者&#xff0c;却是受益良多。 这个系列&#xff0c;先从操作系统开始…

string类写时拷贝

文章目录 1.string类拷贝构造函数的现代写法2.string类写时拷贝vs和g下string结构的不同vs下string的结构&#xff1a;g下string的结构 3.总结 1.string类拷贝构造函数的现代写法 string类拷贝构造函数的传统写法&#xff1a; string(const string& s){if (this ! &s)…

2023年每天都投递很多份简历,但都石沉大海,我还投吗?测试人该何去何从?

各大互联网公司的接连裁员&#xff0c;政策限制的行业接连消失&#xff0c;让今年的求职雪上加霜&#xff0c;想躺平却没有资本&#xff0c;还有人说软件测试岗位饱和了&#xff0c;对此很多求职者深信不疑&#xff0c;因为投出去的简历回复的越来越少了。 另一面企业招人真的…

计算机视觉--利用HSV和YIQ颜色空间处理图像噪声

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天我们将利用HSV和YIQ颜色空间处理图像噪声。在本次实验中&#xff0c;我们使用任意一张图片&#xff0c;通过RGB转HSV和YIQ的操作&#xff0c;加入了椒盐噪声并将其转换回RGB格式&#xff0c;最终实现对图像的噪声处理…

mysql之host is blocked问题

程序上线一段时间之后&#xff0c;更新程序总是遇到这个问题 每次都是重启几次程序&#xff0c;或者执行 flush hosts; 毕竟指标不治本&#xff0c;抽出时间决定分析一下问题&#xff0c;查阅了几篇博客。&#xff08;感谢这几位大佬&#xff09; https://blog.51cto.com/u_…

飞机打方块(四)游戏结束

一、游戏结束显示 1.新建节点 1.新建gameover节点 2.绑定canvas 3.新建gameover容器 4.新建文本节点 2.游戏结束逻辑 Barrier.ts update(dt: number) {//将自身生命值取整let num Math.floor(this.num);//在Label上显示this.num_lb.string num.toString();//获取GameCo…

数据结构—队列

队列 队列的概念及结构队列的实现 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 。 入队列&#xff1a;进行插入操作的一端称为队尾。 出队列&am…

Day8 智慧商城

项目演示 项目收获 创建项目 调整初始化目录 1.删components里的所有文件 2.删views里的所有文件 3.router/index.js 删路由 删规则 import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({routes: [] })export default route…

软件开发合同范本word文档,《某公司软件开发合同》,15页范本供参考

上一篇介绍了软件生命周期全过程&#xff0c;软件工程全周期全过程20项文档模板&#xff0c;附下载。从《合同》到《需求规格说明书》到软件设计、开发、实施、验收、维护等全过程相关文档模板。有朋友反馈附件内容没有补全&#xff0c;本次及后续会用实际案例补全附件内容&…

Backblaze 2023 Q2 硬盘故障质量报告解读

Backblaze 在其博客上发布了 2023 年第二季度的存储设备统计数据。这些数据包括了 Backblaze 在该季度所拥有的存储设备的数量、故障率和更换率等信息&#xff0c;这些信息对于了解存储设备的可靠性和性能非常有用。 在最新的Backblaze硬盘使用统计报告中&#xff0c;我们看到了…

OLED透明屏介绍:领先科技的革命性创新

OLED透明屏作为一项领先的科技创新&#xff0c;在产品设计和用户体验方面展现出了巨大的潜力。 在这篇文章中&#xff0c;尼伽将介绍OLED透明屏的定义、特点、应用领域以及未来发展趋势&#xff0c;以帮助您全面了解OLED透明屏。 一、OLED透明屏的定义与原理 1.1 定义&#x…

概念解析 | 走进射线管积分:探索数学与现实世界的神秘桥梁

注1&#xff1a;本文系“概念解析”系列之一&#xff0c;致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是&#xff1a;射线管积分。 走进射线管积分&#xff1a;探索数学与现实世界的神秘桥梁 射线管积分雷达成像 射线管积分&#xff08;Ray Tube Integration&a…

leetcode 188. 买卖股票的最佳时机 IV

2023.8.21 这道题是 买卖股票的最佳时机III 的升级版&#xff0c;即买卖次数限制为k次&#xff0c;做法和上一篇如法炮制&#xff0c;直接看代码&#xff1a; class Solution { public:int maxProfit(int k, vector<int>& prices) {vector<vector<int>>…

Django模板语法,带你快速入门

目录 案例一&#xff1a;登录页面 案例二&#xff1a;for案例 if案例——单个字符串的传递&#xff0c;列表的传递&#xff0c;字典的传递 模板语法其本质&#xff1a;本质上&#xff0c;Django的模板语法就是在html中&#xff0c;写一些占位符&#xff0c;由数据对这些占位符…