【问题标题】:Why it is better to have independent test cases in unit testing?为什么在单元测试中有独立的测试用例更好?
【发布时间】:2022-01-21 08:43:58
【问题描述】:

在很多单元测试框架中,测试用例是独立的。例如,GoogleTest 说:

测试应该是独立的可重复的。调试由于其他测试而成功或失败的测试是一件痛苦的事。 googletest 通过在不同的对象上运行每个测试来隔离测试。

我不明白为什么测试用例独立是好的。例如,假设一个复合对象A 使用对象BC。很明显,如果BC 有问题,那么A 所做的也将是不正确的,无论它是否正确实现。所以我有点想看到这样的输出:

Testing B [SUCCEED]
Testing C [FAILED]
Testing A [FAILED] because dependent test C failed. 

这些框架是否假设与其相互依赖,不如通过模拟BC 来测试A?因为有时为你的类编写正确的 mocker 可能很复杂(而且本身也有问题),所以我仍然认为依赖测试更好。

【问题讨论】:

    标签: unit-testing testing


    【解决方案1】:

    您正在考虑错误的(独立)独立类型。这里的依赖是 testA2 依赖于 testA1 中完成的某种形式的初始化或设置(这可能取决于 testB2 完成的初始化等)。这使您的测试非常脆弱,因为乱序执行或失败的测试将级联到您的整个测试用例集。这也使得无法单独运行测试用例。

    例如,testA1 可以在测试数据库中创建记录,而 testA2 期望这些记录出现在测试数据库中。如果 testA1 失败(或尚未运行),那么 testA2 也会失败。

    如果您有独立的测试用例(例如,创建记录作为 testA2 设置的一部分),那么测试运行(或正确运行)失败或测试执行乱序不会阻止您其他测试成功完成。

    当然,如果您的被测类(例如 A)和另一个类(例如 C)之间的依赖关系从根本上被破坏了,那么您可能有多个测试用例失败,但这是一个不同于预期的依赖问题在您引用的文本中。

    使用独立的测试用例,如果您不模拟/存根被测(直接)类的依赖项(例如 C),您仍然可以获得您想要的测试结果(如果 C 损坏,则测试 A 失败) (例如 A))。

    需要明确的是,并不是每个人都喜欢这种类型的依赖,有些人会努力通过模拟、存根等方式使他们的单元测试独立于这种类型的问题。不过,这是一种更加自以为是的做法,因为它越来越多复杂性,可能会使您的测试更脆弱,并且更容易错过这些类之间的交互问题。

    但是,正如我之前所说,这是一种与测试用例独立性(特别是在您引用的文本中)通常意味着的不同类型的独立性。

    【讨论】:

    • 我同意你提到的依赖类型(测试 A 为测试 B 设置了一些东西)是一场灾难。但是让我们假设A 类使用B 类的单一方法,该方法假设增加价值,但像int inc(int a) {return --a;} 一样实现。很明显,B 的这种实现,A 无论是否正确实现都会运行不正确,因为B 不正确。因为A 的行为实际上取决于 B。奇怪的是,我们在编写测试时应该以某种方式忽略这种依赖关系,或者至少这是我从测试独立性中理解的。
    • 从我从这些框架中得到的信息来看,我们不应该有任何将这些依赖关系考虑在内的测试。
    • @Afshin 是的,你是对的,但这不是引用文本所涉及的依赖类型。您是否应该(或不应该)通过模拟它们的依赖关系来隔离被测类是一个完全不同的话题,这是一种高度自以为是的做法(比测试本身之间的独立性更自以为是)。
    • 也许引用的文本不适合我的问题,但我的问题实际上是关于我提到的依赖关系。我从我的帖子中删除了那句话。
    • @Afshin 您已经收到了基于您最初提出的问题的答案。如果您对被测类的(不)独立性(而不是测试本身的独立性)有疑问,我建议您提出一个新问题。如果你改变问题问别的问题,我会回滚。
    猜你喜欢
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    相关资源
    最近更新 更多