zoukankan      html  css  js  c++  java
  • 封装log4j支持记录到testng

    一、初始方案

    自动化中需要把日志通过testng的Reporter.log来记录日志在报告中展示。开始是新增了一个日志类:

    ReporterLog.class

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.testng.Reporter;
    
    public class ReporterLogger {
        private Logger LOGGER;
    
        public ReporterLogger(Class<?> clazz){
            LOGGER= LoggerFactory.getLogger(clazz);
        }
    
        public void  info(String message){
            //使用slf4j打印到控制台或者文件
            LOGGER.info(message);
            //记录到Reporter
            Reporter.log(message);
        }
    
    }

    这样会有2个问题:

    1、LOGGER.info(message);这句话打印出来的类名、方法名、行号等不是调用ReporterLogger方法info的类,二是ReporterLogger类。

    2、Reporter.log记录的日志,没有时间、类名、方法名、行号。

    第一个问题测试:

    import com.sqe.sas.test.service.ReporterLogger;
    
    public class LogTest {
        private static final ReporterLogger LOGGER = new ReporterLogger(LogTest.class);
    
        public static void main(String[] args) {
            LOGGER.info("processing。。。。");
        }
    
    }

    打印结果:

    [main][2019-01-29 18:28:14] [INFO] [LogTest.info:25] processing。。。。

    类名打印的是对的,但是方法名和行号打印的都是ReporterLogger中的

    二、改进方案:

    第一个问题:

    使用log4j的log方法

    import org.apache.log4j.Level;
    import org.apache.log4j.Logger;
    import org.testng.Reporter;
    
    public class ReporterLogger {
        private Logger LOGGER; //使用org.apache.log4j.Logger 而不是org.slf4j.Logger;
        static final String FQCN = ReporterLogger.class.getName();  // log4j把传递进来的callerFQCN在堆栈中一一比较,相等后,再往上一层即认为是用户的调用类
    
        public ReporterLogger(Class<?> clazz){
            LOGGER= Logger.getLogger(clazz); // 这里也要改
        }
    
    
        public void  info(String message){
            //使用slf4j打印到控制台或者文件
            LOGGER.log(FQCN, Level.INFO,message,null);
            //记录到Reporter
            Reporter.log(message);
        }
    
    }

    再次测试,打印结果如下:

     [main][2019-01-30 10:44:23] [INFO] [LogTest.main:7] processing。。。。

    已经可以了打印正确的方法名和行号了

    第二个问题:

    在打印的字符串前加上时间、类名、方法名、行号

    import org.apache.log4j.Level;
    import org.apache.log4j.Logger;
    import org.testng.Reporter;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class ReporterLogger {
        private Logger LOGGER; //使用org.apache.log4j.Logger 而不是org.slf4j.Logger;
        static final String FQCN = ReporterLogger.class.getName();  // og4j把传递进来的callerFQCN在堆栈中一一比较,相等后,再往上一层即认为是用户的调用类
    
        public ReporterLogger(Class<?> clazz){
            LOGGER= Logger.getLogger(clazz); // 这里也要改
        }
    
    
        public void  info(String message){
            //使用slf4j打印到控制台或者文件
            LOGGER.log(FQCN, Level.INFO,message,null);
            message = getLogTag()+message;
            //记录到Reporter
            Reporter.log(message);
        }
        //根据堆栈信息,拿到调用类的名称、方法名、行号
        public String getLogTag(){
            String logTag = "";
            Long timeStamp = System.currentTimeMillis();
            String dateString = timestampToDate(timeStamp);
            StackTraceElement stack[] = (new Throwable()).getStackTrace();
            for(int i=0;i<stack.length;i++) {
                StackTraceElement s = stack[i];
                if(s.getClassName().equals(LOGGER.getName())){
                    logTag= "["+dateString+"]"+"["+classNameDeal(s.getClassName())+":"+s.getMethodName()+":"+s.getLineNumber()+"]";
                }
            }
            return logTag;
        }
    
        //时间戳转date字符串
        public static String timestampToDate(Long timestamp){
            if(timestamp.toString().length() <13){
                timestamp = Long.valueOf(timestamp.toString().substring(0,10)+"000");
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
            Date date = new Date(timestamp);
            String dateStr = sdf.format(date);
            return dateStr;
        }
    
        //去掉包名,只保留类名
        private String classNameDeal(String allName){
            String[] className = allName.split("\.");
            return className[className.length-1];
        }
    }
  • 相关阅读:
    The formatter threw an exception while trying to deserialize the message in WCF
    通过Web Deploy方式部署WCF
    The Managed Metadata Service or Connection is currently not available
    How to create Managed Metadata Column
    冒泡算法
    asp.net core 实战项目(一)——ef core的使用
    Vue学习笔记入门篇——安装及常用指令介绍
    Vue学习笔记入门篇——数据及DOM
    Vue学习笔记目录
    Chart.js在Laravel项目中的应用
  • 原文地址:https://www.cnblogs.com/Eric-zhao/p/10336966.html
Copyright © 2011-2022 走看看