是否存在单元测试无法发现的 logic/flow 错误类型?
Is there a type of logic/flow errors that cannot be discovered by unit tests?
假设我定义了合同并明确了要求(包括输入范围、边界值等),并且单元测试验证了所有这些条件,那么当我将这些单元放在一起时是否还会出现集成错误?我现在不考虑外部服务。
我已经看到以下作为集成错误的示例,但我相信这只是单元级别的缺失测试:
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。
是否真的存在单元测试无法发现的逻辑错误(或控制流)?
有趣的问题。一方面是愚蠢的。显然肯定有某种逻辑无法通过单元测试发现,否则单元测试就是 Delphi.
的 Oracle
我认为这里重要的哲学考虑是涌现复杂性的概念。许多思想家过去已经指出了这一点。摩尔定律可能是最好的例子 [晶体管的复杂性大约每 2.5 年翻一番]。不过是一般校长。
因此,将涌现复杂性法则抽象为软件测试:5 个软件单元分别更复杂、相等或更不复杂,还是一起更复杂?当你这样说时,很明显 5 个单元一起工作肯定比单独的单元更复杂。这称为 "More than the sum of it's parts",是系统的一般规则。
我同意你的看法,这个例子是关于缺少 class 显示单元测试的。
但是,也许那个例子的作者想指出单元之间的耦合可以更强
比预期或合同中描述的要多。此外,这个例子已经清楚地表明在集成级别
在单元测试级别上,事情可能与预期不同(也许这并不是故意的
SetRPMtoZero 方法在 CalculateAverage 方法之前调用)。
通常你不会在单元测试级别看到这一点,除非你有世界上最好的规范。
所以,你在集成单元时可能还会遇到什么(同时这也是单元测试无法告诉你的):
- 即使在集成测试的第一阶段,集成本身(f.e。将单元连接在一起,如果我们谈论像 c++ 这样的语言),
可能会失败,如果接口在一个单元中更改,但在其他单元中没有相应调整。
- 如果单位使用公共资源(如文件、内存),则 reservation/release 资源可能会导致阻塞状态或数据损坏
- 如果您用 100% 的单元测试覆盖一个单元的源代码,这并不意味着所有代码都是真正必要的。关于整合
级别你可能会意识到有很多代码,当把这些单元放在一起时,甚至无法达到。这可以帮助您了解,
您的代码的哪些部分可能是 "dead code".
- 性能限制或资源限制(如有限内存)
- 对合同的误解或执行中的错误
假设我定义了合同并明确了要求(包括输入范围、边界值等),并且单元测试验证了所有这些条件,那么当我将这些单元放在一起时是否还会出现集成错误?我现在不考虑外部服务。 我已经看到以下作为集成错误的示例,但我相信这只是单元级别的缺失测试:
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。
是否真的存在单元测试无法发现的逻辑错误(或控制流)?
有趣的问题。一方面是愚蠢的。显然肯定有某种逻辑无法通过单元测试发现,否则单元测试就是 Delphi.
的 Oracle我认为这里重要的哲学考虑是涌现复杂性的概念。许多思想家过去已经指出了这一点。摩尔定律可能是最好的例子 [晶体管的复杂性大约每 2.5 年翻一番]。不过是一般校长。
因此,将涌现复杂性法则抽象为软件测试:5 个软件单元分别更复杂、相等或更不复杂,还是一起更复杂?当你这样说时,很明显 5 个单元一起工作肯定比单独的单元更复杂。这称为 "More than the sum of it's parts",是系统的一般规则。
我同意你的看法,这个例子是关于缺少 class 显示单元测试的。
但是,也许那个例子的作者想指出单元之间的耦合可以更强 比预期或合同中描述的要多。此外,这个例子已经清楚地表明在集成级别 在单元测试级别上,事情可能与预期不同(也许这并不是故意的 SetRPMtoZero 方法在 CalculateAverage 方法之前调用)。 通常你不会在单元测试级别看到这一点,除非你有世界上最好的规范。
所以,你在集成单元时可能还会遇到什么(同时这也是单元测试无法告诉你的):
- 即使在集成测试的第一阶段,集成本身(f.e。将单元连接在一起,如果我们谈论像 c++ 这样的语言), 可能会失败,如果接口在一个单元中更改,但在其他单元中没有相应调整。
- 如果单位使用公共资源(如文件、内存),则 reservation/release 资源可能会导致阻塞状态或数据损坏
- 如果您用 100% 的单元测试覆盖一个单元的源代码,这并不意味着所有代码都是真正必要的。关于整合 级别你可能会意识到有很多代码,当把这些单元放在一起时,甚至无法达到。这可以帮助您了解, 您的代码的哪些部分可能是 "dead code".
- 性能限制或资源限制(如有限内存)
- 对合同的误解或执行中的错误