使用 TestSuite 时,我可以避免在 eclipse 中运行两次 junit 测试吗?

2022-09-03 02:44:56

我需要做一些每个套件的初始化(启动一个Web服务器)。它工作正常,除了当我在 eclipse 中运行项目中的所有测试时,我的测试运行两次。我的测试套件看起来有点像这样:

@RunWith(Suite.class)
@Suite.SuiteClasses({
   SubtestOne.class,
   SubtestTwo.class
})
public class TestSuite
{
   [...]
}

public class SubtestOne
{
   @Test public void testOne() { [...] }
}

public class SubtestTwo
{
   @Test public void testTwo() { [...] }
}

当我在 eclipse 中运行项目中的所有测试时,这会导致 junit 插件运行测试两次,如下所示:

  • 子测试一
  • 子测试二
  • 测试套件
    • 子测试一
    • 子测试二

是否可以使“在项目中运行所有测试”不运行子测试两次?我希望我的子测试仅作为套件的一部分运行。


答案 1

不,测试类将始终直接启动,然后通过套件中的“链接”启动。这是预期的。

一种解决方法可能是在运行配置中设置为仅从包含套件的包中运行测试。打开运行配置,然后选择,然后单击并选择包。Run all tests in the selected project, package or source folderSearch...


答案 2

我意识到这个问题在5年前就被问过了,但是由于很多人对这个问题投了赞成票,我认为我仍然会加入一个解决方案。如果您只想要解决方案,请直接跳到最后;阅读全文,如果你也想理解它;-)

首先,确实可以确保特定的 JUnit 测试类仅在测试套件中运行。此外,无论你是否想在Eclipse(如这里所问)或任何其他工具或环境中运行该测试套件也无关紧要;在大多数情况下,这确实是一个纯粹的JUnit问题。

在我勾勒出解决方案之前,重新审视这里的确切问题可能是一个好主意。所有 JUnit 测试都需要是可见且可实例化的,以便 JUnit 框架及其各个运行器进行选取。这也适用于测试套件和作为测试套件一部分的单个测试。因此,如果 JUnit 选取测试套件,它也将选取单个测试,并且套件中的所有测试将执行两次,一次单独执行,一次作为套件的一部分执行。

因此,如果您愿意,诀窍是防止JUnit拾取单个测试,同时仍然能够将它们作为套件的一部分进行实例化和执行。

想到的一件事是使测试类嵌套在测试套件中的静态内部类。但是,嵌套类仍然需要是公共的(否则它们也不能在套件中运行),如果它们是公共类,它们也会被单独拾取,尽管嵌套在套件的公共类中。但是,JUnit不会尝试运行不可见的测试类。因此,将测试类嵌套在非公共类中可能足以隐藏它们,但我们不能使套件类成为非公共类,因为这样JUnit就不会执行它。但是,我们可以做的是将各个测试嵌套在另一个嵌套在测试套件中的非公共类中,这使我们找到了这个难题的解决方案:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.Test1.class, AllTests.InSuiteOnly.Test2.class})
public class AllTests
{
    static class InSuiteOnly
    {
        public static class Test1
        {
            @Test
            public void test1()
            {
                //...
            }
        }

        public static class Test2
        {
            @Test
            public void test2()
            {
                //...
            }
        }
    }
}

很多人可能会反对现在需要放在单个源文件中的所有测试。如果我想维护单独的 JUnit 测试类,这些类不会自行执行,但仍会在测试套件内执行,该怎么办?一个简单的解决方案是使各个测试类抽象(公共/非公共无关紧要),以便JUnit不会执行它们,并且在测试套件中,我们只需使用原始抽象测试类的具体子类:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({AllTests.InSuiteOnly.SuiteTest1.class, AllTests.InSuiteOnly.SuiteTest2.class})
public class AllTests
{
    static class InSuiteOnly
    {
        public static class SuiteTest1 extends Test1 {}
        public static class SuiteTest2 extends Test2 {}
    }
}

abstract class Test1
{
    @Test
    public void test1()
    {
        //...
    }
}

abstract class Test2
{
    @Test
    public void test2()
    {
        //...
    }
}

此方案适用于 Maven、Eclipse 和所有其他直接利用 JUnit 运行器或实现自己的运行器(这些运行器严格遵循 JUnit 的原始行为和语义)的环境。


推荐