我是否可以在启用所有日志记录的情况下自动执行一次 JUnit 测试用例,并在禁用所有日志记录的情况下自动执行一次 JUnit 测试用例?

StackOverflow https://stackoverflow.com/questions/945659

我找到了解决方案,请参阅下面我自己的答案。有人有更优雅的吗?

我想这样做是为了增加代码覆盖率并发现细微的错误。

假设要测试以下类:

public class Foo {
    private final Logger logger = LoggerFactory.getLogger(Foo.class);
    public void bar() {
        String param=[..];
        if(logger.isInfoEnabled()) logger.info("A message with parameter {}", param);

        if(logger.isDebugEnabled()) {
            // some complicated preparation for the debug message
            logger.debug([the debug message]);
        }
    }
}

以及以下测试类:

public class FooTest {
    @Test
    public void bar() {
        Foo foo=new Foo();
        foo.bar();
    }
}

代码覆盖工具,例如Cobertura 将正确报告仅检查了部分条件分支。

记录器的信息和调试要么被激活,要么被停用。

除了你的覆盖分数看起来很糟糕之外,这还带来了真正的风险。

如果 if(logger.isDebugEnabled()) 内部的代码引起一些副作用怎么办?如果您的代码仅在启用 DEBUG 时才工作,并且在日志级别设置为 INFO 时严重失败,该怎么办?(这实际上发生在我们的一个项目中:p)

所以我的结论是,包含记录器语句的代码应始终在启用所有日志记录的情况下测试一次,并在禁用所有日志记录的情况下测试一次......

有没有办法用 JUnit 做类似的事情?我知道如何全局启用或禁用 Logback 中的所有日志记录,所以问题是:如何执行测试两次,一次启用日志记录,一次禁用日志记录。

附注我知道 这个问题 但我不认为这是重复的。我不太关心绝对覆盖率值,而是关心 if(logger.isDebugEnabled()) 中可能包含的微妙的、难以发现的错误。

有帮助吗?

解决方案

我通过实现一个基类解决了这个问题,如果需要这样的功能,测试类应该扩展该基类。

文章 编写参数化 JUnit 测试 包含解决方案。

日志测试库 对于日志记录基类和 日志测试基础示例测试 举一个使用它的简单例子。

每个包含的测试方法都会执行三次:

1. 像往常一样,它使用 logback-test.xml 中定义的日志记录来执行。这应该有助于编写/调试测试。

2. 它在启用所有日志记录并写入文件的情况下执行。测试后该文件被删除。

3. 它是在禁用所有日志记录的情况下执行的。

是的,LoggingTestBase 需要文档;)

其他提示

您是否尝试过简单地维护两个独立的日志配置文件?每一个将登录在不同级别从根记录器。

所有禁用日志记录

...
<root>
    <priority value="OFF"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

<强>启用所有记录

...
<root>
    <priority value="ALL"/>
    <appender-ref ref="LOCAL_CONSOLE"/>
</root>
...

执行将通过系统参数中指定的类路径上不同的配置:

-Dlog4j.configuration=path/to/logging-off.xml
-Dlog4j.configuration=path/to/logging-on.xml

我建议从JUnit的切换到TestNG的。 TestNG中有很多在JUnit的高级功能。它使您能够运行测试不同的配置多次,我想这就是你所需要的。

eqbridges 建议使用不同的日志记录上下文简单地运行两次测试似乎是最简单的。您不必记住在每个受祝福的测试中编写逻辑,这是一个很大的优势。另一个是您可以很容易地看到哪个日志记录级别是罪魁祸首。

话虽这么说,如果您只需在一次测试运行中执行此操作,则有几种策略。

对于 3.8,我会将所有内容放入套件中,并制作两个套件,每个套件对应一个日志记录级别,这会在运行测试之前设置日志记录级别。从功能上讲,这与使用不同的命令行参数运行整个测试套件两次是一样的,只不过您只需运行一次即可获得它。

在 JUnit 4.x 中,我想到了几个附加选项:

一种是定制跑步者。虽然我无法立即想到要完成这项工作所需要做的所有事情,但实际运行测试两次并使用自定义运行器 @RunWith 注释测试的运行器可以工作。

另一种是参数化测试。尽管您实际上必须设置每个测试来接受参数(这需要一个接受参数的构造函数),然后根据参数设置日志级别。

编辑:为了响应您关于参数化测试操作方法的请求, 这里 是跑步者上帮助您入门的 javadoc,并且 这里 是比较实用的指南。

如果你觉得你有太多的记录,如果你打开的一切,或许你可以尝试减少采伐量。它不是非常有用的,如果太多的计算机procude不去管人阅读。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top