【问题标题】:How to approach writing developer tests (unit tests, integration tests, etc) for a system?如何为系统编写开发人员测试(单元测试、集成测试等)?
【发布时间】:2013-03-28 20:09:08
【问题描述】:

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

我想为此解决方案编写测试,我正在考虑如何(这一切都使用依赖注入和合同设计)。

我可以采取 3 种主要方法。

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

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

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

关于#1,我认为将时间/金钱/精力投入到为我拥有的每一种方法或代码编写测试上是没有意义的。我的意思是这是浪费时间。

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

#2,听起来对我来说是最好的选择。因为它将测试它应该测试的内容。只有我的系统和它的所有类,并模拟所有其他外部系统。

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

即使我要先编写测试 (TDD) 然后编写生产代码,我认为仍然 #2 是最好的。

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

【问题讨论】:

    标签: asp.net unit-testing testing service tdd


    【解决方案1】:

    如果你要谈质量,你应该具备所有 3 个:

    1. 单元测试以确保您的代码按照您的想法执行,暴露任何边缘情况并帮助regression。你(开发者)应该编写这样的测试。
    2. 集成测试以验证整个过程的正确性,组件之间对话是否正确等等。同样,您作为开发人员编写此类测试。
    3. 在类生产环境中进行系统范围的测试(自然会有一些限制 - 您可能无法访问客户端数据库,但您应该在本地计算机上准确复制它)。这些测试通常由专门的测试人员编写(通常使用与应用程序代码不同的编程语言),但当然也可以由您编写。

    第二种和第三种类型的测试(集成和系统)对于测试较小组件的边缘情况来说会花费太多精力。这就是你通常想要的单元测试。您需要集成,因为连接经过测试、验证和正确的模块可能会失败。当然,系统测试是您每天在开发过程中所做的事情,或者是指派人员(手动测试人员)去做。

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

    【讨论】:

    • 从安全/隐私的角度来看,在本地开发机器上拥有客户端数据的精确副本是一个非常糟糕的主意。
    • @DanielS。 - 当然。如果您无权访问客户端数据库,则很难制作精确的数据副本,对吧? 精确复制是指数据之间的结构和关系。您可以在没有任何敏感/真实信息的情况下实现这一目标。
    【解决方案2】:

    所有 3 项都很重要,并且针对不同的测试类型,即单元/集成/系统类别的矩阵,每个类别都有正面和负面的测试。

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

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

    总而言之,答案是“视情况而定”,我建议遵循 SEI CMMi 验证和确认模型(即测试),该模型从每个活动的目标(价值)开始,然后对该活动进行衡量,最终将让整个过程得到持续改进。通过这种方式,您将“什么”和“为什么”与“如何”隔离开来,并且您将能够针对您的给定环境(可能是生命支持系统或当天的推文,向您最喜欢的阿姨、应用程序)回答时间和价值类型的问题)。

    【讨论】:

      【解决方案3】:

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

      加长版

      有一种思想流派,开发人员坚信采用单元\集成\系统测试意味着努力测试每一块被测试的代码。它要么根本没有测试覆盖率,要么致力于测试“一切”。这种二元思维总是让采用任何一种测试策略都显得非常昂贵。

      事实是,强制测试每一行代码\函数\模块与尽可能快地编写所有代码一样合理。这需要太多的时间和精力,而且大部分收益都很少。另一个事实是,您永远无法在一个重要的项目中实现真正的 100% 覆盖。

      测试本身并不是目标。这是实现其他目标的一种方式:最终产品质量、可维护性、互操作性等,同时花费尽可能少的工作量。

      考虑到这一点,退后一步,评估您的特定情况。为什么要“为此解决方案编写测试”?您对今天项目的整体质量不满意吗?你经历过高回归率吗?您是否不确定某些模块是如何工作的(更重要的是,它可能有什么错误)?无论您的确切目标是什么,您都应该能够选择具有特殊挑战的作品并将注意力集中在它们身上。根据这些部分是什么,可以选择适当的测试方法。

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

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

      【讨论】:

        猜你喜欢
        • 2010-11-20
        • 2010-10-23
        • 1970-01-01
        • 2012-12-20
        • 1970-01-01
        • 2011-09-01
        • 2017-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多