如何在JUnit4中以特定的顺序运行testing方法?
我想执行testing方法,由@Test
按照特定的顺序注释。
例如:
public class MyTest { @Test public void test1(){} @Test public void test2(){} }
我想确保每次运行MyTest
之前都在test2()
test1()
之前运行test1()
,但是我找不到像@Test(order=xx)
这样的注释。
我认为这对于JUnit来说非常重要,如果JUnit的作者不想要订单function ,为什么呢?
我认为这对于JUnit来说非常重要,如果JUnit的作者不想要订单function,为什么呢?
我不确定是否有一个干净的方式与JUnit做到这一点,据我所知,JUnit假定所有的testing可以以任意的顺序执行。 从常见问题解答:
我如何使用testing夹具?
(…) 不保证testing方法调用的顺序,因此可以在testEmptyCollection()之前执行testOneItemCollection()。 (……)
为什么这样? 那么,我相信依赖testing是一个作者不想推广的做法。 testing应该是独立的,它们不应该被耦合,违反这个会使事情变得更难维护,会打破单独(显然)运行testing的能力等等。
这就是说,如果你真的想要朝这个方向努力,那么考虑使用TestNG,因为它支持以任意顺序在本地运行testing方法(以及诸如指定方法依赖于方法组等)。 Cedric Beust解释了如何在testng中执行testing的顺序 。
Junit 4.11附带@FixMethodOrder
注释。 使用FixMethodOrder(MethodSorters.NAME_ASCENDING)
升级junit版本并注释testing类,而不是使用自定义解决scheme。 查看发行说明了解详细信息。
这是一个示例:
import org.junit.runners.MethodSorters; import org.junit.FixMethodOrder; import org.junit.Test; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class SampleTest { @Test public void firstTest() { System.out.println("first"); } @Test public void secondTest() { System.out.println("second"); } }
如果您摆脱了现有的Junit实例,并且在构buildpath中下载了JUnit 4.11或更高版本,则以下代码将按其名称顺序执行testing方法,并按升序排列:
@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"); } }
如果订单很重要,您应该亲自下订单。
@Test public void test1() { ... } @Test public void test2() { test1(); ... }
尤其是,如果需要,您应该列出一些或所有可能的排列顺序来testing。
例如,
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(); }
或者,对所有排列进行全面testing:
@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()
是一个简单的函数,它将所有可能的permuations迭代到数组的Collection中。
迁移到TestNG似乎是最好的方法,但是我看不到有关jUnit的明确解决scheme。 这里是我find的jUnit最可读的解决scheme/格式 :
@FixMethodOrder(MethodSorters.NAME_ASCENDING) 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之前被调用。
(尚未发布)更改https://github.com/junit-team/junit/pull/386引入了;@SortMethodsWith
。 https://github.com/junit-team/junit/pull/293至less使订单可以预测没有(在Java 7中它可以是相当随机的)。
看一下JUnit报告。 JUnit已经按照包来组织。 每个包都有(或可以有)TestSuite类,每个类又运行多个TestCases。 每个TestCase可以有多种forms的testing方法public void test*()
,每个testing方法实际上将成为它们所属的TestCase类的一个实例。 每个testing方法(TestCase实例)都有一个名称和一个合格/不合格的标准。
我的pipe理要求的是个别TestStep项目的概念,每个项目都报告自己的通过/失败标准。 任何testing步骤的失败都不能阻止后续testing步骤的执行。
过去,testing开发人员将TestCase类组织到与被testing产品部件相对应的包中,为每个testing创build一个TestCase类,并在testing中将每个testing方法作为一个单独的“步骤”在JUnit输出中完成自己的通过/失败标准。 每个TestCase都是一个独立的“testing”,但TestCase中的各个方法或testing“步骤”必须按照特定的顺序进行。
TestCase方法是TestCase的步骤,testingdevise人员在每个testing步骤中都有独立的通过/失败标准。 现在testing步骤混乱,testing(当然)失败。
例如:
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()
每个testing方法断言并报告自己单独的通过/失败标准。 为了sorting,将其折叠成“一个大的testing方法”会丢失JUnit总结报告中每个“步骤”的合格/不合格标准粒度。 这让我的经理感到不安。 他们目前正在要求另一种select。
任何人都可以解释一下,如何使用混杂的testing方法sorting的JUnit支持每个顺序testing步骤的单独的通过/失败标准,如上面所示和我的pipe理层所要求的那样?
不pipe文档如何,我都认为这是JUnit框架中的一个严重的倒退,正在使许多testing开发人员感到困难。
它是我在Junit工作时遇到的主要问题之一,我提出了以下解决scheme,对我来说工作正常:
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; } }
也创build一个如下图所示的界面:
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD}) public @interface Order { public int order(); }
现在假设你有类A,你已经写了如下的几个testing用例:
(@runWith=OrderRunner.class) Class A{ @Test @Order(order = 1) void method(){ //do something } }
所以执行将从名为“method()”的方法开始。 谢谢!
当testing用例作为套件运行时,你想要的是完全合理的。
不幸的是,现在没有时间给出一个完整的解决scheme,但看看上课:
org.junit.runners.Suite
它允许你以特定的顺序调用testing用例(从任何testing类)。
这些可能被用来创buildfunction,集成或系统testing。
这会让你的unit testing没有特定的顺序(如推荐的),不pipe你是否像这样运行它们,然后重新使用这些testing作为大图的一部分。
我们重用/inheritance相同的代码进行单元,集成和系统testing,有时候是数据驱动的,有时是提交驱动的,有时候会作为一个套件运行。
不知道我是否同意,如果我想testing“file upload”,然后testing“通过file upload插入的数据”,为什么我不希望这些相互独立? 完全合理的,我认为能够单独运行它们,而不是在Goliathtesting案例中。
在这里看到我的解决scheme:“Junit和Java 7”
在这篇文章中,我将介绍如何依次运行junittesting – “就像在源代码中一样”。 testing将运行,以便您的testing方法出现在类文件中。
http://intellijava.blogspot.com/2012/05/junit-and-java-7.html
但是正如帕斯卡尔·特威特所说,这不是一个好的做法。
我已经阅读了一些答案,并且认为它不是最好的做法,但是最简单的方法来定购你的testing – 而JUnit默认运行testing的方式是按字母顺序排列。
所以只要按照你想要的字母顺序来命名你的testing。 还要注意testing名称必须以单词testing开始。 只要注意数字
test12将在test2之前运行
所以:
testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond
请查看这个: https : //github.com/TransparentMarket/junit 。 它按照指定的顺序运行testing(在编译的类文件中定义)。 另外它还具有一个AllTests套件,可以首先运行由子包定义的testing。 使用AllTests实现,可以扩展解决scheme,也可以过滤属性(我们曾经使用@Fast注释,但还没有发布)。
这是JUnit的一个扩展,可以产生所需的行为: https : //github.com/aafuks/aaf-junit
我知道这是针对JUnit哲学的作者,但是当在非严格的unit testing环境(如Java中所使用的)中使用JUnit时,这会非常有帮助。
我最终以为我的testing没有按顺序运行,但事实是,这个混乱是在我的asynchronous工作。 在使用并发时,您还需要在testing之间执行并发检查。 就我而言,作业和testing共享一个信号量,所以下一个testing会挂起,直到正在运行的作业释放locking。
我知道这与这个问题并不完全相关,但也许可以帮助我们find正确的问题