我们编写测试来验证程序行为的正确性。
通过用眼睛检查输出语句的内容来验证程序行为的正确性是一个手动操作,或者更具体地说,是一个视觉过程。
你可以争辩说
目视检查有效,我检查代码是否做了它应该做的事情,对于这些场景,一旦我可以看到它是正确的,我们就可以开始了。
首先,很高兴您对代码是否正常工作感兴趣。这是一件好事。您走在曲线的前面!可悲的是,这种方法存在问题。
目视检查的第一个问题是,您是一个严重的焊接事故,无法再次检查代码的正确性。
第二个问题是,使用的一双眼睛与眼睛主人的大脑紧密耦合。如果代码的作者也拥有视觉检查过程中使用的眼睛,那么验证正确性的过程依赖于视觉检查员大脑中内化的有关程序的知识。
一双新的眼睛很难进来验证代码的正确性,因为它们没有与原始编码员的大脑合作。第二双眼睛的所有者必须与代码的原始作者交谈,以便完全理解所讨论的代码。众所周知,对话作为分享知识的手段是不可靠的。如果原始编码器对新的眼睛不可用,那么这一点是没有意义的。在这种情况下,新的眼睛必须阅读原始代码。
阅读单元测试未涵盖的其他人的代码比读取具有关联单元测试的代码更困难。在最好的情况下,阅读其他人的代码是棘手的工作,在最坏的情况下,这是软件工程中最繁琐的任务。雇主在宣传职位空缺时,强调一个项目是绿地(或全新的)项目,这是有原因的。从头开始编写代码比修改现有代码更容易,从而使广告工作对潜在员工更具吸引力。
通过单元测试,我们将代码划分为其组成部分。然后,对于每个组件,我们设置了我们的停顿,说明程序应该如何运行。每个单元测试都讲述了程序的该部分在特定场景中应如何操作的故事。每个单元测试都像合约中的一个子句,从客户端代码的角度描述应该发生什么。
这意味着一双新的眼睛在有问题的代码上有两条实时和准确的文档。
首先,他们有代码本身,实现,代码是如何完成的;其次,他们拥有原始编码人员在一组正式语句中描述的所有知识,这些语句讲述了该代码应该如何表现的故事。
单元测试捕获并正式描述原作者在实现该类时所拥有的知识。它们提供了该类在客户端使用时的行为方式的说明。
您质疑这样做的有用性是正确的,因为可以编写无用的单元测试,不涵盖所有有问题的代码,变得陈旧或过时等等。我们如何确保单元测试不仅模仿而且改进了知识渊博,尽职尽责的作者在运行时直观地检查其代码输出语句的过程?首先编写单元测试,然后编写代码以使该测试通过。当你完成后,让计算机运行测试,它们速度很快,它们擅长执行重复性任务,非常适合这项工作。
通过在每次启动它们测试的代码并为每个生成运行测试时查看它们来确保测试质量。如果测试失败,请立即修复它。
我们自动执行运行测试的过程,以便在每次构建项目时运行测试。我们还自动生成代码覆盖率报告,详细说明测试覆盖和执行的代码百分比。我们力求高百分比。如果某些公司没有编写足够的单元测试来描述代码行为的任何更改,则会阻止将代码更改签入到源代码控制中。通常,第二双眼睛将与更改的作者一起查看代码更改。审阅者将仔细检查更改,以确保更改易于理解并被测试充分覆盖。因此,审查过程是手动的,但是当测试(单元和集成测试以及可能的用户验收测试)通过此手动审查过程时,就会成为自动构建过程的一部分。每次签入更改时都会运行这些操作。持续集成服务器在生成过程中执行此任务。
自动运行的测试,维护代码行为的完整性,并帮助防止将来对代码库的更改破坏代码。
最后,通过提供测试,您可以积极地重构代码,因为您可以安全地进行重大的代码改进,因为您知道您的更改不会破坏现有测试。
测试驱动开发有一个警告,那就是你必须编写代码,使其具有可测试性。这涉及对接口进行编码,并使用依赖关系注入等技术来实例化协作对象。看看肯特·贝克(Kent Beck)的作品,他很好地描述了TDD。查找接口编码并研究设计模式