我们在某些财务软件中使用(可执行)规范和单元测试。规范涵盖了业务行为,单元测试涵盖了代码。我们也使用其他测试方法,例如自动化集成测试等,但这不是我在这里要求的。
有时我会编写代码,就其本质而言,我知道 - 并且将永远 - 完全涵盖规范,因为它是核心业务功能。一个例子是舍入规则。
在这些时候,我想要编写单元测试之间存在冲突(因为感觉业务需求可能会发生变化,即使它们看起来像上面那样,也会像永远存在的问题一样)感觉我在浪费时间编写“冗余”单元测试。
有没有人为此找到了良好的经验法则?
答案 0 :(得分:2)
...在这种情况下,速度不是问题。可执行规范和单元测试都非常快,实际上作为一个单元运行;规范包含在单元测试中,以便它们一起运行......
据我所知,除了可执行规范之外,进行单元测试无助于更快地发现错误,正确吗?
考虑到这一点,我想到的唯一经验法则是从一些 future maintainer 的角度来看待它。你知道,那个不认识你的人,那个不分享你现有知识的人 - 一个刚刚得到你的代码来处理的人。如何让那个人的生活更轻松?
让我们看看......
如果我选择编写重复的单元测试,这可能会混淆我想象中的未来维护者。 “为什么哦,为什么这个白痴写了重复的测试?他在想什么?”
如果我决定只是跳过单元测试,这也可能会让人感到困惑。 “哦,这不是单元测试所涵盖的,为什么会这样?是因为它已经被某些可执行规范所覆盖,或者因为有人忘了在这里编写单元测试?”
在这两种情况下,问题似乎都是我没有透露我的意图。我没有说明为什么我这样或那样做的原因。解决方案分别是找到表达我的意图的方法。为此,我将使用注释或自解释代码,如
assertTrue("missing unit test", BusinessKnowledge.okToRelyOnSpecTests());
// make okToRelyOnSpecTests return false if you find it to be... well, false
是否使用注释或代码可能是个人偏好的问题。或者是团队习惯/实践的问题。只是保持一致,不要混淆 - 遵循相同的经验法则“不要混淆未来的维护者”。
我们不希望这个家伙花费不眠之夜试图找出隐藏的原因为什么某些部分被注释覆盖而其他部分由代码提供我们呢? :)
答案 1 :(得分:1)
您的规格是否可执行?如果没有,您需要自动化测试(无论我们是在谈论单元测试还是验收测试)。
答案 2 :(得分:1)
你可以改为: “为规范完全涵盖的代码而非编写单元测试是否有意义?”
如果您不知道它应该如何工作,您可以为它编写测试吗?
是的,你可能可以,但是你会通过编写测试来增加规范。
这不是关于规范与测试的问题,而是测试确认代码按照规范运行。
即使规范似乎涵盖了所有内容,您也很可能在编写测试时发现仍然存在一些未涵盖的情况。从这个意义上讲,您不仅要测试代码,还要测试规范。
答案 3 :(得分:1)
单元测试的主要目标之一是发现 fast 的问题。如果您的集成测试和/或可执行规范需要花费很长时间(大多数情况下都会运行),我猜测您不会像单元测试那样经常运行它们。在这种情况下,创建单元测试可能是非常值得的,即使有更多“昂贵”的测试可以验证类似的行为。
答案 4 :(得分:0)
测试的主要功能之一 - 特别是但不是唯一的单元测试 - 是确定代码实际符合规范。如果您不进行测试,您如何确定生产的系统能够满足要求?测试永远不会浪费,只要它不是已经完成的,无效的,以前的测试的重复。也可以开发目标焦点 - 哦,我知道代码已经/将要测试 - 我不需要打扰。这是陈旧而且经常是愚蠢的管理层说话 - 假设是你和我的屁股。
修改强> 规范包含在单元测试中的附加信息;你的规格是可执行的;并且您有自动化集成测试;确实意味着在某些情况下,额外单元测试的编写将是多余的。根据您的示例,如果您的单位没有编写舍入规则,但只使用在其他地方定义的那些,那么我认为可以省略任何新的单元测试。在您编写业务规则的情况下,我倾向于引用包含来自您单元的相应规范的单元测试 - 作为“空”测试;或者更有用的是从单元测试中调用规范单元测试(如果可行)。