在进行TDD时需要记录日志吗?


40

在进行红色,绿色和重构循环时,我们应始终编写最少的代码以通过测试。这就是我被教导有关TDD的方式,以及几乎所有书籍都描述该过程的方式。

但是日志记录呢?

老实说,除非发生真正复杂的事情,否则我很少在应用程序中使用日志记录,但是,我看到无数篇文章都谈到了正确日志记录的重要性。
因此,除了记录异常外,我无法证明在适当的经过测试的应用程序(单元/集成/验收测试)中记录日志的真正重要性。

所以我的问题是:

  1. 如果正在执行TDD,是否需要记录?失败的测试不会揭示应用程序有什么问题吗?
  2. 是否应该在每个类的每个方法中为日志记录过程添加测试?
  3. 例如,如果在生产环境中禁用了某些日志级别,这是否会在测试和环境之间引入依赖性?
  4. 人们谈论日志如何简化调试,但是TDD的主要优点之一是,我始终知道由于测试失败而出了什么问题。

有什么我想念的吗?


5
我认为日志记录是许多规则的特例。一个类/函数应该只做一件事和一件事……除了日志。函数最好是纯函数,除了日志记录。等等等等。记录违反了规则。
Phoshi 2014年

1
日志记录是否几乎与所使用的任何SW开发方法都正交?因此,也许您应该缩小范围,然后问:做TDD时,我们是否需要测试用例来记录日志?
海德2014年

Answers:


50

1)如果要进行TDD,是否需要记录?失败的测试不会揭示应用程序有什么问题吗?

假定您已经对应用程序进行了所有可能的测试,这很少是真的。日志可帮助您查找尚未编写测试的错误。

2)我们应该在每个类的每个方法中为日志记录过程添加测试吗?

如果记录器本身已经过测试,则不需要像其他依赖项那样在每个类中都对其进行重新测试。

3)例如,如果在生产环境中禁用了某些日志级别,这不会在测试和环境之间引入依赖性吗?

人类(和日志聚合器)依赖于日志,测试不应该依赖于它们。通常,有几个日志级别,一些用于生产,一些其他级别用于开发,类似于:

“ Rails日志级别在生产模式下是信息,而在开发和测试中则是调试” -http://guides.rubyonrails.org/debugging_rails_applications.html

其他应用程序使用类似的方法。

4)人们谈论日志如何简化调试,但是TDD的主要优点之一是我总是知道由于测试失败而出了什么问题。

生产错误将通过所有测试,因此您可能需要其他参考资料来调查这些问题。


26
即使是完美执行的TDD,也无法避免性能,系统交互,第三方交互等生产问题。并发问题也很难通过测试完全涵盖。100%的测试覆盖率“仅”表示您的代码已执行了100%,并非在所有状态或环境中都是正确的。
Holstebroe 2014年

34

日志记录对于解释应用程序的非异常行为很有用:

事件日志记录在系统执行过程中发生的事件,以便提供可用于了解系统活动和诊断问题的审核跟踪。它们对于理解复杂系统的活动至关重要,特别是在用户交互很少的应用程序(例如服务器应用程序)的情况下...

无论应用程序如何测试,异常记录得如何,用户都可能会问,

您程序的输出为0,而我们期望为1,为什么呢?

您需要记录日志以验证什么是应用程序配置,参数和其他运行时详细信息,以解释其(非异常)行为。

从以上角度来看,日志记录更注重支持而不是开发。应用程序上线后,最好让其他人处理用户的问题,以使程序员专注于进一步的开发。

记录应用程序的功能可以使其他人了解程序行为,而无需深入研究代码,也不必分散开发人员的要求以解释正在发生的事情。


5
+1表示“日志更多地基于支持”。真的打在了头上。
Tibos

1
+1表示“非异常行为”,也表示“日志记录更多地基于支持”。但是,您能否编辑您的答案以列出您引用的段落的来源?
logc

