为什么在单元测试中最好有独立的测试用例?
Why it is better to have independent test cases in unit testing?
在很多单元测试框架中,测试用例都是独立的。例如,GoogleTest 说:
Tests should be independent and repeatable. It’s a pain to debug a test that succeeds or fails as a result of other tests. googletest isolates the tests by running each of them on a different object.
我不明白为什么测试用例是独立的。例如,假设复合对象 A
使用对象 B
和 C
。很明显,如果 B
和 C
有问题,那么 A
所做的也将是不正确的,无论它是否正确实施。所以我不知何故喜欢看到这样的输出:
Testing B [SUCCEED]
Testing C [FAILED]
Testing A [FAILED] because dependent test C failed.
这些框架是否假设与其相互依赖,不如通过模拟 B
和 C
来测试 A
更好?因为有时为您的 类 编写正确的模拟程序可能很复杂(而且本身就有错误),所以我仍然认为依赖测试更好。
您正在考虑错误的(不)依赖类型。这里的依赖性意味着 testA2 依赖于在 testA1 中完成的某种形式的初始化或设置(这可能取决于 testB2 等完成的初始化)。这会使您的测试非常脆弱,因为乱序执行或失败的测试会级联整个测试用例集。这也使得无法 运行 孤立地测试用例。
例如,testA1 可以在测试数据库中创建记录,而 testA2 期望这些记录存在于测试数据库中。如果 testA1 失败(或者还没有 运行),那么 testA2 也会失败。
如果您有独立的测试用例(例如,创建记录作为 testA2 设置的一部分),则测试失败 运行(或 运行 正确),或出局执行测试的顺序,不会阻止您的其他测试成功完成。
当然,如果您的 class 被测(例如 A)和另一个 class(例如 C)之间的依赖关系从根本上被破坏了,那么您可能有多个测试用例失败,但这是一个不同于您引用的文本中的依赖性问题。
使用独立的测试用例,如果您不mock/stub(直接) class 正在测试中(例如 A))。
要明确的是,并不是每个人都喜欢这种类型的依赖,有些人会通过模拟、存根等方式努力使他们的单元测试独立于此类问题。不过,这是一种更固执己见的做法,因为它增加了复杂性,可能使您的测试更加脆弱,并且更容易遗漏那些 classes 之间的交互问题。
但是,正如我之前所说,这是一种不同于测试用例独立性的通常含义(特别是在您引用的文本中)的独立性。
在很多单元测试框架中,测试用例都是独立的。例如,GoogleTest 说:
Tests should be independent and repeatable. It’s a pain to debug a test that succeeds or fails as a result of other tests. googletest isolates the tests by running each of them on a different object.
我不明白为什么测试用例是独立的。例如,假设复合对象 A
使用对象 B
和 C
。很明显,如果 B
和 C
有问题,那么 A
所做的也将是不正确的,无论它是否正确实施。所以我不知何故喜欢看到这样的输出:
Testing B [SUCCEED]
Testing C [FAILED]
Testing A [FAILED] because dependent test C failed.
这些框架是否假设与其相互依赖,不如通过模拟 B
和 C
来测试 A
更好?因为有时为您的 类 编写正确的模拟程序可能很复杂(而且本身就有错误),所以我仍然认为依赖测试更好。
您正在考虑错误的(不)依赖类型。这里的依赖性意味着 testA2 依赖于在 testA1 中完成的某种形式的初始化或设置(这可能取决于 testB2 等完成的初始化)。这会使您的测试非常脆弱,因为乱序执行或失败的测试会级联整个测试用例集。这也使得无法 运行 孤立地测试用例。
例如,testA1 可以在测试数据库中创建记录,而 testA2 期望这些记录存在于测试数据库中。如果 testA1 失败(或者还没有 运行),那么 testA2 也会失败。
如果您有独立的测试用例(例如,创建记录作为 testA2 设置的一部分),则测试失败 运行(或 运行 正确),或出局执行测试的顺序,不会阻止您的其他测试成功完成。
当然,如果您的 class 被测(例如 A)和另一个 class(例如 C)之间的依赖关系从根本上被破坏了,那么您可能有多个测试用例失败,但这是一个不同于您引用的文本中的依赖性问题。
使用独立的测试用例,如果您不mock/stub(直接) class 正在测试中(例如 A))。
要明确的是,并不是每个人都喜欢这种类型的依赖,有些人会通过模拟、存根等方式努力使他们的单元测试独立于此类问题。不过,这是一种更固执己见的做法,因为它增加了复杂性,可能使您的测试更加脆弱,并且更容易遗漏那些 classes 之间的交互问题。
但是,正如我之前所说,这是一种不同于测试用例独立性的通常含义(特别是在您引用的文本中)的独立性。