是否存在单元测试无法发现的逻辑/流错误类型?

Is there a type of logic/flow errors that cannot be discovered by unit tests?

提问人:John V 提问时间:4/26/2018 最后编辑:John V 更新时间:5/3/2018 访问量:95

问:

假设我已经定义了合同并明确了要求(涵盖输入范围、边界值等),并且进行了单元测试以验证所有这些条件,那么当我将这些单元放在一起时,是否还会有集成错误?我现在不考虑外部服务。 我已经看到以下作为集成错误的示例,但我相信这只是单元级别的缺失测试:

class Engine
{
   int RPM;

   void SetRPMtoZero()
   {
      RPM=0;
   }
}

class Display
{
  CalculateAverage(Engine e)
  {
    if (e.IsRunning)
    {
      int X=smth/e.RPM;  //could be division by 0
    }
  }
}

class IntegratingClass
{
  Engine e
  Display d..

  ...

  e.SetRPMtoZero();
  d.CalculateAverage(e);

  //this sequence would lead to the division by zero

}

我不认为这显示了积分错误 - CalculateAverage 只是缺少对 RPM!=0 的检查。

是否真的存在单元测试无法发现的逻辑错误(或控制流)?

单元测试 与语言无关 的缺陷

评论

0赞 Tarun Lalwani 4/30/2018
单元测试是为测试其他代码而编写的代码。那么测试其他代码的代码会不会遗漏一些东西呢?嗯,它肯定可以。测试是关于将风险降至最低,而不是消除风险。这个问题及其答案很大程度上取决于正在测试的情况,并且没有通用的答案。

答:

-1赞 John Dee 4/30/2018 #1

有趣的问题。一方面,这很愚蠢。显然,一定有某种无法通过单元测试发现的逻辑,否则单元测试就是德尔菲的预言机。

我认为这里重要的哲学考虑是涌现复杂性的概念。许多思想家过去都指出了这一点。摩尔定律可能是最好的例子[晶体管的复杂度大约每2.5年翻一番]。但这是一个一般原则。

因此,将紧急复杂性定律抽象为软件测试:5 个软件单元单独是更多、相等还是更不复杂,还是一起更复杂?当你这样说时,很明显,5个单元一起工作一定比单独的单元更复杂。这被称为“超过其各部分的总和”,是系统的一般规则。

0赞 tangoal 5/3/2018 #2

我同意你的看法,这个例子是关于 Display 类的缺失单元测试。

但是,也许该示例的作者想指出单元之间的耦合可以更强 比预期或合同中描述的要好。此外,这个例子已经清楚地表明,在集成级别上 在单元测试级别上,事情可能与预期不同(也许不是故意的 SetRPMtoZero 方法在 CalculateAverage 方法之前调用。 通常你不会在单元测试级别上看到这一点,除非你有世界上最好的规范。

那么,在集成单元时,你可能会遇到什么(同时这也是单元测试无法告诉你的):

  • 即使在集成测试的第一阶段,集成本身(例如,如果我们谈论像 c++ 这样的语言,则将单元链接在一起), 如果接口在一个单元中更改,但在另一个单元中没有相应地调整,则可能会失败。
  • 如果单元使用公共资源(如文件、内存),则资源的保留/释放可能会导致阻止状态或数据损坏
  • 如果你用 100% 的单元测试覆盖源代码,这并不意味着所有代码都是真正必要的。关于集成 您可能会意识到,在将单元放在一起时,有很多代码甚至无法到达。这可以帮助您找出, 代码的哪些部分可能是“死代码”。
  • 性能限制或资源限制(如内存有限)
  • 对合同的误解或合同执行中的错误