blob: 0d309dc9fafd4e8a9e7c12b3cdc1526cd6b62897 [file] [log] [blame]
/*
* 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.android.tools.idea.tests.gui.framework;
import org.fest.swing.image.ScreenshotTaker;
import org.jetbrains.annotations.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.ReflectiveCallable;
import org.junit.internal.runners.statements.Fail;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
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.awt.*;
import java.lang.reflect.Method;
import java.util.List;
import static org.junit.Assert.assertNotNull;
public class GuiTestRunner extends BlockJUnit4ClassRunner {
private TestClass myTestClass;
@Nullable private final ScreenshotTaker myScreenshotTaker;
public GuiTestRunner(Class<?> testClass) throws InitializationError {
super(testClass);
myScreenshotTaker = canRunGuiTests() ? new ScreenshotTaker() : null;
try {
// A random class which is reachable from module community-main's classpath but not
// module android's classpath
Class.forName("git4idea.repo.GitConfig", false, testClass.getClassLoader());
}
catch (ClassNotFoundException e) {
throw new InitializationError("Invalid test run configuration. Edit your test configuration and make sure that " +
"\"Use classpath of module\" is set to \"community-main\", *NOT* \"android\"!");
}
}
@Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
if (!canRunGuiTests()) {
notifier.fireTestAssumptionFailed(new Failure(describeChild(method), new AssumptionViolatedException("Headless environment")));
System.out.println(String.format("Skipping test '%1$s'. UI tests cannot run in a headless environment.", method.getName()));
} else if (MethodInvoker.doesIdeHaveFatalErrors()) {
notifier.fireTestIgnored(describeChild(method)); // TODO: can we restart the IDE at this point, instead of giving up?
System.out.println(String.format("Skipping test '%1$s': a fatal error has occurred in the IDE", method.getName()));
notifier.pleaseStop();
} else {
super.runChild(method, notifier);
}
}
@Override
protected Statement methodBlock(FrameworkMethod method) {
FrameworkMethod newMethod;
try {
loadClassesWithIdeClassLoader();
Method methodFromClassLoader = myTestClass.getJavaClass().getMethod(method.getName());
newMethod = new FrameworkMethod(methodFromClassLoader);
}
catch (Exception e) {
return new Fail(e);
}
Object test;
try {
test = new ReflectiveCallable() {
@Override
protected Object runReflectiveCall() throws Throwable {
return createTest();
}
}.run();
}
catch (Throwable e) {
return new Fail(e);
}
Statement statement = methodInvoker(newMethod, test);
List<FrameworkMethod> beforeMethods = myTestClass.getAnnotatedMethods(Before.class);
if (!beforeMethods.isEmpty()) {
statement = new RunBefores(statement, beforeMethods, test);
}
List<FrameworkMethod> afterMethods = myTestClass.getAnnotatedMethods(After.class);
if (!afterMethods.isEmpty()) {
statement = new RunAfters(statement, afterMethods, test);
}
return statement;
}
public static boolean canRunGuiTests() {
return !GraphicsEnvironment.isHeadless();
}
private void loadClassesWithIdeClassLoader() throws Exception {
ClassLoader ideClassLoader = IdeTestApplication.getInstance().getIdeClassLoader();
Thread.currentThread().setContextClassLoader(ideClassLoader);
Class<?> testClass = getTestClass().getJavaClass();
myTestClass = new TestClass(ideClassLoader.loadClass(testClass.getName()));
}
@Override
protected Object createTest() throws Exception {
return myTestClass != null ? myTestClass.getJavaClass().newInstance() : super.createTest();
}
@Override
protected Statement methodInvoker(final FrameworkMethod method, Object test) {
try {
assertNotNull(myScreenshotTaker);
return new MethodInvoker(method, test, myScreenshotTaker);
}
catch (Throwable e) {
return new Fail(e);
}
}
}