【问题标题】:Test default value and setter in same test-case or separate test cases在同一测试用例或单独的测试用例中测试默认值和设置器
【发布时间】:2011-09-09 06:42:42
【问题描述】:

您是否建议在 @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(...)

    ...
}

如有任何反馈,我们将不胜感激。

【问题讨论】:

标签: java testing junit4


【解决方案1】:

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

【讨论】:

  • 我认为“最佳实践是每个方法有一个测试用例”应该是“最佳实践是每个测试用例有一个断言”。
【解决方案2】:

Divide et impera :) 所以在多个小案例中拆分...在出现错误时更容易修复。

【讨论】:

    【解决方案3】:

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

    首先,如果将它们拆分为方法,而不是查找嵌入在代码中的 cmets,则更容易查看正在测试的案例。大多数 IDE 会给你一个方法的总结,所以不要说“我测试了边缘情况 XYZ 吗?”然后寻找评论,或寻找设置边缘情况的代码,您只需寻找名为 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);
    }
    

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

    【讨论】:

    • +1 但我建议最好只进行一次测试:当您的测试夹具难以设置/成本高昂时。
    • 当然,如果它是一个可以在各种测试之间共享的夹具。在这种情况下,单个测试可以避免您多次设置夹具。这通常发生在使用内存数据库、Spring 之类的集成测试中。
    【解决方案4】:

    您将 testassertion 混淆了。您的带有多个asserts 的测试方法会测试多个内容:默认设置设置上下文变量。但是一个测试一个东西的测试方法也可以有多个asserts。

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

    1. 设置:在其中创建执行测试所需的对象,并在必要时更改这些对象以将它们置于所需的初始状态。
    2. Exercise:您在其中执行您正在测试的操作。这将是一个方法调用或构造函数调用。
    3. 验证:您检查被测对象是否处于正确状态,并检查您在 exercise 阶段调用的方法返回的值,如果是返回一个值。这是您放置asserts 的地方。如果你使用这种模式,在 verify 阶段放置多个asserts 没有任何问题。
    4. 拆卸:销毁或关闭用于执行测试的对象。

    这是 Gerard Meszaros 在xUnit 测试模式:重构测试代码一书中推荐的方法。

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

    1. 初始设置
    2. 练习构造函数
    3. 验证默认值
    4. 练习设置上下文变量
    5. 验证上下文变量的设置
    6. 拆解

    【讨论】:

      【解决方案5】:

      Eclipse 为每个方法生成单元测试,这似乎是一种合理的方法。 如果测试的方法太复杂而无法使用一种测试方法进行测试,那么您可以考虑重构它。

      但更好的方法是使用 TDD 并预先编写测试,这将推动其余的设计和实现。

      就我个人而言,我更喜欢对每个方法进行一个测试以及 Eclipse http://www.eclemma.org 的 Java 代码覆盖率。

      该工具会告诉您您实际测试的是什么。

      【讨论】:

        猜你喜欢
        • 2023-03-27
        • 1970-01-01
        • 2013-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-27
        • 2013-04-09
        • 2021-10-20
        相关资源
        最近更新 更多