Pavel Ryzhov
Pavel Ryzhov

Reputation: 5142

Are there any conventions of extending JUnit4 test classes?

I have a lot of common logic for my test, so I decide to share it by extending. I've wrote two classes: TestNumberOne which extends TestBase.

TestBase.java

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;

/**
 * @author Pavel
 * @since 2013-03-03
 */
public class TestBase {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClass() in TestBase");
        System.out.flush();
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("afterClass() in TestBase");
        System.out.flush();
    }

    @Before
    public void before() {
        System.out.println("before() in TestBase");
        System.out.flush();
    }

    @After
    public void after() {
        System.out.println("after() in TestBase");
        System.out.flush();
    }
}

TestNumberOne.java

import org.junit.*;

/**
 * @author Pavel
 * @since 2013-03-03
 */
public class TestNumberOne extends TestBase {

    @Test
    public void anyTest() {
        System.out.println("anyTest() in TestNumberOne");
        System.out.flush();
    }
}

I've got such a strange output when I execute my tests:

before() in TestBase
anyTest() in TestNumberOne
after() in TestBase
beforeClass() in TestBase
afterClass() in TestBase

Why does it has so strange order? And are there any conventions of extending JUnit test classes?

UPDATE:

  1. Tests are run in IDEA
  2. To get such a strange results I've run them several times (other results was as expected)

Upvotes: 2

Views: 1524

Answers (4)

František Hartman
František Hartman

Reputation: 15076

This is definitely an IntelliJ IDEA issue.

If I run your code by maven, it runs ok; if I run it in IntelliJ several times, then I sometimes get the incorrect output as you do.

Actually, I found a way to reproduce it:

  • Add Thread.sleep(1000) after each output message.
  • Turn off "Track running test" in Run test window (blue circle above list of run tests)
  • Run whole TestNumberOne test class in IntelliJ (even though you have only one test method) -> output should be in correct order
  • click on the anyTest method in the test list and then at the TestNumberOne -> output is in incorrect order

(also if you run it with sleep, you see that the output is in correct order but gets reordered when the test ends)

So they are run in correct order, only the output is messed up.

Upvotes: 2

Stéphane Piette
Stéphane Piette

Reputation: 5421

When I try your code, I just get the expected output, ie

beforeClass() in TestBase
before() in TestBase
anyTest() in TestNumberOne
after() in TestBase
afterClass() in TestBase

(launched with Eclipse). Which is the convention ^^ Your result is really strange indeed ...

Upvotes: 1

Will
Will

Reputation: 6286

I think when you run the tests, your TestBase is also being run as it's own junit test. Try calling it HelperBase instead.

Upvotes: 0

Ray Tayek
Ray Tayek

Reputation: 10003

don't know of any conventions. in junit 3, the base class was usually abstract.

the following seems to come out in a sane order (except perhaps for the teardowns).

import org.junit.*;
public class BaseTestCase {
    public static String method() {
        return Thread.currentThread().getStackTrace()[2].getMethodName() + "()";
    }
    @BeforeClass public static void classSetupBaseClass() {
        System.out.println(method());
    }
    @AfterClass public static void classTeardownBaseClass() {
        System.out.println(method());
    }
    @Before public void setupBaseClass() {
        System.out.println(method());
    }
    @After public void teardownBaseClass() {
        System.out.println(method());
    }
    @Test public void aTestInBaseClass() {
        System.out.println(method());
    }
}


import static org.junit.Assert.*;
import org.junit.*;

public class  So15183669 extends BaseTestCase {
    @BeforeClass public static void classSetup() {
        System.out.println(method());
    }
    @AfterClass public static void classTeardown() {
        System.out.println(method());
    }
    @Before public void setup() {
        System.out.println(method());
    }
    @After public void teardown() {
        System.out.println(method());
    }
    @Test public void aTest() {
        System.out.println(method());
    }
}


classSetupBaseClass()
classSetup()
setupBaseClass()
setup()
aTest()
teardown()
teardownBaseClass()
setupBaseClass()
setup()
aTestInBaseClass()
teardown()
teardownBaseClass()
classTeardown()
classTeardownBaseClass()

Upvotes: 0

Related Questions