/* * Copyright 2000-2013 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.sass.testcases.scss; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.Parameterized; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; /** * Test runner that executes methods annotated with @{@link FactoryTest} with * all the values returned by a method annotated with @{@link TestFactory} as * their parameters parameter. * * This runner is loosely based on FactoryTestRunner by Ted Young * (http://tedyoung.me/2011/01/23/junit-runtime-tests-custom-runners/). The * generated test names give information about the parameters used (unlike * {@link Parameterized}). * * @since 7.0 */ public class SassTestRunner extends BlockJUnit4ClassRunner { @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface TestFactory { } @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface FactoryTest { } public SassTestRunner(Class klass) throws InitializationError { super(klass); } @Override protected List computeTestMethods() { List tests = new LinkedList(); // Final all methods in our test class marked with @TestFactory. for (FrameworkMethod method : getTestClass().getAnnotatedMethods( TestFactory.class)) { // Make sure the TestFactory method is static if (!Modifier.isStatic(method.getMethod().getModifiers())) { throw new IllegalArgumentException("TestFactory " + method + " must be static."); } // Execute the method (statically) Object params; try { params = method.getMethod().invoke( getTestClass().getJavaClass()); } catch (Throwable t) { throw new RuntimeException("Could not run test factory method " + method.getName(), t); } // Did the factory return an array? If so, make it a list. if (params.getClass().isArray()) { params = Arrays.asList((Object[]) params); } // Did the factory return a scalar object? If so, put it in a list. if (!(params instanceof Iterable)) { params = Collections.singletonList(params); } // For each object returned by the factory. for (Object param : (Iterable) params) { // Find any methods marked with @SassTest. for (FrameworkMethod m : getTestClass().getAnnotatedMethods( FactoryTest.class)) { tests.add(new ParameterizedFrameworkMethod(m.getMethod(), new Object[] { param })); } } } return tests; } private static class ParameterizedFrameworkMethod extends FrameworkMethod { private Object[] params; public ParameterizedFrameworkMethod(Method method, Object[] params) { super(method); this.params = params; } @Override public Object invokeExplosively(Object target, Object... params) throws Throwable { // Executes the test method with the supplied parameters (returned // by the // TestFactory) and not the instance generated by FrameworkMethod. return super.invokeExplosively(target, this.params); } @Override public String getName() { return String.format("%s[%s]", getMethod().getName(), Arrays.toString(params)); } } }