简体   繁体   English

JUnit 4测试套件问题

[英]JUnit 4 test suite problems

I have a problem with some JUnit 4 tests that I run with a test suite. 我在测试套件中运行的某些JUnit 4测试存在问题。

If I run the tests individually they work with no problems but when run in a suite most of them, 90% of the test methods, fail with errors. 如果我单独运行测试,则它们可以正常工作,但是当以套件形式运行时,大多数测试方法(90%的测试方法)会因错误而失败。 What i noticed is that always the first tests works fine but the rest are failing. 我注意到的是,总是第一个测试可以正常工作,但其余的都失败了。 Another thing is that a few of the tests the methods are not executed in the right order (the reflection does not work as expected or it does because the retrieval of the methods is not necessarily in the created order). 另一件事是方法的一些测试未按正确的顺序执行(反射无法按预期方式工作,或者它不能按预期的方式进行,因为方法的检索不一定按创建的顺序进行)。 This usually happens if there is more than one test with methods that have the same name. 如果使用相同名称的方法进行了多个测试,通常会发生这种情况。 I tried to debug some of the tests and it seems that from a line to the next the value of some attributes becomes null . 我尝试调试一些测试,似乎从一行到下一行,某些属性的值变为null

Does anyone know what is the problem, or if the behavior is "normal"? 有谁知道是什么问题,或者行为是否“正常”?

Thanks in advance. 提前致谢。

PS: OK, the tests do not depend on each other, none of them do and they all have the @BeforeClass , @Before , @After , @AfterClass so between tests everything is cleared up. PS:OK,测试不依赖于对方,他们没有这样做,他们都有@BeforeClass@Before@After@AfterClass所以之间的测试一切都清理。 The tests work with a database but the database is cleared before each test in the @BeforeClass so this should not be the problem. 这些测试适用于数据库,但是在@BeforeClass每个测试之前都会清除数据库,因此这不是问题。

Simplefied example: 简化示例:

TEST SUITE: 测试套件:

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"); }   
}

TESTS: The tests are testing the functionalily on a server application running on Glassfish. 测试:这些测试正在运行于Glassfish上的服务器应用程序上进行功能测试。

Now the tests extend a base class that has the @BeforeClass - method that clears the database and login's and the @AfterClass that only makes a logoff. 现在,测试扩展了一个具有@BeforeClass-方法的基类,该方法清除数据库和登录名,而@AfterClass仅进行注销。 This is not the source of the problems because the same thing happened before introducing this class. 这不是问题的根源,因为在介绍此类之前,发生了相同的事情。

The class has some public static attributes that are not used in the other tests and implements the 2 controll methods. 该类具有一些其他测试未使用的公共静态属性,并实现了2种控制方法。

The rest of the classes, for this example the two extends the base class and does not owerride the inherited controll methods. 其余的类,在本例中,这两个类扩展了基类,并且不继承继承的controll方法。

Example of the test classes: 测试类示例:

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

    }

}

and the second : 第二个:

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

    }

This is a basic example, the actual tests are more complex but i tried with simplified tests and still it does not work. 这是一个基本示例,实际测试更为复杂,但是我尝试使用简化测试,但仍然无法正常工作。 Thank you. 谢谢。

The situation you describe sounds like a side-effecting problem. 您描述的情况听起来像是一个副作用。 You mention that tests work fine in isolation but are dependent on order of operations: that's usually a critical symptom. 您提到测试可以很好地隔离工作,但取决于操作顺序:这通常是一个严重的症状。

Part of the challenge of setting up a whole suite of test cases is the problem of ensuring that each test starts from a clean state, performs its testing and then cleans up after itself, putting everything back in the clean state. 设置整套测试用例的部分挑战是确保每个测试都从干净状态开始,执行其测试,然后自行清理,将所有内容恢复为干净状态的问题。

Keep in mind that there are situations where the standard cleanup routines (eg, @Before and @After ) aren't sufficient. 请记住,在某些情况下标准清理例程(例如, @Before@After )还不够。 One problem I had some time ago was in a set of databases tests: I was adding records to the database as a part of the test and needed to specifically remove the records that I'd just added. 我前一段时间遇到的一个问题是在一组数据库测试中:作为测试的一部分,我正在向数据库中添加记录,并且需要专门删除刚添加的记录。

So, there are times when you need to add specific cleanup code to get back to your original state. 因此,有时您需要添加特定的清理代码以恢复到原始状态。

It seems that you built your test suite on the assumption that the order of executing methods is fixed. 看来您是在假设执行方法的顺序是固定的前提下构建测试套件的。 This is wrong - JUnit does not guarantee the order of execution of test methods, so you should not count on it. 这是错误的-JUnit不保证测试方法的执行顺序,因此您不应依赖它。

This is by design - unit tests should be totally independent of each other. 这是设计使然-单元测试应该完全相互独立。 To help guaranteeing this, JUnit creates a distinct, new instance of your test class for executing each test method. 为了保证这一点,JUnit创建了一个独特的测试类新实例来执行每个测试方法。 So whatever attributes you set in one method, will be lost in the next one. 因此,在一种方法中设置的任何属性都将在下一种方法中丢失。

If you have common test setup / teardown code, you should put it into separate methods, annotated with @Before / @After . 如果您具有通用的测试设置/拆卸代码,则应将其放入单独的方法中,并用@Before / @After注释。 These are executed before and after each test method. 它们在每种测试方法之前和之后执行。

Update: you wrote 更新:您写了

the database is cleared before each test in the @BeforeClass 在@BeforeClass中的每个测试之前清除数据库

if this is not a typo, this can be the source of your problems. 如果这不是拼写错误,则可能是问题的根源。 The DB should be cleared in the @Before method - @BeforeClass is run only once for each class. 该数据库应在清除@Before方法- @BeforeClass只运行一次为每个类。

Be careful in how you use @BeforeClass to set up things once and for all, and @Before to set up things before each individual test. 在使用@BeforeClass @Before进行设置时,以及在每次单独测试之前使用@Before进行设置时,请务必谨慎。 And be careful about instance variables. 并注意实例变量。

We may be able to help more specifically, if you can post a simplified example of what is going wrong. 如果您可以发布发生问题的简化示例,我们也许可以提供更具体的帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM