001 /*
002 * Copyright 2008-2016 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.javafx.test;
017
018 import org.junit.internal.runners.statements.Fail;
019 import org.junit.runner.notification.Failure;
020 import org.junit.runner.notification.RunListener;
021 import org.junit.runner.notification.RunNotifier;
022 import org.junit.runners.BlockJUnit4ClassRunner;
023 import org.junit.runners.model.FrameworkMethod;
024 import org.junit.runners.model.InitializationError;
025 import org.junit.runners.model.Statement;
026
027 import javax.annotation.Nonnull;
028 import java.lang.reflect.Field;
029 import java.util.ArrayList;
030 import java.util.Collections;
031 import java.util.Comparator;
032 import java.util.List;
033
034 import static java.util.Collections.unmodifiableList;
035 import static org.junit.runner.Description.createTestDescription;
036
037 /**
038 * @author Andres Almiray
039 * @since 2.6.0
040 */
041 public class FunctionalJavaFXRunner extends BlockJUnit4ClassRunner {
042 private GriffonTestFXClassRule testFXClassRule;
043
044 public FunctionalJavaFXRunner(@Nonnull Class<?> klass) throws InitializationError {
045 super(klass);
046 }
047
048 private static class FailureListener extends RunListener {
049 private final GriffonTestFXClassRule testfx;
050
051 private FailureListener(GriffonTestFXClassRule testfx) {
052 this.testfx = testfx;
053 }
054
055 @Override
056 public void testFailure(Failure failure) throws Exception {
057 testfx.setFailures(true);
058 }
059 }
060
061 @Override
062 protected List<FrameworkMethod> computeTestMethods() {
063 List<FrameworkMethod> methods = new ArrayList<>(super.computeTestMethods());
064 Collections.sort(methods, new Comparator<FrameworkMethod>() {
065 @Override
066 public int compare(FrameworkMethod a, FrameworkMethod b) {
067 return a.getName().compareTo(b.getName());
068 }
069 });
070 return unmodifiableList(methods);
071 }
072
073 @Override
074 protected void runChild(FrameworkMethod method, RunNotifier notifier) {
075 try {
076 resolveTestFXClassRule(method);
077 notifier.addFirstListener(new FailureListener(testFXClassRule));
078 } catch (Exception e) {
079 notifier.fireTestFailure(new Failure(createTestDescription(method.getDeclaringClass(), method.getName()), e));
080 }
081 super.runChild(method, notifier);
082 }
083
084 @Override
085 protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
086 try {
087 resolveTestFXClassRule(method);
088 testFXClassRule.injectMembers(target);
089 } catch (Exception e) {
090 return new Fail(e);
091 }
092 return super.withBefores(method, target, statement);
093 }
094
095 @Override
096 protected boolean isIgnored(FrameworkMethod child) {
097 if (super.isIgnored(child)) {
098 return true;
099 }
100
101 try {
102 resolveTestFXClassRule(child);
103 return testFXClassRule.hasFailures();
104 } catch (Exception e) {
105 return true;
106 }
107 }
108
109 private void resolveTestFXClassRule(FrameworkMethod child) throws NoSuchFieldException, IllegalAccessException {
110 if (testFXClassRule == null) {
111 for (Field field : child.getDeclaringClass().getFields()) {
112 if (GriffonTestFXClassRule.class.isAssignableFrom(field.getType())) {
113 testFXClassRule = (GriffonTestFXClassRule) field.get(null);
114 return;
115 }
116 }
117 throw new IllegalStateException("Class " + child.getDeclaringClass().getName() + " does not define a field of type " + GriffonTestFXClassRule.class.getName());
118 }
119 }
120 }
|