单元测试:记录和依赖注入

Fin*_*las 15 language-agnostic tdd logging unit-testing

所以关于来自SO和其他互联网站点的日志记录,最佳响应似乎是:

void DoSomething() {
    Logger.Log("Doing something!");
    // Code...
}
Run Code Online (Sandbox Code Playgroud)

现在通常你会避免静态方法,但在记录(特殊情况)的情况下,这是最简单和最干净的路线.在静态类中,您可以通过配置文件/框架轻松注入实例,以获得与DI相同的效果.

我的问题来自单元测试的角度.

在上面的示例代码中,想象DoSomething()的意思是将两个数字加在一起.我会为这个罚款写单元测试.伐木怎么样?

我是否会为日志记录编写单元测试(但是对于记录器本身使用模拟实例)?我知道如果是这种情况我将不得不编写一个集成测试来证明记录器实际写入日志文件,但我不确定.

在测试驱动开发之后(我这样做)我需要进行单元测试才能决定接口没有?

有什么建议?

Avd*_*vdi 33

就个人而言,我非常虔诚地练习TDD/BDD,而且我几乎从不测试伐木.除了一些例外,日志记录要么是开发人员的便利,要么是可用性因素,而不是方法核心规范的一部分.它也往往比该方法的实际语义具有更高的变化率,因此您最终只是因为添加了一些信息性日志记录而结束了测试.

有些测试只是简单地运行日志子系统,这可能是值得的,但对于大多数应用程序,我不会测试每个类以特定方式使用日志.


Jon*_*eet 12

我只编写了一些用于记录的单元测试.这是一个痛苦,要么使生产代码混乱(由于注入记录器)或测试臭(用模拟替换静态记录器).与McWafflestix不同,我经常发现它不值得努力.

真正想知道日志记录是否有效,超出您通过其他(动手)测试看到的内容?您可能希望将DI用于临时类,其中日志记录非常重要,但除此之外我只是不打扰测试日志记录.

这假设日志具有调试性质 - 如果它是审计日志或类似的东西(具有功能需求的东西)则是另一回事.

  • @Dockers,可能被引用到死亡,但这是Kent Beck对此的看法.我认为这条线更适合初学者.一旦你知道你在做什么,你确实可以跳过事情,正如乔恩所说.http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565 (2认同)

Yis*_*hai 9

我会将记录分为三类:

1)要求.某些系统需要进行日志记录以进行审计,或者填写项目的其他一些要求(例如应用程序服务器中的日志记录标准).那确实是一项要求,值得进行单元测试和验收测试,以确保满足要求.因此,在这种情况下,可以测试日志的确切字符串.

2)解决问题.如果您在QA或生产中开始变得奇怪,您希望能够追踪正在发生的事情.一般来说,我会说,如果这很重要(比如在一个线程很重的应用程序中,状态可能变得复杂但无法通过已知步骤重现)那么测试给定的状态值最终记录可能是有价值的(所以你不是不测试日志的整个可读性,只是某些事实进入那里).即使稍后更改了类,仍然可能会记录该状态(以及其他状态),因此测试和日志记录之间的耦合是合理的.因此,在这种情况下,只测试部分日志记录(包含测试).

3)发展援助.在许多情况下,我使用日志记录作为更强大的评论形式.你可以写一个如下声明:

 logger.debug("Extract the fifth instance of BLAH from the string " + s);
Run Code Online (Sandbox Code Playgroud)

因此,如果您需要调试正在进行的操作,您可以记录代码并同时拥有有用的工件.在那种情况下,我根本不会进行单元测试,因为给定语句的存在与否本身并不重要.

至于你要测试所有的100%的观点,看到Kent Beck的答案在这里.我认为"测试一切"对初学者来说是个好建议,因为当你开始使用TDD时,诱惑就是不测试任何难以测试的东西,或者推动你去考虑设计以使其可测试,以及将其理性化为不重要的.但是一旦你知道自己在做什么,并欣赏测试的价值,那么平衡你正在做的事情和值得测试的事情是很重要的.