Python自动化测试通过日志3分钟定位bug

一、简单使用

入门小案例

1

2

3

4

5

6

7

8

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')

日志级别

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

日志器设置的级别会过滤掉低于这个级别的日志

1

2

3

4

5

6

7

8

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

配置

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

 

格式化规则

日志的输出格式可以通过下面格式自由组合输出

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

1

2

3

4

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

日志写到文件

只需要配置 filename 参数即可

1

2

3

4

5

6

7

8

9

10

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。

日志组件

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

 

步骤

1 创建日志记录器

1

2

3

4

import logging

#  第一步创建一个logger,用来产生日志

logger = logging.getLogger('%s_log' % __name__)

logger.setLevel(logging.DEBUG)  # 设置日志等级

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

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

2 创建日志处理器

1

2

# 创建一个文本处理器用来将日志写入到文件

file_handler = logging.FileHandler(filename='py34.log',encoding='utf-8')

1

file_handler.setLevel('WARNING'# 设置处理器的日志等级

1

2

3

# 创建一个控制台处理器用来将日志输出到控制台

console_handler = logging.StreamHandler()

console_handler.setLevel('INFO'# 设置控制台处理器的日志等级

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

FileHandler 将日志发送到文件

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

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

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

更多详情见官方文档

(logging.handlers --- 日志处理程序 — Python 3.12.0 文档)

3 创建格式化器

1

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

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

1

2

file_handler.setFormatter(formatter)

console_handler.setFormatter(formatter)

4 创建过滤器

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

详情见官方文档

(日志专题手册 — Python 3.12.0 文档 )

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

1

2

logger.addHandler(file_handler)

logger.addHandler(console_handler)

6 记录日志

1

logger.info('This is a info')

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

1

logger.warning('This is a warning')

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

三、日志模块封装

功能分析

  • 能够自定义日志器名
  • 能够自定义日志文件名和路径
  • 能够自定义日志文件编码方式
  • 能够自定义日志格式
  • 使用时间轮转处理器,并能够配置

封装成函数

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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('我是警告信息')

四、应用到项目中

导入

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

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

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

1

2

from .log_handler import get_logger

logger = get_logger('py41', 'py38.log')

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

1

from common import logger

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

记录日志

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

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

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

...

@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('测试用例【{}】测试结束')

​现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:485187702【暗号:csdn11】

最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mfc140.dll丢失的解决方法,以及解决方法的优缺点

如果你在使用电脑时遇到了“mfc140.dll丢失”的错误提示,这可能会阻止你运行特定的应用程序或游戏。这篇文章将向你介绍导致此错误出现的原因以及mfc140.dll丢失的解决方法,让你的电脑系统恢复正常运行。 一.mfc140.dll丢失的解决方法以及优缺点 方法 1…

Java API接口强势对接:构建高效稳定的系统集成方案

文章目录 1. Java API接口简介2. Java API接口的优势2.1 高度可移植性2.2 强大的网络通信能力2.3 多样化的数据处理能力 3. 实战:Java API接口强势对接示例3.1 场景描述3.2 用户管理系统3.3 订单处理系统3.4 系统集成 4. 拓展:Java API接口在微服务架构中…

07-原型模式-C语言实现

原型模式: Specify the kinds of objects to create using a prototypical instance,and create new objects by copying this prototype.(用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象。 ) UML图&#xff1…

SSM项目实战-登录验证成功并路由到首页面,Vue3+Vite+Axios+Element-Plus技术

1、util/request.js import axios from "axios";let request axios.create({baseURL: "http://localhost:8080",timeout: 50000 });export default request 2、api/sysUser.js import request from "../util/request.js";export const login (…

IoT DC3 是一个基于 Spring Cloud 全开源物联网平台 linux docker部署傻瓜化步骤

如有不了解可先参考我的另一篇文章本地部署:IoT DC3 是一个基于 Spring Cloud 的开源的、分布式的物联网(IoT)平台本地部署步骤 如有不了解可先参考我的另一篇文章本地部署: 1 环境准备: JDK 8 以上 docker 安装好 下载docker-compose-dev.yml 文件 执行基础环境docker安装 …

数据库管理-第119期 记一次迁移和性能优化(202301130)

数据库管理-第119期 记一次迁移和性能优化(202301130) 1 迁移 之前因为DV组件没有迁移成功的那个PDB,后来想着在目标端安装DV组件迁移,结果目标端装不上,而且开了SR也没看出个所以然来。只能换一个方向,尝…

go elasticsearch 测试实例

// 查询列表数据 func QueryOperateList(ctx context.Context, esClient *elastic.Client, index string, pageNum, pageSize int, start, end int64, execSql string, list []interface{}, operateAccount string, operateAddr string, maxRows, minRows int, dbAddr, namespa…

在re:Invent大会上,上汽海外出行选择亚马逊云科技为其提供智能网联解决方案

亚马逊云科技在re:Invent 2023上宣布,中国最大的汽车制造商之一、《财富》世界500强企业上汽集团旗下的上汽海外出行科技有限公司(以下简称“上汽海外出行”)已选择亚马逊云科技为重要云服务供应商,为出海的自主品牌汽车构建领先的…

解决webpack打包生成gz格式css/js文件没法在nginx使用的问题--全网唯一正确

本文绝对是全网解决这个问题唯一正确的文章,没有之一! 很多人都说开启nginx gzip压缩,这些人完全是胡说八道!你们到底懂不懂叫gzip压缩啊?! 不信你就试试,如果css/js只有gz文件,ng…

Linux 系统渗透提权-Server2204-(解析)

B-3:Linux 系统渗透提权 任务环境说明: 服务器场景:Server2204(关闭链接) 用户名:hacker 密码:123456 1.使用渗透机对服务器信息收集,并将服务器中 SSH 服务端口号作为 flag 提 交; Flag:2283/tcp

Angular 由一个bug说起之三:为什么时不时出现额外的水平/垂直滚动条?怎样能更好的防止它的出现?

目录: 什么是单元溢出 控制滚动条出现的属性 怎样能减少意外的滚动条出现 一、什么是单元溢出 在说到这个问题之前我们先简单阐述一下视图窗口(Viewport)和视图内容(View Content) 视图窗口简单来说就是呈现内容的视口,浏览器就是一个窗口&#xff…

论ChatGPT让程序员提升效率—掌握时代工具风口修炼之道【文末送书-02】

文章目录 一.论ChatGPT让程序员提升效率—掌握时代工具风口修炼之道二.ChatGPT在代码编写中的应用2.1 快速解决问题:2.2 优化代码结构:2.3 ChatGPT的学习过程2.4 ChatGPT的自定义训练 三.文末推荐与福利免费包邮送出4本!3.2领书方式 一.论Cha…

RflySim | 姿态控制器设计实验二

本实验的目的是让多旋翼的姿态能够跟随我们给定的期望姿态,姿态控制器的好坏直接决定了多旋翼能否平稳飞行。 RflySim| 姿态控制器设计实验二 01 基础实验 1.复现四旋翼飞行器的Simulink仿真,分析控制分配器的作用; 2.记录姿态的阶跃响应&a…

GWAS power的计算

import math import numpy as np import pandas as pd from matplotlib import pyplot as plt from scipy.special import chdtri from collections import defaultdict %matplotlib inline对于GWAS中power值(statistical power)的计算,用自己…

unity 2d 入门 飞翔小鸟 下坠功能且碰到地面要停止 刚体 胶囊碰撞器 (四)

1、实现对象要受重力 在对应的图层添加刚体 改成持续 2、设置胶囊碰撞器并设置水平方向 3、地面添加盒状碰撞器 运行则能看到小鸟下坠并落到地面上

二叉树题目:翻转二叉树以匹配前序遍历

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题:翻转二叉树以匹配前序遍历 出处:971. 翻转二叉树以匹配前序遍历 难度 5 级 题目描述 要求 给定一个二叉树的根结点 root \texttt{roo…

Redis--13--缓存一致性问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 缓存一致性问题1、先更新缓存,再更新DB方案二:先更新DB,再更新缓存方案三:先删缓存,再写数据库推荐1&…

【c】杨辉三角

下面介绍两种方法 1.利用上面性质的第五条&#xff0c;我们可以求各行各列的组合数 2.利用上面性质的第7条&#xff0c;我们可以用数组完成 下面附上代码 1. #include<stdio.h> void fact(int n ,int m )//求组合数 {long long int sum11;long long int sum21;int a…

C#中GDI+图形图像技术(Graphics类、Pen类、Brush类)

目录 一、创建Graphics对象 1.创建Pen对象 2.创建Brush对象 &#xff08;1&#xff09;SolidBrush类 &#xff08;2&#xff09;HatchBrush类 ​​​​​​​&#xff08;3&#xff09;LinerGradientBrush类 用户界面上的窗体和控件非常有用&#xff0c;且引人注目&#…

家政小程序源码,师傅竞价接单

家政预约上门服务小程序开发方案&#xff0c;php开发语言&#xff0c;前端是uniapp&#xff0c;有成品源码&#xff0c;可以二开&#xff0c;可以定制。 一家政小程序用户端功能&#xff1a;服务分类、在线预约、在线下单。 师傅端&#xff1a;在线接单&#xff0c;竞价&…