/* * This code is distributed under The GNU Lesser General Public License (LGPLv3) * Please visit GNU site for LGPLv3 http://www.gnu.org/copyleft/lesser.html * * Copyright Denis Pavlov 2009 * Web: http://www.genericdtoassembler.org * SVN: https://svn.code.sf.net/p/geda-genericdto/code/trunk/ * SVN (mirror): http://geda-genericdto.googlecode.com/svn/trunk/ */ /* * This clas was reused from JUnit 4.6 library and altered to allow to see parameter names * rather than indices when running junit tests. */ package com.inspiresoftware.lib.dto.geda.utils; import org.junit.Ignore; import org.junit.runner.Runner; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.Suite; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import org.junit.runners.model.TestClass; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * <p> * The custom runner <code>Parameterized</code> implements parameterized tests. * When running a parameterized test class, instances are created for the * cross-product of the test methods and the test data elements. * </p> * * For example, to test a Fibonacci function, write: * * <pre> * @RunWith(Parameterized.class) * public class FibonacciTest { * @Parameters * public static Collection<Object[]> data() { * return Arrays.asList(new Object[][] { * Fibonacci, * { { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, * { 6, 8 } } }); * } * * private int fInput; * * private int fExpected; * * public FibonacciTest(int input, int expected) { * fInput= input; * fExpected= expected; * } * * @Test * public void test(@HeresHowYouGetValue Type value) { * assertAnswerKey(new Object[][] { * Fibonacci, * { { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, * { 6, 8 } } }); * assertEquals(fExpected, Fibonacci.compute(fInput)); * } * } * </pre> * * <p> * Each instance of <code>FibonacciTest</code> will be constructed using the * two-argument constructor and the data values in the * <code>@Parameters</code> method. * </p> */ @Ignore public class ParameterizedSynthesizer extends Suite { /** * Annotation for a method which provides parameters to be injected into the * test class constructor by <code>Parameterized</code>. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public static @interface Parameters { } /** Child class. */ private class TestClassRunnerForParameters extends BlockJUnit4ClassRunner { private final int fParameterSetNumber; private final List<Object[]> fParameterList; TestClassRunnerForParameters(final Class< ? > type, final List<Object[]> parameterList, final int i) throws InitializationError { super(type); fParameterList = parameterList; fParameterSetNumber = i; } @Override public Object createTest() throws Exception { return getTestClass().getOnlyConstructor().newInstance( computeParams()); } private Object[] computeParams() throws Exception { try { return fParameterList.get(fParameterSetNumber); } catch (ClassCastException e) { throw new Exception(String.format( "%s.%s() must return a Collection of arrays.", getTestClass().getName(), getParametersMethod( getTestClass()).getName())); } } @Override protected String getName() { return String.format("[%s]", fParameterList.get(fParameterSetNumber)[0]); } @Override protected String testName(final FrameworkMethod method) { return String.format("%s[%s]", method.getName(), fParameterList.get(fParameterSetNumber)[0]); } @Override protected void validateZeroArgConstructor(final List<Throwable> errors) { // constructor can, nay, should have args. } @Override protected Statement classBlock(final RunNotifier notifier) { return childrenInvoker(notifier); } } private final ArrayList<Runner> runners = new ArrayList<Runner>(); /** * Only called reflectively. Do not use programmatically. * @param klass class * @throws Throwable throwable */ public ParameterizedSynthesizer(final Class< ? > klass) throws Throwable { super(klass, Collections.<Runner>emptyList()); List<Object[]> parametersList = getParametersList(getTestClass()); for (int i = 0; i < parametersList.size(); i++) { runners.add(new TestClassRunnerForParameters(getTestClass().getJavaClass(), parametersList, i)); } } /** {@inheritDoc} */ @Override protected List<Runner> getChildren() { return runners; } @SuppressWarnings("unchecked") private List<Object[]> getParametersList(final TestClass klass) throws Throwable { return (List<Object[]>) getParametersMethod(klass).invokeExplosively( null); } private FrameworkMethod getParametersMethod(final TestClass testClass) throws Exception { List<FrameworkMethod> methods = testClass .getAnnotatedMethods(Parameters.class); for (FrameworkMethod each : methods) { int modifiers = each.getMethod().getModifiers(); if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers)) { return each; } } throw new Exception("No public static parameters method on class " + testClass.getName()); } }