什么时候使用单元测试?

5

我知道如何实现单元测试,但是我不确定什么时候需要使用它们。

假设我有一个基本的提醒应用程序。用户可以添加/编辑/删除提醒并在表视图中查看它们。我应该为应用程序的哪些部分设置单元测试?


你的“代码单元”,例如类、方法等。 - Robert Harvey
4个回答

6
理想情况下,每一行你编写的代码都应该进行单元测试。但是让我们暂时忘记这个,回到现实世界。为重要的代码编写测试并拥有另一道防线是值得的。换句话说,测试一个仅将值分配给一个字段的构造函数是否有意义?很可能没有。而对从客户端提供的复杂XML中提取账户数据的解析器进行单元测试是否值得?很可能是的。
这种差异的原因在哪里?主要有两个:
1. 构造函数代码不太可能遭受不可预测的更改(与经常发生变化以满足需求/优化/重构的解析器代码相比); 2. 构造函数代码相当简单,你已经多次编写过这样的代码,测试可能无法在发现问题方面为你带来巨大优势;快速查看这样的代码,你很可能能够知道发生了什么(与复杂的XML解析器代码相比)。
为什么要区分这些?为什么要测试这个而不是那个?难道直接测试所有东西(如理想情况下所建议的)不是更容易吗?
由于时间和金钱的限制,不行。编写代码需要两者。人们愿意为你的产品支付的金额是有限的,就像他愿意等待产品交付的时间也是有限的。有些测试根本不值得(例如构造函数代码示例)。请记住,单元测试并不免受收益递减的影响(用测试覆盖80%的代码库可能需要额外的20%开发时间,并且后续节省20%的调试/维护时间,而再进行10%的测试可能需要两倍的时间,但带来的效益要小得多)。
同样,您可能想问“在哪里划线?” 什么时候决定“好吧,这段代码不真正需要单元测试”?不幸的是,这种判断需要经验。编写代码,阅读代码,看看其他人(可能是更有经验的开发人员)做什么并学习。
如果我要给出一些通用建议(要进行单元测试的内容),那将是:
  • 从业务/领域逻辑代码开始
  • 确保测试各种转换器/解析器/计算器(它们很容易测试,倾向于经常更改[由于需求变化或重构],并且由于其性质容易出错)
  • 避免测试简单的一行方法,除非那一行在某种程度上至关重要
  • 为您发现的错误编写测试(并保留它们!)
  • 不要盲目遵循“好代码必须有99.99%的测试覆盖率”的神话
  • 阅读问题 关于主题programmers.stackexchange.com上,可以让您以不同的视角来解决问题

+1 - 我喜欢这个 - 写得很好! - Till

1
假设您将提醒存储在某个地方,可能是在plist中。您可以编写一个单元测试来生成一个Reminder对象,存储它,检索数据,最后生成可用的Reminder类对象。
这样你就知道几件事情:
A:您的Reminder生成正在工作
B:您存储数据的方法正在工作
C:从数据到您的Reminder对象正在工作
但是,您不应该期望能够对应用程序的实际“功能”进行单元测试。例如触摸事件或导航控件。这些应该留给验收测试,这是完全不同的讨论。

1

测试你编写的所有代码。如果你想真正酷一点,先编写测试。如果你有一个模型或控制器上的方法,你也应该为它编写一个测试。

不了解你的代码更多信息,很难提供建议。但听起来你会有一个控制器(比如RemindersController)和一个模型(比如Reminder)。这是我会开始的基本概述:

  • RemindersController

    • 应该添加新提醒
    • 应该更新现有提醒
    • 应该删除现有提醒
  • Reminder

    • initWithMessage:atTime: 应该设置消息
    • initWithMessage:atTime: 应该设置时间

我也鼓励您尽可能地测试您编写的每一行代码。可以参考Graham Lee的书《Test Driven iPhone Development》:http://www.amazon.com/Test-Driven-iOS-Development-Developers-Library/dp/0321774183 - Kasper Munck

0

在选择编写测试类型和时间时,我遵循以下原则:

  • 专注于编写端到端测试。相比单元测试,每个测试可以覆盖更多的代码,因此可以获得更多的测试效果。将其作为系统整体的主要自动验证。

  • 针对复杂逻辑的核心部分编写单元测试。在难以调试或编写足够代码覆盖率的端到端测试的情况下,单元测试非常有价值。

  • 等待正在测试的API稳定,然后再编写任何一种类型的测试。您希望避免重构实现和测试的情况。

Rob Ashton在这个主题上有一篇好文章,我从中大量借鉴了上述原则。


"等待你正在测试的API稳定下来" - 这样做会破坏TDD的一个主要优点,即你的测试是API的第一个客户端,根据我的经验,这会导致比在生产代码之后编写测试时更好的API。 - Frank Schmitt
@Frank:我同意你想要编写足够的代码来磨练你的API的可用性。也许这是以单元测试的形式,但也可能是你必须编写的其他实现代码,或者两者都有。无论如何,重点应该是真实世界的使用情况。为了最小化重新工作量,请仅编写足够的代码来验证您的API设计。 - Edward Brey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接