不要依赖临时状态

上一次,我们讨论了构建iOS单元测试的四个简单规则。 我真的很想把所有要做的和不要做的事情放在一起写在一篇文章中,但是阅读起来实在太大了。 所以这是硬币的另一面。 关于您应避免的所有事情的系列文章。

信不信由你,完全有可能编写弊大于利的单元测试 。 在本文中,我们将研究一种依靠临时状态来弄乱单元测试的特殊方法。

什么是临时状态?

如果在使用您的应用过程中可能发生变化,那么就定义而言,这是暂时的或偶然的。 每个应用程序都会在内存或磁盘上存储某种临时状态。 许多应用程序从服务器检索临时状态。

每次您从某个可以写入的位置访问数据时,您都在访问临时状态 。 数据会随着时间变化。 今天得到的可能与明天得到的不一样。

Facebook上的用户可能会说他今天喜欢滑雪,但是明天他会说他喜欢滑雪。 他的爱好是暂时的。 您不能依靠它们随着时间的推移而变得相同。 如果您从服务器上检索他的业余爱好数据,则无法确定会得到什么。

单元测试绝不应依赖临时状态 。 它使他们变得善变。 如果有一天运行它们,它们将提供一个结果。 改天运行它们,它们会产生不同的效果。

单元测试应该是确定性的

这样,我的意思是每次您运行它们时,它们都应始终提供一致的结果。 确定给定单元测试是成功还是失败的事情不应是可能改变的外部事实 。 它应该是您的应用程序所依赖的核心逻辑。

如果单元测试依赖于用户默认设置,本地文件或服务器的响应,则它们不再是确定性的。 这是因为它们的成功或失败不仅仅取决于逻辑本身。

结果,您将无法非常有效地将单元测试用作诊断工具。 您如何知道代码或某些临时状态是否导致给定测试通过或失败? 你不会的 可能永远是。

这种无法确定测试成功或失败原因的能力有时称为脆弱性不稳定测试是由于与被测试代码不直接相关的原因而给出不同结果的测试

您绝对想避免这种情况。

这是片状测试的实际外观

假设您有一个应用程序,其中登录用户可以访问某些功能列表。 您可以通过以下方式实现访问授予机制。

如何修复片状单元测试

问题在于缺乏抽象。 shouldGrantAccessToFeatureWith(id 🙂需要知道用户是否已登录,可以通过直接转到用户默认值来进行登录。

如果将相同的逻辑重构为可以被子类覆盖的函数该怎么办?

在编写单元测试时,请始终问自己,该测试采用什么逻辑? 测试逻辑,然后抽象其他所有内容。

下一步是什么?

我目前正在阅读一系列文章,详细介绍在为iOS编写单元测试时应避免的一些体系结构方面的内容。 下一篇文章深入探讨了避免副作用。

目前,您可以了解我的其他一些单元测试内容

我们应该在iOS应用程序中进行哪些单元测试?

教程:如何在iOS应用中对私有方法进行单元测试。

我正在写有关iOS单元测试的书。 如果您有任何要我讲的建议或主题,请给我发电子邮件。