3

假设我正在开始一个新项目,质量是重中之重。

我计划进行广泛的单元测试,当我在架构上工作以简化和支持进一步的单元测试时,要记住什么是重要的?

编辑:我前段时间读过一篇文章(我现在找不到了)谈论如何将实例化代码与类行为解耦在单元测试时会有所帮助。这就是我在这里寻求的设计技巧。

4

5 回答 5

4

通过能够用测试代码(模拟、伪造等)替换您的方法所具有的尽可能多的依赖项,可以轻松进行测试。目前推荐的实现这一点的方法是通过依赖项倒置,也就是好莱坞原则:“不要调用我们,我们给你打电话。” 换句话说,您的代码应该“请求事物,而不是寻找事物”。

一旦你开始这样思考,你会发现代码很容易依赖很多东西。您不仅依赖于其他对象,还依赖于数据库、文件、环境变量、操作系统 API、全局变量、单例等。通过坚持良好的架构,您可以通过适当的层提供这些依赖关系,从而最大限度地减少这些依赖关系。因此,在进行测试时,您不需要一个充满测试数据的工作数据库,您可以简单地将数据对象替换为模拟数据对象。

这也意味着您必须从对象执行中仔细挑选对象构造。放置在构造函数中的“new”语句会生成一个很难用测试模拟替换的依赖项。最好通过构造函数参数传递这些依赖项。

另外,请牢记得墨忒耳法则。不要在一个对象中挖掘超过一层,否则你会创建隐藏的依赖关系。调用 Flintstones.Wilma.addChild(pebbles); 意味着您认为对“Flintstones”的依赖实际上是对“Flintstones”和“Wilma”的依赖。

于 2010-01-28T13:09:20.630 回答
1

通过使其高度内聚、低解耦来确保您的代码是可测试的。并确保您知道如何在单元测试期间使用模拟工具来模拟依赖项。

建议你先熟悉一下SOLID 原理,这样你才能写出更可测试的代码。

于 2010-01-28T01:43:30.780 回答
1

您可能还想查看这两个 SO 问题:

于 2010-01-28T02:22:12.380 回答
1

一些随意的想法:

  • 定义你的接口:将功能模块相互解耦,并决定它们如何相互通信。接口是不同模块的开发者之间的“契约”。然后,如果您的测试在接口上运行,您可以确保团队可以将彼此的模块视为黑匣子,从而独立工作。

  • 首先构建和测试至少 UI 的基本功能。一旦您的项目可以与您“对话”,它就可以告诉您哪些有效,哪些无效……但前提是它不会对您撒谎。(奖励:如果您的开发人员别无选择,只能使用 UI,您将很快发现易用性、工作流程等方面的任何缺点。)

  • 在最低的实际水平上进行测试:你对小块的工作越有信心,就越容易将它们组合成一个工作的整体。

  • 在开始编码之前,根据规范为每个功能至少编写一个测试。 毕竟,功能是您的客户购买您产品的原因。确保它的设计目的是做它应该做的事情!

  • 当它做了它应该做的事情时不要满足;确保它不会做它应该做的事情! 输入坏数据,以不合逻辑的方式使用它,在数据传输期间断开网络电缆,与冲突的应用程序一起运行。你的客户会的。

祝你好运!

于 2010-01-28T02:37:25.530 回答
0

您的测试只会与您的要求一样好。它们可以是您一次性提出的要求,可以是您在添加功能时一次提出一个要求,也可以是您在发布后提出的要求并且人们开始报告一大堆错误,但如果没有人能够或不会准确记录事情应该做什么,那么您就无法编写一个好的测试。

于 2010-01-28T02:16:59.487 回答