带有测试依赖的单元测试

36 投票
6 回答
19833 浏览
提问于 2025-04-16 04:52

当你有以下情况时,怎么进行单元测试呢?

  • 一些普通的单元测试
  • 一些更复杂的测试,用来检查边缘情况,这些测试依赖于普通的测试

举个例子,想象一下在测试一个CSV读取器(我随便编的一个例子),

def test_readCsv(): ...

@dependsOn(test_readCsv)
def test_readCsv_duplicateColumnName(): ...

@dependsOn(test_readCsv)
def test_readCsv_unicodeColumnName(): ...

我希望子测试只有在它的父测试成功时才会运行。这样做的原因是,运行这些测试需要时间。如果很多失败的报告都指向同一个原因,那也没什么意义。当然,我可以把所有的边缘情况都塞进主测试里,但我在想有没有更有条理的方法来处理这个。

我找到了一些相关但不同的问题,

更新:

我发现了 TestNG,它对测试依赖关系有很好的内置支持。你可以这样写测试,

@Test{dependsOnMethods = ("test_readCsv"))
public void test_readCsv_duplicateColumnName() {
   ...
}

6 个回答

2

我不太确定你指的是哪种语言(因为你在问题中没有具体提到),但像 PHPUnit 这样的工具有一个叫做 @depends 的标签,它只有在依赖的测试已经通过的情况下才会运行。

根据你使用的语言或单元测试工具,可能也会有类似的功能。

5

Proboscis 是一个用 Python 写的库,类似于 Java 里的 TestNG

你可以在这里查看它的详细信息:packages.python.org/proboscis/

它支持依赖关系,比如:

@test(depends_on=[test_readCsv])
public void test_readCsv_duplicateColumnName() {
   ...
}
15

我个人觉得,不用太担心单元测试之间的依赖关系。这听起来有点像代码的坏味道。这里有几点想法:

  • 如果一个测试失败了,那其他的测试也应该一起失败,这样你才能更好地了解问题的严重程度,看看代码改动带来了多大的影响。
  • 测试失败应该是例外,而不是常态。所以没必要浪费时间去创建依赖关系,因为大多数情况下(希望如此!)这样做并没有什么好处。如果测试经常失败,问题不在于单元测试的依赖,而在于测试本身经常出错。
  • 单元测试应该运行得非常快。如果测试运行得很慢,那就应该把精力放在提高测试速度上,而不是去防止后续的失败。可以通过让代码之间的关系更松散,使用依赖注入或模拟来实现这一点。

撰写回答