我想以特定的顺序执行@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中,它可以是相当随机的)。
其他回答
JUnit从5.5开始允许在类上使用@TestMethodOrder(OrderAnnotation.class),在测试方法上使用@Order(1)。
JUnit旧版本允许测试方法使用类注释有序运行:
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)
默认情况下,测试方法按字母顺序运行。所以,为了设置特定的方法,你可以像这样命名它们:
a_TestWorkUnit_WithCertainState_ShouldDoSomething b_TestWorkUnit_WithCertainState_ShouldDoSomething c_TestWorkUnit_WithCertainState_ShouldDoSomething
Or
_1_TestWorkUnit_WithCertainState_ShouldDoSomething _2_TestWorkUnit_WithCertainState_ShouldDoSomething _3_TestWorkUnit_WithCertainState_ShouldDoSomething
你可以在这里找到例子。
这是我在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报告。JUnit已经按包组织。每个包都有(或可以有)TestSuite类,每个类依次运行多个testcase。每个TestCase可以有多个public void test*()形式的测试方法,每个测试方法实际上都将成为它们所属的TestCase类的实例。每个测试方法(TestCase实例)都有一个名称和一个通过/失败的标准。
我的管理需要的是单独的TestStep项的概念,每个项报告自己的通过/失败标准。任何测试步骤的失败都不能阻止后续测试步骤的执行。
在过去,在我的位置上,测试开发人员将TestCase类组织到与所测试产品的部分相对应的包中,为每个测试创建一个TestCase类,并使每个测试方法成为测试中的单独“步骤”,在JUnit输出中完成它自己的通过/失败标准。每个TestCase都是一个独立的“测试”,但是TestCase中的各个方法,或者测试“步骤”,必须以特定的顺序发生。
TestCase方法是TestCase的步骤,并且测试设计者得到了每个测试步骤单独的通过/失败标准。现在测试步骤变得混乱,测试(当然)失败了。
例如:
Class testStateChanges extends TestCase
public void testCreateObjectPlacesTheObjectInStateA()
public void testTransitionToStateBAndValidateStateB()
public void testTransitionToStateCAndValidateStateC()
public void testTryToDeleteObjectinStateCAndValidateObjectStillExists()
public void testTransitionToStateAAndValidateStateA()
public void testDeleteObjectInStateAAndObjectDoesNotExist()
public void cleanupIfAnythingWentWrong()
每个测试方法都断言并报告自己独立的通过/失败标准。 为了排序,将其分解为“一个大的测试方法”会丢失JUnit摘要报告. ...中每个“步骤”的通过/失败标准粒度这让我的经理们很不高兴。他们目前要求另一种选择。
谁能解释一下,一个具有打乱测试方法排序的JUnit如何支持每个连续测试步骤的单独通过/失败标准,就像上面的例子和我的管理层所要求的那样?
不管文档是什么,我认为这是JUnit框架中的严重倒退,使许多测试开发人员的生活变得困难。
如果您摆脱了现有的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");
}
}