Run acceptance tests with custom suite to set Configs
@Parameterized doesn't allow for running a single test method in Eclipse, since Eclipse looks for a test name exactly matching the method name, and @Parameterized always appends "[name]" to method names. Use a custom suite that avoids this problem by not appending anything to the name for the default config. Running a single test method in Eclipse now chooses the default (empty) config. This is arguably not as nice as if it ran all permutations with that name, but it at least chooses the least surprising option. Since this suite only deals with setting a single field of a single type on the test, it can be simpler than the more general implementation of @Parameterized. It also has the advantage that subclasses can provide their own @ConfigSuite.Config implementations to add additional permutations at the per-acceptance-test level, rather than globally. Change-Id: I2a83f789f922d894c1bd111c1339f7ca9aacab00
This commit is contained in:
parent
afb276e22e
commit
9760cdc2b2
@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.acceptance;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.gerrit.acceptance.GitUtil.initSsh;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@ -22,6 +21,7 @@ import com.google.common.base.Joiner;
|
||||
import com.google.gerrit.extensions.common.ListChangesOption;
|
||||
import com.google.gerrit.server.OutputFormat;
|
||||
import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
|
||||
import com.google.gerrit.testutil.ConfigSuite;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
@ -31,39 +31,13 @@ import org.junit.Rule;
|
||||
import org.junit.rules.TestRule;
|
||||
import org.junit.runner.Description;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameter;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.junit.runners.model.Statement;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
@RunWith(ConfigSuite.class)
|
||||
public abstract class AbstractDaemonTest {
|
||||
private static class NamedConfig extends Config {
|
||||
private final String name;
|
||||
|
||||
private NamedConfig(String name) {
|
||||
this.name = checkNotNull(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Parameters(name = "{0}")
|
||||
public static Iterable<Object[]> configs() {
|
||||
Config defaultConfig = new NamedConfig("default");
|
||||
|
||||
return Arrays.asList(new Object[][]{
|
||||
{defaultConfig},
|
||||
});
|
||||
}
|
||||
|
||||
@Parameter
|
||||
@ConfigSuite.Parameter
|
||||
public Config baseConfig;
|
||||
|
||||
@Inject
|
||||
|
@ -0,0 +1,186 @@
|
||||
// Copyright (C) 2014 The Android Open Source Project
|
||||
//
|
||||
// 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.google.gerrit.testutil;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.lang.annotation.ElementType.FIELD;
|
||||
import static java.lang.annotation.ElementType.METHOD;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import org.junit.runner.Runner;
|
||||
import org.junit.runners.BlockJUnit4ClassRunner;
|
||||
import org.junit.runners.Suite;
|
||||
import org.junit.runners.model.FrameworkMethod;
|
||||
import org.junit.runners.model.InitializationError;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Suite to run tests with different {@code gerrit.config} values.
|
||||
* <p>
|
||||
* For each {@link Config} method in the class and base classes, a new group of
|
||||
* tests is created with the {@link Parameter} field set to the config.
|
||||
*
|
||||
* <pre>
|
||||
* @RunWith(ConfigSuite.class)
|
||||
* public abstract class MyAbstractTest {
|
||||
* @ConfigSuite.Parameter
|
||||
* protected Config cfg;
|
||||
*
|
||||
* @ConfigSuite.Config
|
||||
* public static Config firstConfig() {
|
||||
* Config cfg = new Config();
|
||||
* cfg.setString("gerrit", null, "testValue", "a");
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* public class MyTest {
|
||||
* @ConfigSuite.Config
|
||||
* public static Config secondConfig() {
|
||||
* Config cfg = new Config();
|
||||
* cfg.setString("gerrit", null, "testValue", "b");
|
||||
* }
|
||||
*
|
||||
* @Test
|
||||
* public void myTest() {
|
||||
* // Test using cfg.
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* This creates a suite of tests with three groups:
|
||||
* <ul>
|
||||
* <li><strong>default</strong>: {@code MyTest.myTest}</li>
|
||||
* <li><strong>firstConfig</strong>: {@code MyTest.myTest[firstConfig]}</li>
|
||||
* <li><strong>secondConfig</strong>: {@code MyTest.myTest[secondConfig]}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ConfigSuite extends Suite {
|
||||
private static final String DEFAULT = "default";
|
||||
|
||||
@Target({METHOD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface Config {
|
||||
}
|
||||
|
||||
@Target({FIELD})
|
||||
@Retention(RUNTIME)
|
||||
public static @interface Parameter {
|
||||
}
|
||||
|
||||
private static class ConfigRunner extends BlockJUnit4ClassRunner {
|
||||
private final Method configMethod;
|
||||
private final Field parameterField;
|
||||
private final String name;
|
||||
|
||||
private ConfigRunner(Class<?> clazz, Field parameterField, String name,
|
||||
Method configMethod) throws InitializationError {
|
||||
super(clazz);
|
||||
this.parameterField = parameterField;
|
||||
this.name = name;
|
||||
this.configMethod = configMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createTest() throws Exception {
|
||||
Object test = getTestClass().getJavaClass().newInstance();
|
||||
parameterField.set(test, callConfigMethod(configMethod));
|
||||
return test;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getName() {
|
||||
return Objects.firstNonNull(name, DEFAULT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String testName(FrameworkMethod method) {
|
||||
String n = method.getName();
|
||||
return name == null ? n : n + "[" + name + "]";
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Runner> runnersFor(Class<?> clazz) {
|
||||
List<Method> configs = getConfigs(clazz);
|
||||
Field field = getParameterField(clazz);
|
||||
List<Runner> result = Lists.newArrayListWithCapacity(configs.size() + 1);
|
||||
try {
|
||||
result.add(new ConfigRunner(clazz, field, null, null));
|
||||
for (Method m : configs) {
|
||||
result.add(new ConfigRunner(clazz, field, m.getName(), m));
|
||||
}
|
||||
return result;
|
||||
} catch (InitializationError e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Method> getConfigs(Class<?> clazz) {
|
||||
List<Method> result = Lists.newArrayListWithExpectedSize(3);
|
||||
for (Method m : clazz.getMethods()) {
|
||||
Config ann = m.getAnnotation(Config.class);
|
||||
if (ann != null) {
|
||||
checkArgument(!m.getName().equals(DEFAULT),
|
||||
"@ConfigSuite.Config cannot be named %s", DEFAULT);
|
||||
result.add(m);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static org.eclipse.jgit.lib.Config callConfigMethod(Method m) {
|
||||
if (m == null) {
|
||||
return new org.eclipse.jgit.lib.Config();
|
||||
}
|
||||
checkArgument(
|
||||
org.eclipse.jgit.lib.Config.class.isAssignableFrom(m.getReturnType()),
|
||||
"%s must return Config", m);
|
||||
checkArgument((m.getModifiers() & Modifier.STATIC) != 0,
|
||||
"%s must be static", m);
|
||||
checkArgument(m.getParameterTypes().length == 0,
|
||||
"%s must take no parameters", m);
|
||||
try {
|
||||
return (org.eclipse.jgit.lib.Config) m.invoke(null);
|
||||
} catch (IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Field getParameterField(Class<?> clazz) {
|
||||
List<Field> fields = Lists.newArrayListWithExpectedSize(1);
|
||||
for (Field f : clazz.getFields()) {
|
||||
if (f.getAnnotation(Parameter.class) != null) {
|
||||
fields.add(f);
|
||||
}
|
||||
}
|
||||
checkArgument(fields.size() == 1,
|
||||
"expected 1 @ConfigSuite.Parameter field, found: %s", fields);
|
||||
return fields.get(0);
|
||||
}
|
||||
|
||||
public ConfigSuite(Class<?> clazz) throws InitializationError {
|
||||
super(clazz, runnersFor(clazz));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user