438

I want to execute test methods which are annotated by @Test in specific order.

For example:

public class MyTest {
    @Test public void test1(){}
    @Test public void test2(){}
}

I want to ensure to run test1() before test2() each time I run MyTest, but I couldn't find annotation like @Test(order=xx).

I think it's quite important feature for JUnit, if author of JUnit doesn't want the order feature, why?

Elrond_EGLDer
  • 47,430
  • 25
  • 189
  • 180
卢声远 Shengyuan Lu
  • 29,208
  • 21
  • 78
  • 123
  • 3
    They seem to me to be executed in the order they appear in the source file. – user207421 Sep 12 '10 at 03:46
  • 90
    You should never write tests that need to be executed in a specified order. That's really bad practice. Every test should be able to run independent. – Apfelsaft Jul 31 '12 at 09:57
  • 3
    I think the tests, when run individually are run in the order they appear in the file but if run as part of a suite they tend to be run in alphabetical order. I agree that tests should be independent but in my case I was testing that a cache is loaded once and then the same cache is called without loaded every other time after that until it is purged. I made sure they were in the order I wanted them to run in, in the file, and then I named them test1, test2 to ensure they ran in the suite correctly. It's not perfect but you could try it. – Alexei Blue Oct 01 '12 at 17:31
  • 6
    @EJP this was almost universally true of java pre 7. Pre 7, most JVMs did this, but it was never guaranteed. Java 7 JVMs can return the methods in a non-deterministic order. – Matthew Farwell Nov 25 '12 at 20:52
  • 2
    @Apfelsaft so what are test suits useful for? http://stackoverflow.com/questions/4649410/how-can-i-run-or-change-the-order-of-specific-test-methods-in-a-junit-test-cla – Mohammad Jafar Mashhadi Jun 29 '13 at 10:56
  • 19
    Work around. Remove @Test from you test cases, convert them as private functions, then crate a single test case, and call private functions in order. – Simon Guo Feb 04 '14 at 19:05
  • 16
    Removing @Test from the test cases will mess up the JUnit report. By the way, enforcing a specific order is a bad practice for **Unit tests** but not necessarily a bad practice for **Integration tests**. The best choice (not ideal) is to annotate the class with `@FixMethodOrder(MethodSorters.NAME_ASCENDING)`, keep the `@Test` annotation for all test methods and rename them alphabetically depending on the desired order of execution, e.g. `t1_firstTest()`, `t2_secondTest()`, etc. – MisterStrickland Mar 31 '16 at 17:14
  • 2
    @Apfelsaft - Please tell us why it is a bad idea to have tests execute in a specific order. – MasterJoe Jun 30 '17 at 18:35
  • 4
    It's very easy to pontificate about how unit tests need to be independent, but there are still very good reasons for running tests in a specific order. In my case, I run three separate tests for each of 7 possible values of an input parameter. And for each possible value, I want to compare those three tests, so it's much easier to do this if they're grouped together in the output. It also helps me recognize patterns in the test failures. So thanks go to the people who actually answered the question. – MiguelMunoz Jul 23 '18 at 17:53

21 Answers21

248

I think it's quite important feature for JUnit, if author of JUnit doesn't want the order feature, why?

I'm not sure there is a clean way to do this with JUnit, to my knowledge JUnit assumes that all tests can be performed in an arbitrary order. From the FAQ:

How do I use a test fixture?

(...) The ordering of test-method invocations is not guaranteed, so testOneItemCollection() might be executed before testEmptyCollection(). (...)

Why is it so? Well, I believe that making tests order dependent is a practice that the authors don't want to promote. Tests should be independent, they shouldn't be coupled and violating this will make things harder to maintain, will break the ability to run tests individually (obviously), etc.

That being said, if you really want to go in this direction, consider using TestNG since it supports running tests methods in any arbitrary order natively (and things like specifying that methods depends on groups of methods). Cedric Beust explains how to do this in order of execution of tests in testng.

Community
  • 1
  • 1
