2

我正在使用 junit 和 eclipse 来编写功能测试。

运行单个测试时,它会按照我在班级中设置的顺序运行。

例如。

testCreateUser
testJoinUserToRoom
testVerify
testDeleteUser

但是,当我将此测试作为套件的一部分运行时(因此在包中),顺序是随机的。

例如,它将进行验证,然后删除用户,然后加入用户到房间,然后创建用户。

我在套件中的测试不相互依赖。但是,测试中的每个单独测试都取决于它们以正确的顺序运行。

有什么办法可以做到这一点?

谢谢。

4

2 回答 2

6

您不能保证JUnit中测试方法的执行顺序。

保证了套件测试的执行顺序(如果您使用的是Suite),但如果通过反射找到测试类,则执行顺序不是(例如,如果您在 Eclipse 中运行包,或者来自 maven 或 ant 的一组测试)。这可能由 ant 或 maven 定义,但不是由 JUnit 定义的。

通常,JUnit 按照它们在源文件中定义的顺序执行测试方法,但并非所有 JVM 都保证这一点(尤其是 JVM 7)。如果某些方法是从抽象基测试类继承的,那么这也可能不成立。(这听起来像你的情况,但我无法从你的描述中看出)。

有关这方面的更多信息,请参阅我对Has JUnit4 是否开始支持测试排序的回答?是故意的吗?.

那么你能做些什么来解决你的问题呢?有两种解决方案。

在您的原始示例中,您实际上只有一个测试(验证),但您有 4 个方法,两个设置(createUser、joinUserToRoom)和一个拆卸(deleteUser)。所以你的第一个选择是更好地定义你的测试用例,使用TestRule,特别是ExternalResourceExternalResource允许您为测试定义之前/之后的行为,类似于@Before/@After. 但是,优点ExternalResource是您可以将其排除在测试之外。

因此,您将在外部资源中创建/删除用户:

public class UsesExternalResource {
     @Rule
     public ExternalResource resource= new ExternalResource() {
         @Override
         protected void before() throws Throwable {
            // create user
         };

         @Override
         protected void after() {
            // destroy user
         };
     };

     @Test
     public void testJoinUserToRoom() {
        // join user to room
        // verify all ok
     }
}

对我来说,这更简单,更容易理解,并且您可以进行独立测试,这是一件好事。这就是我要做的,但你需要稍微重构你的测试。您还可以使用RuleChain堆叠这些规则。

如果您真的想在测试方法之间引入依赖关系,您的第二个选择是查看TestNG,您可以在其中定义从一个测试到另一个测试的依赖关系。

于 2011-12-15T12:18:16.700 回答
0

如果它们具有“正确”顺序,那么它们不是多个测试,而是您错误地注释为多个独立测试的单个测试。

最佳实践是以批准的 junit 样式(设置 - 执行 - 验证)重写它们,由执行任何所需的常见设置的 @Before 或 @BeforeClass 方法支持。

快速的解决方法是使用一个带有 @Test 注释的方法,该方法按顺序调用其他测试方法。如果您使用 Junit 不是为了进行严格的单元测试,而是更像是场景驱动的系统测试,那么这将成为首选替代方案。它不一定是此类使用的最佳工具,但在某些情况下确实可以很好地工作。

然后,到目前为止,您要做的是进行一次测试:

@Test public void testUserNominalLifeCycle(...

然后,如果你觉得自己有美德,可以通过额外的新测试来补充,比如

@Test public void testUserWhoNeverJoinsARoom(...
于 2011-12-15T10:18:49.767 回答