在Method级别(不是类级别)指定junit 4测试的顺序

时间:2010-06-21 23:18:27

标签: java unit-testing junit4 junit3

我知道这是不好的做法,但需要完成,或者我需要切换到testng。是否有类似于JUnit 3的testSuite的方法来指定要在类中运行的测试的顺序?

6 个答案:

答案 0 :(得分:62)

如果您确定真的想要这样做:可能有更好的方法,但这就是我能想到的......

JUnit4有一个注释:@RunWith,可以覆盖测试的默认Runner。

在您的情况下,您需要创建BlockJunit4ClassRunner的特殊子类,并覆盖computeTestMethods()以按照您希望它们执行的顺序返回测试。例如,假设我想以反向字母顺序执行我的测试:

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List computeTestMethods() {
        List list = super.computeTestMethods();
        List copy = new ArrayList(list);
        Collections.sort(copy, new Comparator() {
            public int compare(FrameworkMethod o1, FrameworkMethod o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        return copy;
    }
}
@RunWith(OrderedRunner.class)
public class OrderOfTest {
    @Test public void testA() { System.out.println("A"); }
    @Test public void testC() { System.out.println("C"); }
    @Test public void testB() { System.out.println("B"); }
}

运行此测试会产生:

C
B
A

对于您的特定情况,您需要一个比较器,它将按照您希望它们执行的顺序按名称对测试进行排序。 (我建议使用Google Guava的类Ordering.explicit("methodName1","methodName2").onResultOf(...);来定义比较器,其中onResultOf提供了一个将FrameworkMethod转换为其名称的函数......但显然你可以随心所欲地实现它。

答案 1 :(得分:62)

我可以看到这样做的几个原因,特别是在使用JUnit运行功能测试或测试持久对象时。例如,考虑一个持久存储到某种持久存储的对象Article。如果我想按照单元测试原则测试Article对象上的插入,更新和删除功能“所有测试应该是可重新排序的,并且只测试功能的特定部分”,我将进行三次测试:< / p>

  • testInsertArticle()
  • testUpdateArticle()
  • testDeleteArticle()

但是,为了能够测试更新功能,我首先需要插入文章。要测试删除功能,我还需要插入一篇文章。因此,在实践中,插入功能已在testUpdateArticle()testDeleteArticle()中进行了测试。然后很容易创建一个测试方法testArticleFunctionality()来完成所有工作,但是这样的方法最终会变得很大(并且他们不会只测试Article对象的部分功能)。

对于运行功能测试也是如此,例如对于一个宁静的API。如果不是因为不确定性的测试顺序,JUnit也适用于这些情况。

那就是说,我扩展了迈克尔D OrderedRunner使用注释来确定测试的顺序,我想我应该分享。它可以进一步扩展,例如通过准确指定每个测试所依赖的测试,但这就是我现在正在使用的。

这是如何使用的。它避免了对AA_testInsert()AB_testUpdate()AC_testDelete(),...,ZC_testFilter()等命名测试的需求。

@RunWith(OrderedRunner.class)
public class SomethingTest {
    @Test
    @Order(order=2)
    public void testUpdateArticle() {
        // test update
    }

    @Test
    @Order(order=1)
    public void testInsertArticle() {
        // test insert
    }

    @Test
    @Order(order=3)
    public void testDeleteArticle() {
        // test delete
    }
}

无论这些测试如何放在文件中,无论您是从Eclipse内部运行它们,它们始终都会以order=1开始,order=2秒和最后order=3运行,使用Ant或任何其他方式。

实施如下。首先,注释Order

@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
    public int order();
}

然后,修改后的OrderedRunner

public class OrderedRunner extends BlockJUnit4ClassRunner {
    public OrderedRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        Collections.sort(list, new Comparator<FrameworkMethod>() {
            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);

                if (o1 == null || o2 == null)
                    return -1;

                return o1.order() - o2.order();
            }
        });
        return list;
    }
}

答案 2 :(得分:26)

从JUnit版本4.11开始,可以通过使用@FixMethodOrder注释您的班级并指定任何可用的MethodSorters来影响测试执行的顺序。有关详细信息,请参阅this链接。

答案 3 :(得分:4)

使用junit 4.11 new annotation @FixMethodOrder可以设置特定订单:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)

答案 4 :(得分:1)

如果您想按顺序运行junit测试,“就像它们在您的源代码中一样”, 并且不想修改您的测试代码, 在这里看到我对此的说明:

How to run junit tests in order as they present in your source code

但这确实不是一个好主意,测试必须是独立的。

答案 5 :(得分:1)

我的github回购中的Joscarsson和Michael D代码。我希望他们不介意。我还为Parameterized类提供了有序版本。它已经被用作maven依赖

<repositories>
    <repository>
        <id>git-xxx</id>
        <url>https://github.com/crsici/OrderedRunnerJunit4.11/raw/master/</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.sici.org.junit</groupId>
    <artifactId>ordered-runner</artifactId>
    <version>0.0.1-RELEASE</version>
</dependency>