我想以特定的顺序执行@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 5更新(以及我的观点)
我认为这对JUnit来说是非常重要的功能,如果JUnit的作者不想要订单功能,为什么?
默认情况下,单元测试库不会尝试按照源文件中出现的顺序执行测试。
JUnit 5和JUnit 4一样以这种方式工作。为什么?因为如果顺序很重要,这意味着一些测试在它们之间是耦合的,这对于单元测试来说是不可取的。 所以JUnit 5引入的@Nested特性遵循相同的默认方法。
But for integration tests, the order of the test method may matter since a test method may change the state of the application in a way expected by another test method. For example when you write an integration test for a e-shop checkout processing, the first test method to be executed is registering a client, the second is adding items in the basket and the last one is doing the checkout. If the test runner doesn't respect that order, the test scenario is flawed and will fail. So in JUnit 5 (from the 5.4 version) you have all the same the possibility to set the execution order by annotating the test class with @TestMethodOrder(OrderAnnotation.class) and by specifying the order with @Order(numericOrderValue) for the methods which the order matters.
例如:
@TestMethodOrder(OrderAnnotation.class)
class FooTest {
@Order(3)
@Test
void checkoutOrder() {
System.out.println("checkoutOrder");
}
@Order(2)
@Test
void addItemsInBasket() {
System.out.println("addItemsInBasket");
}
@Order(1)
@Test
void createUserAndLogin() {
System.out.println("createUserAndLogin");
}
}
输出:
创建用户和登录 添加物品在购物篮 结帐订单
顺便说一下,指定@TestMethodOrder(OrderAnnotation.class)看起来不需要(至少在我测试的5.4.0版本中是这样)。
边注 关于这个问题:JUnit 5是编写集成测试的最佳选择吗?我不认为它应该是首先考虑的工具(Cucumber和co可能经常为集成测试带来更具体的价值和特性),但在一些集成测试用例中,JUnit框架就足够了。所以这个功能的存在是个好消息。
我认为这对JUnit来说是非常重要的功能,如果JUnit的作者不想要订单功能,为什么?
我不确定是否有一种干净的方法可以用JUnit做到这一点,据我所知,JUnit假设所有测试都可以以任意顺序执行。常见问题解答:
如何使用测试夹具? (…)不能保证测试方法调用的顺序,因此testOneItemCollection()可能会在testEmptyCollection()之前执行。(…)
为什么会这样?好吧,我相信让测试依赖于顺序是作者不想提倡的做法。测试应该是独立的,它们不应该是耦合的,违反这一点会让事情更难维护,会破坏单独运行测试的能力(显然)等等。
话虽如此,如果您真的想朝着这个方向发展,可以考虑使用TestNG,因为它支持以任意顺序本机运行测试方法(以及诸如指定方法依赖于方法组之类的事情)。Cedric Beust解释了如何按照测试中执行测试的顺序来做这件事。
不确定我同意,如果我想测试“文件上传”,然后测试“文件上传插入的数据”,为什么我不希望这些是相互独立的?我认为能够分开运行它们是非常合理的,而不是在一个歌利亚测试案例中同时运行它们。
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源代码
如果订单很重要,你应该自己下订单。
@Test public void test1() { ... }
@Test public void test2() { test1(); ... }
特别是,如果有必要,您应该列出要测试的一些或所有可能的顺序排列。
例如,
void test1();
void test2();
void test3();
@Test
public void testOrder1() { test1(); test3(); }
@Test(expected = Exception.class)
public void testOrder2() { test2(); test3(); test1(); }
@Test(expected = NullPointerException.class)
public void testOrder3() { test3(); test1(); test2(); }
或者,所有排列的完整测试:
@Test
public void testAllOrders() {
for (Object[] sample: permute(1, 2, 3)) {
for (Object index: sample) {
switch (((Integer) index).intValue()) {
case 1: test1(); break;
case 2: test2(); break;
case 3: test3(); break;
}
}
}
}
这里,permute()是一个简单的函数,它将所有可能的排列迭代到数组的Collection中。