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

Java 在同一个测试用例或单独的测试用例中测试默认值和setter,java,testing,junit4,Java,Testing,Junit4,您是否建议在@testmethods中对测试用例进行分组,或者每个测试场景有一个@testmethod?例如,假设有不同的方法来设置应用程序中的上下文 以下想法可以接受吗 @Test public void testContextSetting() { // Test default setting assert(...) // Test setting a context variable assert(...) ... } 或者,你更愿意建议这样

您是否建议在@testmethods中对测试用例进行分组,或者每个测试场景有一个@testmethod?例如,假设有不同的方法来设置应用程序中的上下文

以下想法可以接受吗

@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(...)

    ...
}

任何反馈都将不胜感激。

最佳实践是每个方法有一个测试用例。方法名称描述您正在执行的测试。当您的测试失败时,如果只是一个断言,那么调试就更容易了。

划分et impera:)因此,在多个小案例中进行拆分…在出现错误时更容易修复。

我更喜欢每个方法有一个测试案例

首先,如果将案例拆分为方法,而不是查找代码中嵌入的注释,那么更容易看到正在测试哪些案例。大多数IDE都会为您提供方法摘要,因此,您只需查找名为
setupContextEdgeCaseXYZ()
的方法,而不是说“我测试了edgecase XYZ吗?”然后查找注释或查找设置该edgecase的代码

第二个原因是,如果您有多个案例,其中一个可能会失败,而其他案例则永远不会执行

 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);
}
通过分解案例,您可以避免上述错误,因为这些错误会变成编译错误或警告

您将测试与断言混淆。使用multiple
assert
s的测试方法可以测试多种情况:默认设置和设置上下文变量。但是测试一件事情的测试方法也可以有多个
assert
s

一个好的模式是每个测试用例有四个阶段:

  • 设置:在此处创建执行测试所需的对象,并在必要时更改这些对象以使其处于所需的初始状态
  • 练习:执行正在测试的操作的地方。这将是一个方法调用或构造函数调用
  • 验证:检查测试对象是否处于正确状态,并检查在练习阶段调用的方法返回的值(如果返回值)。这是放置
    断言的位置。如果使用此模式,则在验证阶段放置多个
    assert
    s没有任何错误
  • 拆卸:销毁或关闭用于执行测试的对象
  • 这是GerardMeszaros在《xUnit测试模式:重构测试代码》一书中推荐的方法

    将该模式与第一个示例中的模式进行对比,在第一个示例中,您似乎会这样做:

  • 初始设置
  • 练习构造器
  • 验证默认值
  • 设置上下文变量的练习
  • 验证上下文变量的设置
  • 拆卸

  • Eclipse根据每个方法生成单元测试,这似乎是一种合理的方法。 如果测试方法太复杂,不能用一种测试方法测试它,那么你可以考虑重构它。p> 但更好的方法是使用TDD并提前编写测试,这将推动其余的设计和实现

    就我个人而言,我更喜欢在Eclipse的Java代码覆盖范围内对每个方法进行一次测试


    该工具将告诉您实际测试的内容。

    这仍然是一本有用的读物:(请参阅多断言部分)另请参见+1,但我建议使用一个测试的情况:当您的测试夹具难以设置/成本高昂时。当然,如果它是一个可以在各种测试之间共享的夹具,则使用一个测试可以避免多次设置夹具。这种情况经常发生在使用内存数据库Spring之类的集成测试中,我认为“最佳实践是每个方法有一个测试用例”应该是“最佳实践是每个测试用例有一个断言”。