我想以特定的顺序执行@Test注释的测试方法。

例如:

public class MyTest {
    @Test public void test1(){}
    @Test public void test2(){}
}

我想确保每次运行MyTest时都在test2()之前运行test1(),但我找不到@Test(order=xx)这样的注释。

我认为这对JUnit来说是非常重要的功能,如果JUnit的作者不想要订单功能,为什么?


当前回答

这是我在Junit工作时遇到的主要问题之一,我想出了以下解决方案,对我来说很好:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> list = super.computeTestMethods();
        List<FrameworkMethod> copy = new ArrayList<FrameworkMethod>(list);
        Collections.sort(copy, 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 copy;
    }
}

还可以创建如下界面:

 @Retention(RetentionPolicy.RUNTIME)


@Target({ ElementType.METHOD})

public @interface Order {
public int order();
}

现在假设你有一个类A,你写了几个测试用例,如下所示:

(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)

void method(){

//do something

}

}

因此,执行将从名为“method()”的方法开始。 谢谢!

其他回答

不确定我同意,如果我想测试“文件上传”,然后测试“文件上传插入的数据”,为什么我不希望这些是相互独立的?我认为能够分开运行它们是非常合理的,而不是在一个歌利亚测试案例中同时运行它们。

迁移到TestNG似乎是最好的方法,但是我没有看到jUnit的明确解决方案。以下是我为jUnit找到的最有可读性的解决方案/格式:

@FixMethodOrder( MethodSorters.NAME_ASCENDING ) // force name ordering
public class SampleTest {
    @Test
    void stage1_prepareAndTest(){};

    @Test
    void stage2_checkSomething(){};

    @Test
    void stage2_checkSomethingElse(){};

    @Test
    void stage3_thisDependsOnStage2(){};

    @Test
    void callTimeDoesntMatter(){}
}

这确保stage2方法在stage1方法之后和stage3方法之前被调用。

附注:我觉得这种方法比jUnit 5.5 @Order注释更好,因为它为读者提供了更好的标记。

对于JUnit 4,将这个注释放在测试类上解决了这个问题。

@FixMethodOrder(MethodSorters.JVM)

如果您摆脱了现有的Junit实例,并在构建路径中下载Junit 4.11或更高版本,以下代码将按照它们的名称(升序排序)执行测试方法:

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SampleTest {

    @Test
    public void testAcreate() {
        System.out.println("first");
    }
    @Test
    public void testBupdate() {
        System.out.println("second");
    }
    @Test
    public void testCdelete() {
        System.out.println("third");
    }
}

JUnit 4更新

从JUnit 4.13 @OrderWith开始,可以复制JUnit 5 @Order注释。这个解决方案与JUnit4的集成比@RunWith自定义BlockJUnit4ClassRunner实现更好。

下面是我如何用注释排序替换方法名排序(@FixMethodOrder(MethodSorters.NAME_ASCENDING))。

@OrderWith(OrderAnnotation.class)
public class MyTest {
    @Test
    @Order(-1)
    public void runBeforeNotAnnotatedTests() {}

    @Test
    public void notAnnotatedTestHasPriority0() {}

    @Test
    @Order(1)
    public void thisTestHasPriority1() {}

    @Test
    @Order(2)
    public void thisTestHasPriority2() {}
}
/**
 * JUnit 4 equivalent of JUnit 5's {@code org.junit.jupiter.api.Order}
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface Order {
    /**
     * Default order value for elements not explicitly annotated with {@code @Order}.
     *
     * @see Order#value
     */
    int DEFAULT = 0;

    /**
     * The order value for the annotated element.
     * <p>Elements are ordered based on priority where a lower value has greater
     * priority than a higher value. For example, {@link Integer#MAX_VALUE} has
     * the lowest priority.
     *
     * @see #DEFAULT
     */
    int value();
}
import org.junit.runner.Description;
import org.junit.runner.manipulation.Ordering;
import org.junit.runner.manipulation.Sorter;

/**
 * Order test methods by their {@link Order} annotation. The lower value has the highest priority.
 * The tests that are not annotated get the default value {@link Order#DEFAULT}.
 */
public class OrderAnnotation extends Sorter implements Ordering.Factory {
    public OrderAnnotation() {
        super(COMPARATOR);
    }

    @Override
    public Ordering create(Context context) {
        return this;
    }

    private static final Comparator<Description> COMPARATOR = Comparator.comparingInt(
            description -> Optional.ofNullable(description.getAnnotation(Order.class))
                                   .map(Order::value)
                                   .orElse(Order.DEFAULT));
}

未加注释的测试的默认优先级为0。具有相同优先级的测试顺序尚未确定。

要点:https://gist.github.com/jcarsique/df98e0bad9e88e8258c4ab34dad3c863

启发:

Aman Goel的回答是 由JUnit团队编写的测试执行顺序 JUnit 5源代码