我想以特定的顺序执行@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的作者不想要订单功能,为什么?
当前回答
(尚未发布的)更改https://github.com/junit-team/junit/pull/386引入了@SortMethodsWith。https://github.com/junit-team/junit/pull/293至少使顺序可以预测(在Java 7中,它可以是相当随机的)。
其他回答
正如其他人所说,理想情况下,测试应该独立于执行顺序。这使得测试不那么脆弱,并允许它们独立运行(许多ide允许您选择一个测试方法并独立于其他测试执行它)。
话虽如此,对于集成测试,有些人更喜欢依赖于方法排序。
从JUnit 4.13开始,您可以通过扩展ordered定义自己的类来重新排序测试。请参阅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");
}
}
(尚未发布的)更改https://github.com/junit-team/junit/pull/386引入了@SortMethodsWith。https://github.com/junit-team/junit/pull/293至少使顺序可以预测(在Java 7中,它可以是相当随机的)。
对于JUnit 4,将这个注释放在测试类上解决了这个问题。
@FixMethodOrder(MethodSorters.JVM)
如果订单很重要,你应该自己下订单。
@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中。
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框架就足够了。所以这个功能的存在是个好消息。