引用的@logc来源在第一个单词“日志记录”中的链接被引用-如果单击它,将带到Wikipedia文章:en.wikipedia.org/wiki/Logfile
gnat 2014年

16

这里的大多数答案都集中在正确性方面。但是日志记录也有不同的目的:日志记录可以是一种收集性能相关数据的方法。因此,即使系统正常运行,日志也可以告诉您为什么它运行缓慢。即使全面覆盖了所有方面的测试,测试套件也无法说明。

当然,性能关键型系统可以/应该为某些操作仪表板提供关键性能指标,但是“经典”日志记录可以提供不同级别的详细信息。


2
另外,不要忘记出于审计跟踪目的而记录日志。或计费。或各种统计。或事件日志记录,用于与其他系统的其他统计信息进行匹配。
PlasmaHH 2014年

概要分析是否可以不登录就做?还是只是意味着您可以连续记录分析结果?
Bergi 2014年

@Bergi:完全取决于您的应用程序如何工作。如果它是一个Web应用程序,则记录每个请求的服务时间,然后稍后尝试将这些事件聚类为“不良执行者”也可能起作用。
PlasmaHH 2014年

@Bergi分析是在开发过程中发生的,但要牢记对实时系统有影响,使用磁盘可能会变慢,CPU可能会加载得更多,服务可能无法及时响应,并行线程可能会遇到锁定问题……
johannes

@PlasmaHH审核是核心要求的一部分,必须包含在测试中。在大多数情况下,我不会在“常规”日志记录路由上运行它。普通日志记录可能会失败,而审核不会失败。我根据表现收集了“各种统计数据”;)
johannes

8

对您的主要问题的简短回答是:通常,TDD不会公开您代码中的错误。有些可能,理想情况下很多,但是没有失败的测试并不意味着没有错误。这是软件测试中非常重要的准则。

由于您可能无法知道系统中是否有不正确的行为(可能是在极少数情况下),因此日志记录是一个有用的工具,可以帮助您了解不可避免的错误发生时的错误。

日志记录和TDD解决了不同的问题。


7
  1. 除非您有100%的测试覆盖率(通常不是这种情况),否则您将不知道您的软件将永远不会崩溃(编辑:并且-如评论中所述-即使这样做,与软件无关的某些事情也可能导致崩溃);这与认为您可以制作完全没有错误的软件(甚至NASA都无法做到)相同。因此,至少,您需要记录可能的故障,以防程序崩溃,以便您知道原因。

  2. 日志记录应由外部库或内部框架来完成,具体取决于您所使用的技术。我的意思是说,它应该是以前已经测试过的东西,而您不需要测试自己。测试每种方法记录其应做的事情是过分的。

  3. 日志不用于测试,任何情况下都不应存在依赖性。就是说,尽管日志应该保存在与环境相对应的文件中(如果您应该在测试,开发和生产环境中使用不同的文件),但是如果感觉受到限制,则无需禁用测试日志记录至少)。

  4. 错误可能非常不清楚,而且当一个TDD测试失败时,错误并不总是很明显。日志应该更精确。例如,如果您正在执行排序算法,并且整个测试用例都失败了,则应该为算法的每个测试提供日志,以帮助您找出问题的根源。


3
即使您拥有100%的覆盖率,您是否也能针对可能发生的所有事情进行覆盖?如果与您的数据库的网络连接断开怎么办?您的测试会告诉您吗?
Zachary K

如果您具有100%的覆盖率,您将永远不会知道您的软件将永远不会崩溃。100%的覆盖率虽然很理想,但提供的正确性信息却少得多。
Andres F.

是的,您也是正确的。关键是,不可能发生崩溃是不可能的。我会编辑。
皮埃尔·阿劳德

1
编辑仍然不正确。即使您具有100%的测试覆盖率,代码中也可能存在错误(无需责怪外部原因)。测试并不意味着您的代码有效。他们唯一可以肯定地暗示的是,您未能编写发现错误的测试:)测试覆盖率是一项重要指标,但与缺少错误没有直接关系。
Andres F.