Pascal Thivent
  • 535,937
  • 127
  • 1,027
  • 1,106
  • 2
    I suspect that JUnit4 tests are in fact done in spec order. It is not guaranteed because that would (1) promote bad practices among testers and would (2) tie JUnit's hands somewhat. – emory Sep 12 '10 at 05:26
  • 15
    Either you have two independent tests, or you only have one test and should code as such. – Jon Freedman Sep 12 '10 at 09:23
  • 4
    @JonFreedman, as I understand the question, it's not a case of the tests being interdependent, just of having a spec of things to test and wanting the results to appear in that order. – Jon Bright Apr 28 '12 at 14:11
  • 186
    I can understand not enforcing order for unit tests, however when using JUnit to write integration tests it would be nice to be able to specify the order that tests are run. E.g. Run the login test first. – Brian DiCasa Jun 29 '12 at 13:43
  • 14
    @BrianD. login is probably a "fixture" instead of a test that must run before all the others. I will probably write a BeforeClass that logs in and then write the tests to execute in any order. – marcospereira Oct 22 '12 at 00:51
  • 2
    I would probably do login as a Rule so that one field in the class can simultaneously declare the test to login as well as logout. Although this raises a second related question, which is, what if another Rule wants to be logged in before it runs? Now you have some order dependency again. – Trejkaz Nov 14 '12 at 00:10
  • 52
    The implication "tests should be independent => tests should be ORDER independent" is not true. Consider automated grading of student's homeworks. I want to test their solution for smaller inputs first and for larger inputs later. When the solution is failing for smaller inputs (for time/memory limit), then why should the tests run for larger inputs? – mirelon Mar 10 '13 at 21:24
  • 2
    >>>>> TL;DR and Ressurrecting mode on! -> JUnit is wrong! If I want to run the unit test in a class and assume the first succeeds to test another one (let's say for inclusion and edition of a value) it will allow the last to fail if the failure is actually in the first. – Fagner Brack Mar 21 '13 at 12:45
  • 3
    Note, JUnit does not run them in the order they are defined in the class. I have seen them run in different order for at least JUnit 4.10. – studgeek Mar 27 '13 at 21:07
  • 2
    @Pascal Wouldn't a TestSuite solve this problem? We used them to test databases where the individual tests were independent it also made sense to combine some tests together into a larger scenario, such as (create table/insert data/delete data/drop table). This was before JUnit4, so my apologies if TestSuite has been deprecated or replaced with some newer feature. My question would be whether you would recommend TestSuites at all. – Kelly S. French May 03 '13 at 13:59
  • 3
    Junit 4.11 has the feature now - see other answer by Özhan Düz – Wolfgang Fahl Mar 18 '14 at 18:48
  • Junit是不能按照函数申明的顺序,进行顺序执行的,有违作者的设计本意。如果你非要这么做。那你可以使用TestNG – linjiejun Nov 04 '20 at 03:42
112

If you get rid of your existing instance of Junit, and download JUnit 4.11 or greater in the build path, the following code will execute the test methods in the order of their names, sorted in ascending order:

@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");
    }
}
Eric Leschinski
  • 123,728
  • 82
  • 382
  • 321
Aniket Kulkarni
  • 1,607
  • 2
  • 14
  • 20
  • 11
    We've actually tried a similar method test_001_login(), for example, but although it mostly works to preserve order, it is not guaranteed- we have several instances per test run where 004, 005, and 006 are run after 007. It makes you say, "WTF!," and run to StackOverflow for answers. – Max P Magee Oct 02 '14 at 16:11
  • 2
    in my tests: testAcase - worked, test_A_case / testA_case - did not! – Rodislav Moldovan Feb 27 '16 at 21:15
  • 7
    I have tried this annotation parameter "MethodSorters.JVM", e.g. "@FixMethodOrder(MethodSorters.JVM)". From the API: JVM - Leaves the test methods in the order returned by the JVM. Works just fine for my what I'm doing (CRUD), runs the test methods in the order they are written in. +1 – Edvinauskas May 05 '17 at 08:32
  • 2
    This annotation is indeed an answer, but it has the caveat that it is not defined (in Junit 4.12) with `@Inherited` and therefore becomes ineffective on my `AbstractTestCase` parent class. – AbVog Sep 03 '18 at 21:38
  • I have jUnit 4.12 and this hack does not work – Igor Kanshyn May 23 '21 at 15:05
53

If the order is important, you should make the order yourself.

@Test public void test1() { ... }
@Test public void test2() { test1(); ... }

In particular, you should list some or all possible order permutations to test, if necessary.

For example,

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(); }

Or, a full test of all permutations:

@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; 
            }
        }
    }
}

Here, permute() is a simple function which iterates all possible permuations into a Collection of array.

Xiè Jìléi
  • 12,317
  • 15
  • 72
  • 100
50

Migration to TestNG seems the best way, but I see no clear solution here for jUnit. Here is most readable solution / formatting I found for jUnit:

@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(){}
}

This ensures stage2 methods are called after stage1 ones and before stage3 ones.

joro
  • 1,425
  • 1
  • 18
  • 22
  • 6
    This approach is nice, but it would be valid to mention that if you have more than 10 tests it wont work fine unless you add a `0` prefix, e.g. `void stage01_prepareAndTest(){ }` – EliuX May 08 '18 at 04:07
