日志无论是在测试、开发中都非常重要,如果你在跑自动化时程序报错了,但是你没有日志你怎么去定位时程序错误还是你app的错误?或者还是其它环境因素?
试想我们运行自动化测试用例时,要保存一份日志,最重要的是什么呢?
首先,我们得知道日志保存的位置;其次,日志的级别是什么,这决定了日志的详细程度;还有最重要的,你的日志应该是什么格式的?这包含了日志生成的时间,日志对应的代码的行数,日志详细信息等。
日志级别
脚本运行会有很多的情况,比如调试信息、报错异常信息等。日志要根据这些不同的情况来继续分级管理,不然对于排查问题的筛选会有比较大的干扰。日志一般定位的级别如下:
级别 | 何时使用 |
DEBUG | 调试信息,也是最详细的日志信息。 |
INFO | 证明事情按预期工作。 |
WARNING | 表明发生了一些意外,或者不久的将来会发生问题(如‘磁盘满了’)。软件还是在正常工作。 |
ERROR | 由于更严重的问题,软件已不能执行一些功能了。 |
CRITICAL | 严重错误,表明软件已不能继续运行了。 |
首先我们日志需要按照info、debug、error等级别来进行区分的。当然这个级别可以自己去设置。在一般的情况下我们普通的输出我们直接用info类型,调试的时候用debug类型,如果预计有错误时那么我们就需要用error类型的日志,一般情况去info级别最为合适。
日志格式
日志格式化是为了提高日志的可阅读性,比如:时间+模块+行数+日志具体信息的内容格式。
[formatter_form01] format=%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s datefmt=%Y-%m-%d %H:%M:%S
日志效果如下
2021-08-26 14:09:19 testmycase.py [line:9] INFO info类型的日志
2021-08-26 14:09:19 testmycase.py [line:10] ERROR error 的日志
Logging模块的使用如下:
import logging import logging.config #这个是配置文件的路径 CONF_LOG = "log.conf" logging.config.fileConfig(CONF_LOG) logger = logging.getLogger('testmycase.py') #下面就是使用日志打印日志信息 logger.info("info类型的日志") logger.error("error 的日志")
其中log.conf是日志的配置文件,其中设置一些日志的基本信息,日志配置信息如下:
[loggers] keys=root,infoLogger,errorlogger [logger_root] level=DEBUG handlers=infohandler,errorhandler [logger_infoLogger] handlers=infohandler qualname=infoLogger propagate=0 [logger_errorlogger] handlers=errorhandler qualname=errorlogger propagate=0 #################################### [handlers] keys=infohandler,errorhandler [handler_infohandler] class=StreamHandler level=INFO formatter=form02 args=(sys.stdout,) [handler_errorhandler] class=FileHandler level=ERROR formatter=form01 args=('./mylog.log', 'a') ##################################### [formatters] keys=form01,form02 [formatter_form01] format=%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s datefmt=%Y-%m-%d %H:%M:%S [formatter_form02] format=%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s datefmt=%Y-%m-%d %H:%M:%S
每个人可能根据自己实际需求配置不同,但是基本如上,再根据自己的需求微调。
配置信息的基本释义如下
1. 初始化 logger = logging.getLogger("endlesscode"),getLogger()方法后面最好加上所要日志记录的模块名字,后面的日志格式中的%(name)s 对应的是这里的模块名字
2. 设置级别 logger.setLevel(logging.DEBUG),Logging中有NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL这几种级别,日志会记录设置级别以上的日志
3. Handler,常用的是StreamHandler和FileHandler,windows下你可以简单理解为一个是console和文件日志,一个打印在CMD窗口上,一个记录在一个文件上
4. formatter,定义了最终log信息的顺序,结构和内容,我喜欢用这样的格式 '[%(asctime)s] [%(levelname)s] %(message)s', '%Y-%m-%d %H:%M:%S',
%(name)s Logger的名字
%(levelname)s 文本形式的日志级别
%(message)s 用户输出的消息
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(levelno)s 数字形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
下面我们根据考研帮的一个案例来实操一下:
测试场景为:启动考研帮App的脚本增加log采集功能,设置指定的日志格式输出,并将日志保存到指定文件。
首先需要编写如上的log.conf的日志文件配置
然后编写考研启动的.py文件,代码如下
在考研帮的.py中除了对考研帮基本的测试外,加入日志收集的代码如下
import logging import logging.config #这个是配置文件的路径 CONF_LOG = "log.conf" logging.config.fileConfig(CONF_LOG) logger = logging.getLogger('testmycase.py')
在考研帮代码中的某个节点可以加入日志信息,如检查跳过按钮可以写loging.info("check skip")
整体代码如下
"""Created on 2021-0826 @author:米丫"""
from appium import webdriver from time import sleep caps={} caps["platformName"] = "Android" caps["platformVersion"] = "4.4.2" caps["deviceName"] = "127.0.0.1:62001" caps["appPackage"] = "com.tal.kaoyan" caps["appActivity"] = "com.tal.kaoyan.ui.activity.SplashActivity" caps["noReset"] = True driver=webdriver.Remote('http://localhost:4723/wd/hub',caps) sleep(2) def login(): loging.info("check login") #输入账号 el3 = driver.find_element_by_id("com.tal.kaoyan:id/login_email_edittext") el3.send_keys("zgjy1234") sleep(2) #输入密码 el4 = driver.find_element_by_id("com.tal.kaoyan:id/login_password_edittext") el4.send_keys("zgjy123456") sleep(2) #点击登录 el5 = driver.find_element_by_id("com.tal.kaoyan:id/login_login_btn") el5.click() sleep(2) try: loging.info("check update") #取消升级 el1=driver.find_element_by_id("android:id/button2") except Exception: login() else: el1.click() sleep(2) try: loging.info("check skip") #跳过 el2 = driver.find_element_by_id("com.tal.kaoyan:id/tv_skip") except Exception: login() else: el2.click() sleep(2) login() sleep(2) driver.quit()
最终运行代码日志信息其中一条如下
2021-08-26 14:22:19 testmycase.py [line:41] INFO check update
至此,我们在实现考研帮的启动的同时完成了日志的收集,并且日志配置文件,可以适用于很多模块,很多app甚至是web的使用中,这种日志收集的方式可谓是适用性非常地广泛。