在同一测试用例或单独的测试用例中测试默认值和 setter

2022-09-01 03:11:56

您是建议在@Test方法中对测试用例进行任何分组,还是建议为每个测试方案使用一个@Test方法?例如,假设有不同的方法可以在应用程序中设置上下文。

以下想法可以接受吗?

@Test
public void testContextSetting() {
    // Test default setting
    assert(...)

    // Test setting a context variable
    assert(...)

    ...
}

或者,你宁愿建议像这样,让每种方法尽可能原子化:

@Test
public void textDefaultSetting() {
    // Test default setting
    assert(...)
}

@Test
public void testSettingContextVar() {
    // Test setting a context variable
    assert(...)

    ...
}

任何反馈将不胜感激。


答案 1

我更喜欢每种方法都有一个测试用例。

首先,如果将哪些案例拆分为多个方法,则更容易看到正在测试的案例,而不是查找嵌入在代码中的注释。大多数 IDE 会给你一个方法摘要,所以你只需查找名为 的方法,而不是说“我是否测试了 edgecase XYZ?”然后寻找注释,或者查找设置该 edgecase 的代码。setupContextEdgeCaseXYZ()

第二个原因是,如果有多个案例在一起,其中一个可能会失败,然后其他案例永远不会执行。

 testDefaultCase()
 testInvalidInput()
 testEdgeCase1()
 testEdgeCase2()

使用此结构,可以更轻松地确定输入检查是否错误,并且边缘情况 2 处理不当,但其他情况正常(您可能会发现两个失败的情况相关,并且问题诊断得更快)。

第三个原因是,您可能会意外地离开前一个测试集中的值,从而以不显眼的方式使后一个测试无效。一个简单的例子:

@Test
public void testMyMethod() {
  //test default
  String test = Foo.bar(null);
  assertEquals("foo", test);

  //test case 1
  Foo.bar(aValue);
  //Oops forgot to set value above, this passes regardless of 
  //what the above call does
  assertEquals("foo", test);
}

通过将案例分解,您可以避免上述错误,因为这会变成编译错误或警告。


答案 2

最佳做法是每种方法有一个测试用例。方法名称描述您正在执行的测试。当测试失败时,如果它只是一个断言,则更容易调试。