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