19

Its one of the main issue which I faced when I worked on Junit and I came up with following solution which works fine for me:

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;
    }
}

also create a interface like below:

 @Retention(RetentionPolicy.RUNTIME)


@Target({ ElementType.METHOD})

public @interface Order {
public int order();
}

Now suppose you have class A where you have written several test cases like below:

(@runWith=OrderRunner.class)
Class A{
@Test
@Order(order = 1)

void method(){

//do something

}

}

So execution will start from method named "method()". Thanks!

ricosrealm
  • 1,526
  • 1
  • 15
  • 25
Aman Goel
  • 2,535
  • 1
  • 16
  • 17
19

JUnit since 5.5 allows @TestMethodOrder(OrderAnnotation.class) on class and @Order(1) on test-methods.

JUnit old versions allow test methods run ordering using class annotations:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FixMethodOrder(MethodSorters.JVM)
@FixMethodOrder(MethodSorters.DEFAULT)

By default test methods are run in alphabetical order. So, to set specific methods order you can name them like:

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

You can find examples here.

Zon
  • 12,838
  • 4
  • 69
  • 82
13

JUnit 5 update (and my opinion)

I think it's quite important feature for JUnit, if author of JUnit doesn't want the order feature, why?

By default, unit testing libraries don't try to execute tests in the order that occurs in the source file.
JUnit 5 as JUnit 4 work in that way. Why ? Because if the order matters it means that some tests are coupled between them and that is undesirable for unit tests.
So the @Nested feature introduced by JUnit 5 follows the same default approach.

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.

For example :

@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");
    }
}

Output :

createUserAndLogin

addItemsInBasket

checkoutOrder

By the way, specifying @TestMethodOrder(OrderAnnotation.class) looks like not needed (at least in the 5.4.0 version I tested).

Side note
About the question : is JUnit 5 the best choice to write integration tests ? I don't think that it should be the first tool to consider (Cucumber and co may often bring more specific value and features for integration tests) but in some integration test cases, the JUnit framework is enough. So that is a good news that the feature exists.

davidxxx
  • 104,693
  • 13
  • 159
  • 179
8

The (as yet unreleased) change https://github.com/junit-team/junit/pull/386 introduces a @SortMethodsWith. https://github.com/junit-team/junit/pull/293 at least made the order predictable without that (in Java 7 it can be quite random).

Anthony Dahanne
  • 4,410
  • 2
  • 37
  • 39
Jesse Glick
  • 22,072
  • 9
  • 77
  • 100
  • 2
    Seems that #386 has been merged in 4.11. – Jesse Glick Dec 18 '13 at 21:26
  • `@SortMethodsWith` has been renamed to `@FixMethodOrder` and [was released in 4.11](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.11.md#test-execution-order). – M. Justin Nov 09 '20 at 21:57
7

Look at a JUnit report. JUnit is already organized by package. Each package has (or can have) TestSuite classes, each of which in turn run multiple TestCases. Each TestCase can have multiple test methods of the form public void test*(), each of which will actually become an instance of the TestCase class to which they belong. Each test method (TestCase instance) has a name and a pass/fail criteria.

What my management requires is the concept of individual TestStep items, each of which reports their own pass/fail criteria. Failure of any test step must not prevent the execution of subsequent test steps.

In the past, test developers in my position organized TestCase classes into packages that correspond to the part(s) of the product under test, created a TestCase class for each test, and made each test method a separate "step" in the test, complete with its own pass/fail criteria in the JUnit output. Each TestCase is a standalone "test", but the individual methods, or test "steps" within the TestCase, must occur in a specific order.

The TestCase methods were the steps of the TestCase, and test designers got a separate pass/fail criterion per test step. Now the test steps are jumbled, and the tests (of course) fail.

For example:

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()

Each test method asserts and reports its own separate pass/fail criteria. Collapsing this into "one big test method" for the sake of ordering loses the pass/fail criteria granularity of each "step" in the JUnit summary report. ...and that upsets my managers. They are currently demanding another alternative.

Can anyone explain how a JUnit with scrambled test method ordering would support separate pass/fail criteria of each sequential test step, as exemplified above and required by my management?

Regardless of the documentation, I see this as a serious regression in the JUnit framework that is making life difficult for lots of test developers.

Stefan Hanke
  • 3,258
  • 2
  • 28
  • 32
5

Not sure I agree, If I want to test 'File Upload' and then test 'Data Inserted by File Upload' why would I not want these to be independent from each other? Perfectly reasonable I think to be able to run them separately rather than having both in a Goliath test case.

Mattk
  • 83
  • 1
  • 5
4

What you want is perfectly reasonable when test cases are being run as a suite.

Unfortunately no time to give a complete solution right now, but have a look at class:

org.junit.runners.Suite

Which allows you to call test cases (from any test class) in a specific order.

These might be used to create functional, integration or system tests.

This leaves your unit tests as they are without specific order (as recommended), whether you run them like that or not, and then re-use the tests as part of a bigger picture.

We re-use/inherit the same code for unit, integration and system tests, sometimes data driven, sometimes commit driven, and sometimes run as a suite.

CharlieS
  • 1,331
  • 1
  • 8
  • 10
3

See my solution here: "Junit and java 7."

In this article I describe how to run junit tests in order - "just as in your source code". Tests will be run, in order as your test methods appears in class file.

http://intellijava.blogspot.com/2012/05/junit-and-java-7.html

But as Pascal Thivent said, this is not a good practise.

kornero
  • 1,101
  • 8
  • 10
  • 1
    @NicolasBarbulesco I have two blogs (rus and eng). It is too complicated, because you sholdn't create tests with execution order dependency. My solution is workaround, but real solution - is to remove that dependency. – kornero May 22 '13 at 09:46
  • 1
    This post doesn't contain an actual answer. Please, consider adding at least the basic explanation, besides the link. – default locale Mar 13 '17 at 12:26
1

With JUnit 5.4, you can specify the order :

@Test
@Order(2)
public void sendEmailTestGmail() throws MessagingException {

you just need to annotate your class

@TestMethodOrder(OrderAnnotation.class)

https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-execution-order

i'm using this in my project and it works very well !

Walid
  • 112
  • 8
1

As others have stated, tests should be ideally be independent of execution order. This makes tests less fragile, and allows them to be run independently (many IDEs allow you to select a test method and execute it independently of other tests).

That being said, for integration tests, some people prefer to rely on method ordering.

Starting with JUnit 4.13 you can define your own class to reorder tests by extending Ordering. See the JUnit wiki for more details. Here's an example using the built-in Alphanumeric class to order the tests alphanumerically using the test method name:

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");
    }
}
NamshubWriter
  • 22,197
  • 2
  • 38
  • 54
