0


百日筑基第九天-单元测试Junit、Log4j 、Log4j 2

百日筑基第九天-单元测试Junit、Log4j 、Log4j 2

Junit

  • Junit是一个开源的 Java 单元测试框架。
  • 单元测试,就是针对最小的功能单元编写测试代码。在 Java 中,最小的功能单元就是方法,因此,对 Java 程序员进行单元测试实际上就是对 Java 方法的测试。
  • 单元测试可以确保你编写的代码是符合软件需求和遵循开发规范的。单元测试是所有测试中最底层的一类测试,是第一个环节,也是最重要的一个环节,是唯一一次能够达到代码覆盖率 100% 的测试,是整个软件测试过程的基础和前提。

使用:

1.导入依赖

<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>RELEASE</version><scope>compile</scope></dependency>

2.测试方法中添加一组断言(假设有一个Factorial类且有待测方法fact)

@Testvoidfact(){assertEquals(1,Factorial.fact(1));assertEquals(2,Factorial.fact(2));assertEquals(6,Factorial.fact(3));assertEquals(100,Factorial.fact(5));}

3.右键点「Run FactorialTest」,即可得到哪一行执行失败。

额外逻辑:

测试也支持添加前后逻辑:@BeforeEach、@AfterEach、@BeforeAll、@AfterAll

classCalculatorTest{Calculator calculator;@BeforeEachvoidsetUp(){
        calculator =newCalculator();}@AfterEachvoidtearDown(){
        calculator =null;}@Testvoidsub(){assertEquals(0,calculator.sub(1,1));}@Testvoidadd(){assertEquals(2,calculator.add(1,1));}}
  • @BeforeEachsetUp() 方法会在运行每个 @Test 方法之前运行;
  • @AfterEachtearDown() 方法会在运行每个 @Test 方法之后运行。
publicclassDatabaseTest{staticDatabase db;@BeforeAllpublicstaticvoidinit(){
        db =createDb(...);}@AfterAllpublicstaticvoiddrop(){...}}

All 通常用来初始化和销毁静态变量。

异常测试:

publicclassFactorial{publicstaticlongfact(long n){if(n <0){thrownewIllegalArgumentException("参数不能小于 0");}long r =1;for(long i =1; i <= n; i++){
            r = r * i;}return r;}}

当n<0时怎么测试呢?答:assertThrows

@TestvoidfactIllegalArgument(){assertThrows(IllegalArgumentException.class,newExecutable(){@Overridepublicvoidexecute()throwsThrowable{Factorial.fact(-2);}});}

使用 Lambda 表达式:

@Test
void factIllegalArgumentLambda() {
    assertThrows(IllegalArgumentException.class, () -> {
        Factorial.fact(-2);
    });
}

忽略测试:

@Disabled加在@Test注解之上

Log4j

打印日志,缺点是影响性能,但是日常开发中必不可少。(刚入职时前辈告诉我尽量多打日志)

  • Log4j 的一个好处是,不需要重新启动 Java 程序就可以调整日志的记录级别,非常灵活。可以通过 log4j.properties 文件来配置 Log4j 的日志级别、输出环境、日志文件的记录方式。
  • Log4j 还是线程安全的,可以在多线程的环境下放心使用。

第一步,在 pom.xml 文件中引入 Log4j 包:

<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>

第二步,在 resources 目录下创建 log4j.properties 文件,内容如下所示:

### 设置###
log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制台 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=debug.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = debug.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

1)配置根 Logger,语法如下所示:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

level 就是日志的优先级,从高到低依次是 ERROR、WARN、INFO、DEBUG。如果这里定义的是 INFO,那么低级别的 DEBUG 日志信息将不会打印出来。

appenderName 就是指把日志信息输出到什么地方,可以指定多个地方,当前的配置文件中有 3 个地方,分别是 stdout、D、E。

2)配置日志输出的目的地,语法如下所示:

log4j.appender.appenderName = fully.qualified.name.of.appender.class  
log4j.appender.appenderName.option1 = value1  
…  
log4j.appender.appenderName.option = valueN

Log4j 提供的目的地有下面 5 种:

  • org.apache.log4j.ConsoleAppender:控制台
  • org.apache.log4j.FileAppender:文件
  • org.apache.log4j.DailyRollingFileAppender:每天产生一个文件
  • org.apache.log4j.RollingFileAppender:文件大小超过阈值时产生一个新文件
  • org.apache.log4j.WriterAppender:将日志信息以流格式发送到任意指定的地方

3)配置日志信息的格式,语法如下所示:

log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class  
log4j.appender.appenderName.layout.option1 = value1  
…  
log4j.appender.appenderName.layout.option = valueN

Log4j 提供的格式有下面 4 种:

  • org.apache.log4j.HTMLLayout:HTML 表格
  • org.apache.log4j.PatternLayout:自定义
  • org.apache.log4j.SimpleLayout:包含日志信息的级别和信息字符串
  • org.apache.log4j.TTCCLayout:包含日志产生的时间、线程、类别等等信息

自定义格式的参数如下所示:

  • %m:输出代码中指定的消息
  • %p:输出优先级
  • %r:输出应用启动到输出该日志信息时花费的毫秒数
  • %c:输出所在类的全名
  • %t:输出该日志所在的线程名
  • %n:输出一个回车换行符
  • %d:输出日志的时间点
  • %l:输出日志的发生位置,包括类名、线程名、方法名、代码行数,比如:method:com.itwanger.Log4jDemo.main(Log4jDemo.java:14)

