测试是需要成本的,也需要考虑当时当地的实际情况的,这就是一方面我非常强调测试,但也可能在特定的情况下完全没有传统意义的测试的原因。
另一方面,对测试的理解和实践是因人而异的(或者说存在某种进阶,这种进阶由软件实践的经验和能力相对决定),根据进阶不同,对其理解和实践就会不同。
在这里,包括单元测试究竟是不是设计以及在细致区分单元测试和测试用例都可以有不同的理解和实践。这些理解和实践没有绝对的对与错,而只是在粒度和看问题的角度上有所不同,或者说软件实践经验的不同。
但,尽管存在不同的理解和实践,我们却可以把分歧统一在一个前提下:
那就是一切为了更好的软件实践。
从这个基本点出发,测试可以被看作传统意义的测试,也可以看作是设计的一部分或者是辅助设计,根据测试粒度的不同产生的其他的分歧也不再是问题,甚至是更具挑战性的理解和实践:测试可以看作测试,传统意义的代码本身也可以看作测试(从这里也可以引申为设计和代码实践的随意性或者也可以说是一种非常自然的更高级的软件实践)。在我的软件实践里,我更喜欢这种实践模式,当然,这是有前提的,他必须和具体软件项目、人员、时间和其他辅助资源相适应,而不是一种必然选择。显然,在很多软件环境下,我会采用适当保守的做法来保证我的队伍可以轻松而且可靠地完成工作,这就是软件赋予我们的灵活性。
实际上,讲到这里,怎么做可能是更好的实践已经有了答案,尽管这个答案不是明确意义的对错或者第1条第2条的方式给出的。我也试图谈论更多来更清楚这些回答,当然这些具体看法根据个体实践经验不同会存在不同的理解,这都是正常的。
记住,这里没有绝对性质的对错,凡是能够更好的辅助完成软件实践就是成功的。
我们时常提到测试驱动开发,但实际上真正符合的不多,通常所称的“测试驱动开发”只是有了单元测试而根本没有驱动的意味。很多问题由此产生,在很多时候我们谈论的差不多是两个不同的概念。正常的情况下,测试是可以作为主要设计手段的,至少是极好的辅助设计手段,根据粒度和规模的不同,就体现为不同的具体实践,包括传统意义的单元测试来测试单个的对象或者更大规模的对象群,这都是正确的实践。在这里,也可能存在测试转化问题,也就是开始作为设计的实践到后期的更趋向传统的测试,这是更具体的实践。
测试成本的要素包含很多方面,是否写了测试代码只是其中一个重要部分,是否采用JUint以及Mock对象更加不是对其评价的决定性因素。对测试的更好评价应该是额外代码、测试可重复性、测试范围和边界值识别等综合构成(测试对设计的作用是更高级的判定)。
对于涉及到数据库持久方面的测试、涉及到UI(浏览器或者富客户端)交互的测试以及多对象多方法过程的测试(也可体现为UI交互,这里是指独立性质的)等,以及上面说到的一些问题(不再重复),是我们现实测试实践要面临的问题。对这些问题的解决,就会更多的涉及到项目具体情况的选择和具体项目和团队的情况来作最佳判定,这就是成本的意义。我在这里还想提醒在关注这些具体的项目因素的同时,还要注重下面的问题:
对象的所有者和使用者问题;
不要单纯意义上理解测试,有些测试可以采用单元测试之外的手段完成;
项目在不同进展阶段测试的便捷性(也可体现为大分层概念)。
测试,是一个理解和实践都可能差异很大的软件实践,它包含了具体的代码实践,也是需要和项目治理和设计相适应的方法论,当然,也是体现实用哲学的软件思想。
在方便的时候,我很乐意具体阐述我在测试上的实践经验和教训(如讲座),也可以就我正在实践和思考的更具挑战性的思考和实践进行探讨。