【问题标题】:JUnit 4 test suite problemsJUnit 4 测试套件问题
【发布时间】:2011-03-02 14:36:58
【问题描述】:

我在使用测试套件运行的一些 JUnit 4 测试时遇到问题。

如果我单独运行测试,它们可以正常运行,但在大多数测试方法中运行时,90% 的测试方法会因错误而失败。我注意到的是,第一个测试总是很好,但其余的都失败了。另一件事是,一些测试方法没有按正确的顺序执行(反射没有按预期工作,或者因为方法的检索不一定按照创建的顺序)。如果有多个测试具有相同名称的方法,通常会发生这种情况。我尝试调试一些测试,似乎从一行到下一行,某些属性的值变成了null。

有谁知道问题出在哪里,或者行为是否“正常”?

提前致谢。

附: 好的,测试不相互依赖,它们都没有,它们都有@BeforeClass、@Before、@After、@AfterClass,所以在测试之间一切都被清除了。测试与数据库一起工作,但在 @BeforeClass 中的每个测试之前都会清除数据库,所以这应该不是问题。

简单示例:

测试套件:

import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
importy testclasses...;

@RunWith(Suite.class)
@Suite.SuiteClasses({ Test1.class, Test2.class })
public class TestSuiteX {
 @BeforeClass
 public static void setupSuite() { System.out.println("Tests started"); }   
 @AfterClass
 public static void setupSuite() { System.out.println("Tests started"); }   
}

测试: 测试是在 Glassfish 上运行的服务器应用程序上进行功能测试。

现在测试扩展了一个基类,该基类具有@BeforeClass - 清除数据库和登录名的方法以及仅进行注销的@AfterClass。 这不是问题的根源,因为在引入此类之前发生了同样的事情。

该类具有一些在其他测试中未使用的公共静态属性,并实现了 2 个控制方法。

其余的类,在本例中,这两个类扩展了基类,并且不覆盖继承的控制方法。

测试类示例:

    imports....

    public class Test1 extends AbstractTestClass {  
    protected static Log log = LogFactory.getLog( Test1.class.getName() );

    @Test
    public void test1_A() throws CustomException1, CustomException2 {

        System.out.println("text");

        creates some entities with the server api.
        deletes a couple of entities with the server api.

        //tests if the extities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

}

第二个:

public class Test1 extends AbstractTestClass {

    protected static Log log = LogFactory.getLog( Test1.class.getName() );

    private static String keyEntity;
    private static EntityDO entity;

    @Test
    public void test1_B() throws CustomException1, CustomException2 {

        System.out.println("text");

        creates some entities with the server api, adds one entities key to the static attribute and one entity DO to the static attribute for the use in the next method.
        deletes a couple of entities with the server api.

        //tests if the extities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

    @Test
    public void test2_B() throws CustomException1, CustomException2 {

        System.out.println("text");

        deletes the 2 entities, the one retrieved by the key and the one associated with the static DO attribute

        //tests if the deelted entities exists in the database
        Assert.assertNull( serverapi.isEntity(..) );

    }

这是一个基本示例,实际测试更复杂,但我尝试了简化测试,但仍然无法正常工作。 谢谢。

【问题讨论】:

  • 您能否发布一个测试示例并说明您是如何运行测试套件的。
  • 该测试套件是一个 JUnit 4 测试套件,它设置了所有测试类,并有一个 @BeforeClass 和一个 @AfterClass,它们仅 SOP 一些次要信息(基本字符串)。
  • 您发布的代码遗漏了最重要的细节:1)AbstractTestClass,2)@BeforeClass、@Before、@After、@AfterClass 方法,3)如何以及何时初始化 keyEntity 和实体, 4) 哪个测试失败了,究竟是怎么失败的?

标签: java junit4 test-suite


【解决方案1】:

您似乎在假设执行方法的顺序是固定的情况下构建了您的测试套件。这是错误的 - JUnit 不保证测试方法的执行顺序,所以你不应该指望它。

这是设计使然 - 单元测试应该完全相互独立。为了帮助保证这一点,JUnit 创建了一个独特的、新的测试类实例来执行每个测试方法。因此,您在一种方法中设置的任何属性都将在下一种方法中丢失。

如果你有通用的测试设置/拆卸代码,你应该把它放在单独的方法中,用@Before/@After注解。这些在每个测试方法之前和之后执行。

更新:你写的

在@BeforeClass 中的每个测试之前清除数据库

如果这不是一个错字,这可能是您的问题的根源。应该在 @Before 方法中清除 DB - @BeforeClass 每个类只运行一次。

【讨论】:

  • 好的,测试不依赖于彼此,但是它们的方法这样做,所以我不能将数据库清理代码放在@Before方法中,因为它会在每个方法之前清理数据库并且不会工作。如果您认为我将数据库清理代码放在套件的 @BeforeClass 中,那不是这样。谢谢。
  • @Hypnus,你上面所说的“测试”是一个测试类,对吧?显然我们在这里有一个术语不匹配。一个测试类可能包含许多测试方法。用单元测试的说法,每个方法代表一个单独的测试。这些测试——即测试方法——不应该相互依赖。
【解决方案2】:

您描述的情况听起来像是一个副作用问题。您提到测试在孤立的情况下可以正常工作,但取决于操作顺序:这通常是一个关键症状。

设置一整套测试用例的部分挑战是确保每个测试从干净状态开始,执行其测试,然后自行清理,将所有内容恢复到干净状态。

请记住,在某些情况下,标准清理例程(例如 @Before 和 @After)是不够的。我前段时间遇到的一个问题是在一组数据库测试中:作为测试的一部分,我正在向数据库中添加记录,并且需要专门删除我刚刚添加的记录。

因此,有时您需要添加特定的清理代码才能恢复到原始状态。

【讨论】:

    【解决方案3】:

    注意如何使用@BeforeClass 来一劳永逸地设置事物,以及如何使用@Before 在每次单独测试之前进行设置。并注意实例变量。

    如果您可以发布一个简化的问题示例,我们或许可以提供更具体的帮助。

    【讨论】:

    • 谢谢你,我会的,但在 2 小时内我有一些紧急工作要做。
    • 我为我的案例添加了一个简化示例。我尝试在包上直接使用 JUnit 运行测试,但仍然无法正常工作(然后某些方法在不同的位置失败)。谢谢。
    猜你喜欢
    • 2010-10-02
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-20
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多