我想以特定的顺序执行@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来说是非常重要的功能,如果JUnit的作者不想要订单功能,为什么?
我不确定是否有一种干净的方法可以用JUnit做到这一点,据我所知,JUnit假设所有测试都可以以任意顺序执行。常见问题解答:
如何使用测试夹具? (…)不能保证测试方法调用的顺序,因此testOneItemCollection()可能会在testEmptyCollection()之前执行。(…)
为什么会这样?好吧,我相信让测试依赖于顺序是作者不想提倡的做法。测试应该是独立的,它们不应该是耦合的,违反这一点会让事情更难维护,会破坏单独运行测试的能力(显然)等等。
话虽如此,如果您真的想朝着这个方向发展,可以考虑使用TestNG,因为它支持以任意顺序本机运行测试方法(以及诸如指定方法依赖于方法组之类的事情)。Cedric Beust解释了如何按照测试中执行测试的顺序来做这件事。
其他回答
看一看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从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 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源代码
对于JUnit 4,将这个注释放在测试类上解决了这个问题。
@FixMethodOrder(MethodSorters.JVM)
我认为这对JUnit来说是非常重要的功能,如果JUnit的作者不想要订单功能,为什么?
我不确定是否有一种干净的方法可以用JUnit做到这一点,据我所知,JUnit假设所有测试都可以以任意顺序执行。常见问题解答:
如何使用测试夹具? (…)不能保证测试方法调用的顺序,因此testOneItemCollection()可能会在testEmptyCollection()之前执行。(…)
为什么会这样?好吧,我相信让测试依赖于顺序是作者不想提倡的做法。测试应该是独立的,它们不应该是耦合的,违反这一点会让事情更难维护,会破坏单独运行测试的能力(显然)等等。
话虽如此,如果您真的想朝着这个方向发展,可以考虑使用TestNG,因为它支持以任意顺序本机运行测试方法(以及诸如指定方法依赖于方法组之类的事情)。Cedric Beust解释了如何按照测试中执行测试的顺序来做这件事。