FunctionalJavaFXRunner.java
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<?> klassthrows 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 failurethrows 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 childthrows NoSuchFieldException, IllegalAccessException {
107         if (testFXClassRule == null) {
108             for (Field field : child.getDeclaringClass().getFields()) {
109                 if (GriffonTestFXClassRule.class.isAssignableFrom(field.getType())) {
110                     testFXClassRule = (GriffonTestFXClassRulefield.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 }