第三步,写个使用 Demo:

packagecom.itwanger;importorg.apache.log4j.LogManager;importorg.apache.log4j.Logger;/**
 * @author 微信搜「沉默王二」,回复关键字 PDF
 */publicclassLog4jDemo{privatestaticfinalLogger logger =LogManager.getLogger(Log4jDemo.class);publicstaticvoidmain(String[] args){// 记录debug级别的信息
        logger.debug("debug.");// 记录info级别的信息
        logger.info("info.");// 记录error级别的信息
        logger.error("error.");}}

1)获取 Logger 对象

要使用 Log4j 的话,需要先获取到 Logger 对象,它用来负责日志信息的打印。通常的格式如下所示:

privatestaticfinalLogger logger =LogManager.getLogger(Log4jDemo.class);

2)打印日志

有了 Logger 对象后,就可以按照不同的优先级打印日志了。常见的有以下 4 种:

Logger.debug();Logger.info();Logger.warn();Logger.error();

程序运行后会在 target 目录下生成两个文件,一个名叫 debug.log,内容如下所示:

2020-10-20 20:53:27  [ main:0 ] - [ DEBUG ]  debug.
2020-10-20 20:53:27  [ main:3 ] - [ INFO ]  info.
2020-10-20 20:53:27  [ main:3 ] - [ ERROR ]  error.

另外一个名叫 error.log,内容如下所示:

2020-10-20 20:53:27  [ main:3 ] - [ ERROR ]  error.

Log4j 2

Log4j 2 强在哪

1)在多线程场景下,Log4j 2 的吞吐量比 Logback 高出了 10 倍,延迟降低了几个数量级。

2)Log4j 2 可以减少垃圾收集器的压力。

3)支持 Lambda 表达式。

4)支持自动重载配置。

第一步,在 pom.xml 文件中添加 Log4j 2 的依赖:

<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-api</artifactId><version>2.5</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.5</version></dependency>

(这个 artifactId 还是 log4j,没有体现出来 2,而在 version 中体现,多少叫人误以为是 log4j)

第二步,来个最简单的测试用例:

importorg.apache.logging.log4j.LogManager;importorg.apache.logging.log4j.Logger;publicclassDemo{privatestaticfinalLogger logger =LogManager.getLogger(Demo.class);publicstaticvoidmain(String[] args){
        logger.debug("log4j2");}}

第三步,在 resource 目录下增加 log4j2-test.xml 文件,内容如下所示:

<?xml version="1.0" encoding="UTF-8"?><Configuration><Appenders><Consolename="Console"target="SYSTEM_OUT"><PatternLayoutpattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console></Appenders><Loggers><Rootlevel="DEBUG"><AppenderRefref="Console"/></Root></Loggers></Configuration>

1)配置 appender,也就是配置日志的输出目的地。

有 Console,典型的控制台配置信息上面你也看到了,我来简单解释一下里面 pattern 的格式:

  • %d{HH:mm:ss.SSS} 表示输出到毫秒的时间
  • %t 输出当前线程名称
  • %-5level 输出日志级别,-5 表示左对齐并且固定输出 5 个字符,如果不足在右边补空格
  • %logger 输出 logger 名称,最多 36 个字符
  • %msg 日志文本
  • %n 换行

顺带补充一下其他常用的占位符:

  • %F 输出所在的类文件名,如 Demo.java
  • %L 输出行号
  • %M 输出所在方法名
  • %l 输出语句所在的行数, 包括类名、方法名、文件名、行数
  • %p 输出日志级别
  • %c 输出包名,如果后面跟有 {length.} 参数,比如说 %c{1.},它将输出报名的第一个字符,如 com.itwanger 的实际报名将只输出 c.i

2)配置 Loggers,指定 Root 的日志级别,并且指定具体启用哪一个 Appenders。

3)自动重载配置

Logback 支持自动重载配置,Log4j 2 也支持,那想要启用这个功能也非常简单,只需要在 Configuration 元素上添加

monitorInterval

属性即可。

<Configuration monitorInterval="30">
...
</Configuration>

注意值要设置成非零,上例中的意思是至少 30 秒后检查配置文件中的更改。最小间隔为 5 秒。

Async 示例

除了 Console,还有 Async,可以配合文件的方式来异步写入,典型的配置信息如下所示:

<Configuration><Appenders><Filename="DebugFile"fileName="debug.log"><PatternLayout><Pattern>%d %p %c [%t] %m%n</Pattern></PatternLayout></File><Asyncname="Async"><AppenderRefref="DebugFile"/></Async></Appenders><Loggers><Rootlevel="debug"><AppenderRefref="Async"/></Root></Loggers></Configuration>

把这个 Async 加入到 Appenders:

<Configuration><Appenders><Consolename="Console"target="SYSTEM_OUT"><PatternLayoutpattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console><Filename="DebugFile"fileName="debug.log"><PatternLayout><Pattern>%d %p %c [%t] %m%n</Pattern></PatternLayout></File><Asyncname="Async"><AppenderRefref="DebugFile"/></Async></Appenders><Loggers><Rootlevel="DEBUG"><AppenderRefref="Console"/><AppenderRefref="Async"/></Root></Loggers></Configuration>

本文转载自: https://blog.csdn.net/qq_45477639/article/details/140138793
版权归原作者 不要飞升 所有, 如有侵权,请联系我们删除。

“百日筑基第九天-单元测试Junit、Log4j 、Log4j 2”的评论:

还没有评论