6

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

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

假设要测试以下类:

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 这样的代码覆盖工具将正确报告只有一些条件分支已被检查。

info 和 debug 为记录器激活或停用。

除了在您的覆盖范围内看起来很糟糕之外,这还带来了真正的风险。

如果 if(logger.isDebugEnabled()) 里面的代码有一些副作用怎么办?如果您的代码仅在启用 DEBUG 时才有效,并且在日志级别设置为 INFO 时惨遭失败怎么办?(这实际上发生在我们的一个项目中:p)

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

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

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

4

5 回答 5

4

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

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

有关日志记录基类,请参阅LoggingTestBase ,有关使用它的简单示例,请参阅LoggingTestBaseExampleTest 。

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

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

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

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

是的,LoggingTestBase 需要文档;)

于 2009-06-03T16:25:32.923 回答
3

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

禁用所有日志记录

...
<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
于 2009-06-03T17:11:03.990 回答
2

我建议从 JUnit 切换到 TestNG。TestNG 比 JUnit 有很多高级特性。它使您可以使用不同的配置多次运行测试,我想这就是您所需要的

于 2009-06-03T16:25:19.990 回答
1

eqbridge 建议使用不同的日志记录上下文简单地运行两次测试似乎是最简单的。您不必记住在每个有福的测试中编写逻辑代码,这是一个很大的优势。另一个是您可以很容易地看到应该归咎于哪个日志记录级别。

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

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

在 JUnit 4.x 中,我想到了几个额外的选项:

一种是自定义跑步者。尽管我无法想出要完成这项工作所需要做的所有事情,但是实际上运行两次测试并使用 @RunWith 自定义运行程序注释测试的运行程序可以工作。

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

编辑:为了响应您对参数化测试的操作方法的请求,这里是运行器上的 javadoc 以帮助您入门,这里是一个更实用的指南。

于 2009-06-03T17:24:04.580 回答
0

如果您觉得打开所有内容时日志记录过多,也许您可​​以尝试减少日志记录量。如果计算机产生的东西太多,更不用说人类阅读,它就不是很有用。

于 2009-06-04T06:28:17.020 回答