如何为系统编写开发人员测试(单元测试、集成测试等)



我有一个WCF服务,它运行并与数据库,文件系统和一些外部web服务交互,然后创建结果并对其进行Xml序列化并最终返回。

我想为这个解决方案编写测试,我正在考虑如何(它都使用依赖注入和契约式设计)。

我可以采取三种主要的方法。

1)我可以选择最小的代码/方法单元并为其编写测试。选择一个类,并将其从依赖项(其他类等)中隔离出来。虽然它保证了质量,但它需要花费很多时间来编写它们,而且速度很慢。

2)只使与外部系统的交互可模拟,并编写一些测试,涵盖从请求发出到响应序列化和返回的主要场景。这将测试类之间的所有交互,但模拟所有外部资源访问。

3)我可以设置一个测试环境,其中与外部web服务的交互发生,文件访问发生,数据库访问发生,等等。然后从头到尾编写测试。这需要环境设置和对所有其他系统的依赖都已启动并运行。

关于#1,我认为没有必要投入时间/金钱/精力为我拥有的每个方法或代码编写测试。我是说这是浪费时间。

关于#3,因为它依赖于外部资源/系统,所以很难设置和运行它。

#2,对我来说是最好的选择。因为它会测试它应该测试的东西。只有我的系统和它的所有类,并嘲笑所有其他外部系统。

所以基本上,经过几年的单元测试经验,我的结论是编写单元测试是一种浪费,应该避免,相反,孤立的系统测试是最好的投资回报。

即使我打算先写测试(TDD),然后再写产品代码,我仍然认为#2是最好的。

你对此有什么看法?您会为您的应用程序编写小型单元测试吗?你认为这是一种很好的实践,是对时间/预算/精力的最佳利用吗?

如果你想谈论质量,你应该有三个:

  1. 单元测试,以确保你的代码做你认为它做的,暴露任何边缘情况,并帮助回归。你(开发者)应该编写这样的测试。
  2. 集成测试,以验证整个过程的正确性,组件是否正确地相互通信等等。同样,您作为开发人员编写这样的测试。
  3. 在类似生产环境中的系统范围测试(当然有一些限制—您可能无法访问客户端数据库,但是您应该在本地机器上拥有其精确的副本)。这些测试通常由专门的测试人员编写(通常使用与应用程序代码不同的编程语言),但当然也可以由您编写。

第二和第三种类型的测试(集成和系统)对于测试较小组件的边缘情况将会花费太多的精力。这就是您通常需要进行单元测试的目的。您需要集成,因为在连接已测试、验证和正确的模块时可能会出现故障。当然,系统测试是你每天都要做的,在开发过程中,或者有指定的人(手动测试人员)来做。

从列表中选择测试类型可能在某种程度上起作用,但远远不是完整的解决方案或高质量的软件。

这三个都是重要的,针对不同的测试类型,这是单元/集成/系统类别的矩阵,每个类别中都有积极和消极的测试。

对于代码覆盖率单元测试将产生最高的百分比,其次是集成,然后是系统。

您还需要考虑测试的目的是验证(将满足最终用户/客户需求,即价值)还是验证(写入规范,即正确)。

总之,答案是"视情况而定",我建议遵循SEI CMMi模型进行验证和确认(即测试),该模型从每个活动的目标(价值)开始,然后使该活动服从于最终将使整个过程受到持续改进的措施。通过这种方式,你已经将"是什么"one_answers"为什么"从"如何"中分离出来,并且你将能够回答给定环境(可能是生命支持系统或当天的Tweet,给你最喜欢的阿姨,应用程序)的时间和价值类型的问题。

总结: #2(集成测试)似乎是最合乎逻辑的,但是您应该毫不犹豫地使用各种测试来实现对最需要它的代码库片段的最佳覆盖。为"一切"进行测试并不是一个值得追求的目标。

长版

有一种思想流派认为,开发人员相信采用单元/集成/系统测试意味着努力测试每一段代码。要么根本没有测试覆盖,要么承诺测试"一切"。这种二元思维总是使采用任何一种测试策略显得非常昂贵。

事实是,强迫每一行代码函数模块都进行测试,就像尽可能快地编写所有代码一样合理。这需要花费太多的时间和精力,而且大部分的回报很少。另一个事实是,你永远不可能在一个重要的项目中实现真正的100%的覆盖率。

测试本身不是一个目标。它是实现其他事情的一种手段:最终产品质量、可维护性、互操作性等等,同时花费尽可能少的努力。

记住这一点,退后一步,评估一下你的具体情况。为什么要"为这个解决方案编写测试"?您对今天项目的整体质量不满意吗?你是否经历过高退步率?您可能不确定某些模块是如何工作的(更重要的是,它可能有什么bug)?不管你的确切目标是什么,你都应该能够选择具有特定挑战的部分,并将注意力集中在它们上面。根据这些部分的内容,可以选择合适的测试方法。

如果你有一个特别棘手的函数或类,考虑对它们进行单元测试。如果您面临一个复杂的体系结构,其中包含多个难以理解的交互,请考虑编写集成测试,为您最棘手的场景建立一个干净的基线,并更好地了解问题的来源(您可能会在此过程中清除一些错误)。如果您的关注点没有在更本地化的测试中得到解决,系统测试可以提供帮助。

基于您为特定场景提供的信息,面向外部的单元测试集成测试(#2)看起来最有希望。看起来你有很多外部依赖关系,所以我猜这就是大多数复杂性隐藏的地方。综合单元测试(#1)是#2的超集,所有额外的内部内容都带有可疑的价值。#3(完整系统测试)可能不允许您测试外部边缘情况错误条件,以及您想要的。

最新更新