我希望按特定顺序执行被标记为 @Test
的测试方法。
例如:
public class MyTest {
@Test public void test1(){}
@Test public void test2(){}
}
我希望每次运行MyTest
时,都能确保在运行test2()
之前先运行test1()
,但我找不到类似于@Test(order=xx)
的注解。
我认为这是JUnit的一个重要功能,如果JUnit的作者不想要有序功能,那么为什么呢?
我希望按特定顺序执行被标记为 @Test
的测试方法。
例如:
public class MyTest {
@Test public void test1(){}
@Test public void test2(){}
}
我希望每次运行MyTest
时,都能确保在运行test2()
之前先运行test1()
,但我找不到类似于@Test(order=xx)
的注解。
我认为这是JUnit的一个重要功能,如果JUnit的作者不想要有序功能,那么为什么呢?
JUnit 4 更新
从 JUnit 4.13 开始,可以使用 @OrderWith
注解来模拟 JUnit 5 的 @Order
注解。这个方案比使用自定义的 BlockJUnit4ClassRunner
实现与 JUnit 4 更好地集成。
下面是如何使用注解排序替代方法名排序(@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));
}
当测试用例作为一个套件运行时,您的要求是完全合理的。
不幸的是,现在没有时间提供一个完整的解决方案,但是请看一下类:
org.junit.runners.Suite
这允许您按特定顺序调用任何测试类中的测试用例。
这些可能用于创建功能、集成或系统测试。
这样,您的单元测试就可以按照推荐的方式保持无特定顺序(无论您是否以此方式运行它们),然后将测试作为更大画面的一部分进行重复使用。
我们在单元测试、集成测试和系统测试中重复/继承相同的代码,有时是数据驱动的,有时是提交驱动的,有时作为套件运行。
Ordering
。有关详细信息,请参见JUnit Wiki。以下是一个示例,使用内置的Alphanumeric
类按测试方法名称按字母数字顺序排列测试:import org.junit.Test;
import org.junit.runner.OrderWith;
import org.junit.runner.manipulation.Alphanumeric;
@OrderWith(Alphanumeric.class)
public class TestMethodOrder {
@Test
public void testA() {
System.out.println("first");
}
@Test
public void testB() {
System.out.println("second");
}
@Test
public void testC() {
System.out.println("third");
}
}
请查看我的解决方案: “Junit和Java 7。”
在本文中,我将描述如何按顺序运行junit测试-“就像在您的源代码中一样”。 测试将按照测试方法在类文件中出现的顺序运行。
http://intellijava.blogspot.com/2012/05/junit-and-java-7.html
但正如Pascal Thivent所说,这不是一个好的做法。
@FixMethodOrder(MethodSorters.JVM)
现在是时候转向Junit5了。以下是我们可能得到的示例:
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class OrderedTests {
@Test
@Order(1)
void nullValues() {}
@Test
@Order(2)
void emptyValues() {}
@Test
@Order(3)
void validValues() {}
}
对于Junit4,将您在多个测试中拥有的逻辑复制到一个测试方法中。
@FixMethodOrder(MethodSorters.JVM)
或 @FixMethodOrder(MethodSorters.DEFAULT)
或 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
在您的测试类前加上这些代码。@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BookTest {...}
@Test
@Order(2)
public void sendEmailTestGmail() throws MessagingException {
@TestMethodOrder(OrderAnnotation.class)
https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order
我在我的项目中使用了这个,它运行得非常好!这里有一个扩展程序可以实现所需的JUnit行为:https://github.com/aafuks/aaf-junit
我知道这与JUnit作者的理念相悖,但在使用JUnit进行非严格单元测试(如Java中的实践)时,这非常有帮助。
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
为类进行注释,并保留所有测试方法的@Test
注解,并根据期望的执行顺序按字母顺序重命名它们,例如t1_firstTest()
,t2_secondTest()
等。 - MisterStrickland