/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.runtime.junit4.runners;
import junit.extensions.TestDecorator;
import junit.framework.AssertionFailedError;
import junit.framework.JUnit4TestAdapter;
import junit.framework.JUnit4TestCaseFacade;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestListener;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Sortable;
import org.junit.runner.manipulation.Sorter;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
/**
* <p>The <code>JUnit38ClassRunner</code> provides a means to explicitly define
* a JUnit3 runner for running JUnit3 tests. This comes in handy when you
* are trying to run a suite of PDE tests that combines JUnit3 with JUnit4 style tests.
* <p>
* For example, suppose we have two tests:
* <pre>
* @RunWith(TestRunnerSWT.class)
* public class NewProjectJUnit4Test {
* @Test
* public void verifyNewProjectCreation() throws Exception {
* ...
* }
* }
*
* @(JUnit38ClassRunner.class)
* public class NewProjectJUnit3Test extends UITestCaseSWT {
* public void testNewProjectCreation() throws Exception {
* ...
* }
* }
* </pre>
* The annotation on <code>NewProjectJUnit3Test<code> will allow you to run them both in a JUnit4 suite
* like so:
* <pre>
* @RunWith(Suite.class)
* @SuiteClasses( { NewProjectJUnit3Test.class, NewProjectJUnit4Test.class })
* public class MixedSuite {}
* </pre>
* <p>
* <b>NOTE:</b> this provision should not be required as the JUnit test suite runner
* should handle the mixed case smartly. That said, there are issues with the PDE test
* runner and until they are resolved, this workaround is required.
*
*
*
* @author Phil Quitslund
*
*/
public class JUnit38ClassRunner extends Runner implements /*Filterable, */ Sortable {
private static final class OldTestClassAdaptingListener implements
TestListener {
private final RunNotifier fNotifier;
private OldTestClassAdaptingListener(RunNotifier notifier) {
fNotifier= notifier;
}
public void endTest(Test test) {
fNotifier.fireTestFinished(asDescription(test));
}
public void startTest(Test test) {
fNotifier.fireTestStarted(asDescription(test));
}
// Implement junit.framework.TestListener
public void addError(Test test, Throwable t) {
Failure failure= new Failure(asDescription(test), t);
fNotifier.fireTestFailure(failure);
}
private Description asDescription(Test test) {
if (test instanceof JUnit4TestCaseFacade) {
JUnit4TestCaseFacade facade= (JUnit4TestCaseFacade) test;
return facade.getDescription();
}
return Description.createTestDescription(test.getClass(), getName(test));
}
private String getName(Test test) {
if (test instanceof TestCase)
return ((TestCase) test).getName();
else
return test.toString();
}
public void addFailure(Test test, AssertionFailedError t) {
addError(test, t);
}
}
private Test fTest;
public JUnit38ClassRunner(Class<?> klass) {
this(new TestSuite(klass.asSubclass(TestCase.class)));
}
public JUnit38ClassRunner(Test test) {
super();
fTest= test;
}
@Override
public void run(RunNotifier notifier) {
TestResult result= new TestResult();
result.addListener(createAdaptingListener(notifier));
fTest.run(result);
}
public static TestListener createAdaptingListener(final RunNotifier notifier) {
return new OldTestClassAdaptingListener(notifier);
}
@Override
public Description getDescription() {
return makeDescription(fTest);
}
private Description makeDescription(Test test) {
if (test instanceof TestCase) {
TestCase tc= (TestCase) test;
return Description.createTestDescription(tc.getClass(), tc.getName());
} else if (test instanceof TestSuite) {
TestSuite ts= (TestSuite) test;
String name= ts.getName() == null ? "" : ts.getName();
Description description= Description.createSuiteDescription(name);
int n= ts.testCount();
for (int i= 0; i < n; i++)
description.addChild(makeDescription(ts.testAt(i)));
return description;
} else if (test instanceof JUnit4TestAdapter) {
JUnit4TestAdapter adapter= (JUnit4TestAdapter) test;
return adapter.getDescription();
} else if (test instanceof TestDecorator) {
TestDecorator decorator= (TestDecorator) test;
return makeDescription(decorator.getTest());
} else {
// This is the best we can do in this case
return Description.createSuiteDescription(test.getClass());
}
}
//TODO (pq): verify these impls.
// public void filter(Filter filter) throws NoTestsRemainException {
// filter.apply(this);
// }
public void sort(Sorter sorter) {
sorter.apply(this);
}
}