0

I've read a few answers and agree its not best practice, but the easiest way to order your tests - and the way that JUnit runs tests by default is by alphabetic name ascending.

So just name your tests in the alphabetic order that you want. Also note the test name must begin with the word test. Just watch out for numbers

test12 will run before test2

so:

testA_MyFirstTest testC_ThirdTest testB_ATestThatRunsSecond

pstorli
  • 117
  • 1
  • 6
0

Please check out this one: https://github.com/TransparentMarket/junit. It runs the test in the order they are specified (defined within the compiled class file). Also it features a AllTests suite to run tests defined by sub package first. Using the AllTests implementation one can extend the solution in also filtering for properties (we used to use @Fast annotations but those were not published yet).

Martin Kersten
  • 4,953
  • 4
  • 36
  • 63
0

Here is an extension to JUnit that can produce the desired behavior: https://github.com/aafuks/aaf-junit

I know that this is against the authors of JUnit philosophy, but when using JUnit in environments that are not strict unit testing (as practiced in Java) this can be very helpful.

shlomi33
  • 1,352
  • 6
  • 8
0

I ended up here thinking that my tests weren't run in order, but the truth is that the mess was in my async jobs. When working with concurrency you need to perform concurrency checks between your tests as well. In my case, jobs and tests share a semaphore, so next tests hang until the running job releases the lock.

I know this is not fully related to this question, but maybe could help targeting the correct issue

McCoy
  • 548
  • 8
  • 17
0

You can use one of these piece of codes: @FixMethodOrder(MethodSorters.JVM) OR @FixMethodOrder(MethodSorters.DEFAULT) OR @FixMethodOrder(MethodSorters.NAME_ASCENDING)

Before your test class like this:

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class BookTest {...}
Gaspar
  • 1,177
  • 10
  • 19
0

If you want to run test methods in a specific order in JUnit 5, you can use the below code.

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MyClassTest { 

    @Test
    @Order(1)
    public void test1() {}

    @Test
    @Order(2)
    public void test2() {}

}
Oguzhan Cevik
  • 380
  • 3
  • 14
0

It's time to move to Junit5. Here is a sample of what we could get:

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
 class OrderedTests {

     @Test
     @Order(1)
     void nullValues() {}

     @Test
     @Order(2)
     void emptyValues() {}

     @Test
     @Order(3)
     void validValues() {}
 }

For Junit4, copy the logic that you have in several tests in one test method.

Igor Kanshyn
  • 407
  • 3
  • 7