3
证明“ 100%的测试覆盖率通过!=无错误”是微不足道的。反例:(add(x, y) = 2总是返回2)。以下测试通过并提供完整的覆盖范围:assert(2 == add(1,1))。越野车功能的100%测试覆盖率:)
Andres F.

5

是的,通常情况下,您需要记录日志。

记录与调试无关。好吧,好的,日志记录的一部分有时与调试有关,如果在开发过程中不需要它,则可以跳过该部分。

但是日志记录的更重要的部分是关于可维护性。设计良好的日志记录可能会回答以下问题:

  • 该应用程序仍然存在并且可以运行吗?(通过每1000秒记录一次心跳。)
  • 在过去的10个月中,应用程序的性能是否发生了变化?(通过记录用例的性能统计信息。)
  • 在过去的10个月中,应用程序的负载是否发生了变化?(通过记录每种请求类型的请求数。)
  • 我们的接口有没有改变其性能特征?
  • 新版本是否会对某些子系统造成不同的使用特性?
  • 我们受到DoS攻击吗?
  • 发生什么类型的错误?

所有这些都可以通过日志记录来实现。是的,应该进行计划,设计和测试,最好是自动进行。

与其他功能一样,日志记录功能值得我们重视。


4

TL; DR:日志记录和TDD是正交的。有一个与需要另一个无关

如果正在执行TDD,是否需要记录?失败的测试不会揭示应用程序有什么问题吗?

总的来说,我已经实现的大多数日志记录都是用于操作故障排除,而不是用于开发调试(尽管可能会有所帮助)。此日志记录的主要受众是运行服务器的管理员和操作人员,支持将日志发送给他们以进行分析的人员以及希望查看日志并尝试弄清楚正在发生什么的客户。

这些日志可以帮助您解决集成点上的问题。这可能包括网络服务(数据库,肥皂等),本地资源(磁盘,内存等),不良数据(客户输入,不良/损坏的数据源等)等。捕获异常,记录故障,甚至进行信息性记录(设置,配置等)都可以帮助您进行故障排除。

是否应该在每个类的每个方法中为日志记录过程添加测试?

在需要的地方添加测试以测试日志记录。如果您有临时呼叫要注销信息,则应该对其进行测试。尽管如果您使用面向方面的编程或元编程来实现日志记录和日志测试,则可以减轻测试的负担。

例如,如果在生产环境中禁用了某些日志级别,这是否会在测试和环境之间引入依赖性?

如果您使用IoC编写代码并使用了模拟程序,那么您应该能够有效地测试所有日志记录,而无需依赖特定的环境设置。


3

TDD通常有助于减少编码错误。它对于规范中的错误或对工作原理的误解的帮助不大。

“哦?您可以确认登录成功之前得到一条数据消息?我不知道,好吧,它无法处理!”……这种事情。日志记录对于告诉您该软件试图执行的操作非常有用,这样您就可以发现您做错了什么。


2

根据我的经验,当我们不执行TDD时,会将大量日志记录添加到应用程序中。然后不确定性级别变高,因此我们添加日志记录以查看发生了什么。

而在进行TDD时(或者可能需要进行测试),我发现自己添加的日志语句要少得多。反过来,这意味着更少的LOC,并且可能(并非总是)影响性能。

但是在大多数情况下,无论开发方法如何,我们都会以半自动方式为函数添加进出日志。据我所知,这对于生产问题分析是必不可少的。

示例可能是公共接口上存在的EJB服务bean的方法。当函数执行复杂的计算时,可能是另一种情况。有数字输入方法会很有帮助(例如,您可以编写单元测试以回到手头的一般主题)。


您能否解释一下为什么要添加功能的出入日志的原因?为什么您的公司需要这样做?
gnat 2014年

是的,一点没错。我希望现在会更好。
dbalakirev 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.