0

In unit custom runner I want to perform action before and after running the test action, so I came around with this solution.

how solid is doing it that way, is there a more clean way to achieve that?

public class SomeCustomRunner extends BlockJUnit4ClassRunner {
    private int  m_testMethodIndex  = 0;
    private int  m_testMethodsCount = 0;
    private boolean m_sessionSetup = false;

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        if(m_sessionSetup == false) {
            m_sessionSetup = true;
            beforeTestClass(); //->> DO MY STUFF HERE
        }

        super.runChild(method, notifier);

        m_testMethodIndex++;

        if(m_testMethodIndex == m_testMethodsCount) {
            afterTestClass(); //->> DO MY STUFF HERE
        }
    }

    @Override
    protected List<FrameworkMethod> getChildren() {
        List<FrameworkMethod> methods = super.getChildren();
        m_testMethodsCount = methods.size();
        return methods;
    }
}
Pranjal
  • 63
  • 2
  • 7
Shay_t
  • 163
  • 1
  • 16

3 Answers3

1

Instead of creating a separate test runner, you can define the actions to perform before and after in the test class itself in methods annotated with @BeforeClass resp. @AfterClass.

To reuse them in more than one test you can easily inherit them from a base class.

Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
  • i am aware of them, but my base runner is doing much more then test methods. so for this complex case i might need it – Shay_t Jun 26 '17 at 12:47
  • 1
    It seems that the JUnit API does not support this case. But I wouldn't be sure how your solution behaves in case of exceptions in the test cases, when multithreaded etc. – Uwe Allner Jun 26 '17 at 13:09
  • so i guess this "hack" is something ill have to find out, maybe someone tried it already . – Shay_t Jun 27 '17 at 05:36
0

the easiest way is override the run method as below:

public class LifecycleRunner extends BlockJUnit4ClassRunner {

    public LifecycleRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    public void run(RunNotifier notifier) {
        beforeRunTests();
        try {
            super.run(notifier);
        } finally {
            afterRunTests();
        }
    }

    private void afterRunTests() {
        trace();
    }

    private void beforeRunTests() {
        trace();
    }

    private void trace() {
        System.out.println(Thread.currentThread().getStackTrace()[2]);
    }
}
holi-java
  • 29,655
  • 7
  • 72
  • 83
0

To gain full control over test execution, install a proper RunListener in your runner.

@Override
public void run(final RunNotifier notifier)
{
    final RunListener listener = new RunListener()
    {
        @Override
        public void testStarted(final Description description) throws Exception
        {
            // do something before each (non-ignored) Test method is executed
        }


        @Override
        public void testFinished(final Description description) throws Exception
        {
            // do something after each Test method was performed (failed or successful)
        }

        // check further listener methods yourself!

    };

    // install your listener
    notifier.addListener(listener);
    super.run(notifier);
    // and remove it again
    notifier.removeListener(listener);
}