技术开发 频道

测试驱动开发之可执行的文档

  那么为什么要用TDD来执行文档的功能呢?这就要说说文档的一些问题了。

  首先要说的是,文档有很多的好处,这已经被广泛认可了,否则我也不用在这里说TDD的文档功能了;其次文档不一定非要是文字或图表的形式,我们的最终目的是要用文档来表达一些信息,一些从代码里无法得到或不容易得到的信息。传统文档如UML图,或是用NDoc之类的软件生成的API参考已经可以传达这些信息了,但是他们也有一些缺点:

  1. 文档与代码不同步。通常代码永远都是最新的,而文档则会有一个滞后期,维护文档和代码的同步成本非常高,许多项目会因为这个成本而导致文档和代码不同步。这时候文档根本描述不了代码,而文档的意义也已经不存在了,要么你从文档中得到错误信息,要么用更多的时间去看代码。如果使用TDD的方式写代码,由于实现每个函数之前必须要先写相关的测试,保证了每个(public)函数都有文档说明,同时当函数行为发生变化时,也必须先添加或修改测试,保证了测试这份文档永远是最新的。

  2. 项目进行中没有API文档。API的说明文档很多都是在代码完成后才写成的,项目进行时,经常会出现某个人误用另一个人写的函数而导致bug的情况。使用 TDD的方式,可以通过阅读测试代码来学习如何使用其他人写的类或方法,比直接读实现代码更有效,可以很好的避免误用的情况,有助于提高质量。

  3. 写文档成本太高,没时间写,程序员不喜欢或不擅长写文档。TDD作为一个开发实践有多种功能,文档只是其中之一,同样时间内用TDD可以获得更多的收益,降低了文档的成本。同时,测试也是用程序员熟悉的语言写成,程序员比较容易掌握。

  那是不是只要TDD就好了,不需要其他的文档了呢?当然不是,TDD的文档功能有很多好处,但是什么东西都不是功能较多的,我们还是需要配合多用形式的文档来达到我们的目的。具体实践时可根据对TDD的掌握程度,项目对文档的要求,团队对文档的要求,来决定用什么形式来撰写文档。

  使用TDD的文档功能时需要非常注意代码的可读性,这是它能否执行文档功能的一个重要条件。

  再来一个UAT测试的例子:

  public void should_not_create_publication_in_offline_mode_when_click_no()

  {

  using (ribbonTestUtility = new RibbonTestUtility())

  {

  ribbonTestUtility.StartWordInOfflineMode();

  ribbonTestUtility.ClickCreatePublication();

  OfflineWarningDialogModel warningDialogModel = ribbonTestUtility.GetOfflineWarningDialog();

  warningDialogModel.ClickNo();

  EftAssert.IsWindowNotExists(ribbonTestUtility.EftApplication,

  RibbonElementName.SETUP_WIZZARD_WINDOW_TITLE);

  }

  }

  用下划线来分割单词虽然不符合C#的命名规范,可是提高了可读性,因为Pascal Case的方法名很长时可读性会很差,毕竟命名规范是为了提高可读性而设计的。方法名应该表示该测试的意图,并符合英语语法,可以当成普通的英语句子阅读。

  我的一个同事曾经参加过一个项目,在这个项目中有很多领域词汇,很难用英语表达出来,即使表达出来看的人也很难理解。考虑到沟通成本以及项目中并没有老外存在的情况,他们决定使用中文TDD,用中文给测试用例命名。虽然用中文写代码并不是很好的实践,但在这个项目中确实能够解决问题,可以说应变的非常好。也希望大家能够认清技术和实践的本质和目的,灵活运用,避免盲从。

  总结

  TDD除了可以验证功能外,还具有文档功能。它永远保持最新,可以表达程序意图,并且可以编译执行,是可执行的文档。但是决不能用TDD文档代替所有文档,需要在项目中进行权衡。在实践中,代码可读性影响着TDD文档功能的效果,表达不了意图的代码是无法执行文档功能的。

0
相关文章