RSpec是一个非常强大的测试应用工具。 它历史悠久且提供了丰富的功能。
其中一个功能就是在一个对象或类上存一个方法,使得它不再像通常那样执行及工作,而是返回硬编码的值,并不是实际执行。这里有一个简单的例子[1]:
该段代码中的第二行导致对student.grades的任何调用总是返回数组['A','A +','C']。 #grades方法的实际定义将永远不会被调用。在这个例子的基础上,我们可以想象,如果在我们的系统中存在一个Student类,那么可能存在一个GpaCalculator类。 进而,TDD这样的类也会建立。
作为参考点,使用DePaul大学Alma Mater的GPA量表,其中A转换为4.0等级点,B转换为3.0等级点。
这里是前几个测试可能是什么样子:
[2]
这里已经有点繁琐了。 有人看到这里可能会找机会重构一下,把它整理成如下的样子:
这当然更好, 不幸的是,很多人会到这里就停下了,继续其他的事情。对于这个小例子来说,这样做并没有什么不妥。但是在一个大的测试套件中,从长期来看,尽可能多的保持代码清洁是很重要的,这有助于提高代码的可维护性。
反复存根相同的方法,在每次测试中返回不同的数组(或hash),对于这种情况,是有一些技术可以消除繁琐并提高可读性的。
目前来说,我的建议是:
有点清洁了,不是吗? 我们将每个单独测试中的“stub this to return”的繁琐语法移动到before块。 剩下的是预期的GPA最基础的和直接影响它等级的。
有些人可能不喜欢前面的:每个块。 另一种方法是将存根直接放入相应的let块:
在我看来,这不是真的更好,但它是一个选择。
一个完全不同的方法是使用双精度[3],但避免完全使用:
经历了这些,你的最终版本可能会是这样:
请记住,虽然你的任务不是生产代码,也不需要运行您的业务,但它们仍然是您业务的关键部分。 如果它们很难阅读,修改或添加,那么开发起来将会受苦。 注意寻找重构它们并使它们更易于维护的方法。
[1]虽然本文使用RSpec和Ruby作为例子,这里提出的想法也适用于其他语言和它们各自的测试框架。
[2]为了举例,我们在这里将学生注入GpaCalculator。 一个更好的方法是简单地将学生的成绩传递到GpaCalculator,并完全消除GpaCalculator对学生的依赖。 这样你的GpaCalculator就是独立的,它可以在你代码的其他地方使用,而不一定要有Student对象。
[3] instance_doubles,a.k.a验证双精度,在RSpec 3中引入,并提供一些安全性,防止实际上不存在的存根方法。
【英文原文:https://8thlight.com/blog/dariusz-pasciak/2016/09/08/better-rspec-stubbing.html】
{测试窝原创译文,译者:亚然}
译者简介:亚然,软件测试爱好者,长期从事软件测试工作