2.3 重构的安全保证
重构是一项日常工作,而不是阶段性工作,不要等东西坏到无法再修只能丢掉,而是一旦发现损坏马上维修。 如何保证重构不引入新的问题:
一个完备的、可自动化运行的用例库无疑是重构最好的安全保证。
2.4 明确编码的目标
关键在于 “用户怎么来用这个新特性”
先写测试代码的另一个好处在于测试帮助你集中在新特性的接口上而不是其实现。你会问自己“用户怎么来用这个新特性?” 让测试跑起来是给这个特性作了结论,你也就清楚了自己将要作的是什么。
3、如何进行测试驱动开发
下面结合我在端口管理模块的开发工作中实践测试驱动开发的经验谈谈几点关于“如何进行测试驱动开发”的看法。
3.1 测试驱动开发,作的是单元测试
单元测试和集成测试、系统测试不同,单元测试是直接验证开发者代码实现内部逻辑性、外部需求特性是否正常的测试方法。这些是在编码之前一个开发者最需要考虑的事情,也就是“开发前测试”需要考虑的事情。单元测试应该脱离一个正常运作的系统、一个已经集成好了的功能子系统来进行。不要以集成测试、系统测试的角度来看待单元测试。
单元测试关心的是:
(1)单元外部需求的满足性。注重契约式编程中外部接口的前后契约条件检验,如前置契约不满足,外部接口应该返回失败,前置契约满足,则外部接口的输出、返回、对代码上下文语义环境的结果影响应该满足后置契约的要求。
(2)单元内部实现应满足的设计语义假定(包括值域的、代码逻辑的),这些假定在编码时通过断言来表达(ASSERT),测试时就可以直接作为检测手段。
3.2 根据需求与设计方案设计用例
设计用例时需要考虑的无非也就是如下两点:
(1)需求,这个是外部特性,在用例设计上必须以需求作为检查目标。这是首要的。
(2)设计,这个是内部特性,在用例设计上应该对设计完备性(已经能直接指导编码)、以及设计的语义假设进行检查,如果设计不够完备,那么当然无从检验编码该达到什么目标,因为连蓝图都没有,无从校对起。语义假设是什么? 语义假设,是设计的内部逻辑特性。比如顺序内聚性就是一种语义假设(在作A之前,必须先满足条件B,那么你就需要在调用A时检测条件B是否满足)。语义假设检查主要通过ASSERT进行,下面会谈到。设计太粗则不够完备,无法针对设计方案进行细致的用例设计,必然导致测试得太粗。
如果觉得用例写不下去,那么就不要硬写,而是需要好好琢磨一下以上两点是否合理。在编码之前先写用例意味着:此时还没有“实现代码”,不存在实现的合理性问题,如果有不合理,则只会是需求或者设计上的不合理,测试驱动的一大好处也就是能在开发的前期发现这两个起着决定性作用的研发环节的缺陷。
3.3 自动化测试
CUnit测试框架是一个比较好的自动化运行测试用例的手段。它可以用一个明显的方式规范化的向你表达:你的测试用例是都pass了,还是有的fail了。
如果你的项目还没有集成CUnit测试框架了的VC版本,请尽快集成。
必须做到能够100%自动化运行你的测试用例,不要干需要人工核对才能确认正确与否的傻事。
每一次对代码进行了修改,都要运行已有的所有测试用例确保无误。