001 /* 002 * Created on Nov 17, 2007 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with 005 * the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on 010 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the 011 * specific language governing permissions and limitations under the License. 012 * 013 * Copyright @2007-2009 the original author or authors. 014 */ 015 package org.fest.swing.junit.v4_3_1.runner; 016 017 018 import static org.junit.runner.Description.createSuiteDescription; 019 import static org.junit.runner.Description.createTestDescription; 020 021 import java.lang.reflect.InvocationTargetException; 022 import java.lang.reflect.Method; 023 import java.util.List; 024 025 import org.fest.swing.junit.runner.FailureScreenshotTaker; 026 import org.fest.swing.junit.runner.ImageFolderCreator; 027 import org.junit.Test; 028 import org.junit.internal.runners.*; 029 import org.junit.runner.Description; 030 import org.junit.runner.Runner; 031 import org.junit.runner.notification.RunNotifier; 032 033 /** 034 * Understands a JUnit 4.3.1 test runner that takes a screenshot of a failed GUI test. 035 * 036 * @author Alex Ruiz 037 * @author Yvonne Wang 038 */ 039 public class GUITestRunner extends Runner { 040 041 private final List<Method> testMethods; 042 private final Class<?> testClass; 043 044 private final FailureScreenshotTaker screenshotTaker; 045 046 /** 047 * Creates a new <code>{@link GUITestRunner}</code>. 048 * @param testClass the class containing the tests to run. 049 * @throws InitializationError if something goes wrong when creating this runner. 050 */ 051 public GUITestRunner(Class<?> testClass) throws InitializationError { 052 this.testClass = testClass; 053 testMethods = new TestIntrospector(testClass).getTestMethods(Test.class); 054 validate(); 055 screenshotTaker = new FailureScreenshotTaker(new ImageFolderCreator().createImageFolder()); 056 } 057 058 private void validate() throws InitializationError { 059 MethodValidator methodValidator = new MethodValidator(testClass); 060 methodValidator.validateMethodsForDefaultRunner(); 061 methodValidator.assertValid(); 062 } 063 064 /** 065 * Run the tests for this runner, taking screenshots of failing tests. 066 * @param notifier will be notified of events while tests are being run, started, finishing, and failing. 067 */ 068 @Override 069 public void run(RunNotifier notifier) { 070 new InnerRunner(this, notifier).runProtected(); 071 } 072 073 // called by InnerRunner 074 void doRun(RunNotifier notifier) { 075 if (testMethods.isEmpty()) notifier.testAborted(getDescription(), new Exception("No runnable methods")); 076 for (Method method : testMethods) 077 invokeTestMethod(method, notifier); 078 } 079 080 private void invokeTestMethod(Method method, RunNotifier notifier) { 081 Object test; 082 try { 083 test = testClass.getConstructor().newInstance(); 084 } catch (InvocationTargetException e) { 085 notifier.testAborted(descriptionOf(method), e.getCause()); 086 return; 087 } catch (Exception e) { 088 notifier.testAborted(descriptionOf(method), e); 089 return; 090 } 091 createMethodRunner(test, method, notifier).run(); 092 } 093 094 private MethodRunner createMethodRunner(Object test, Method method, RunNotifier notifier) { 095 return new MethodRunner(new TestInfo(test, testClass, method), notifier, screenshotTaker); 096 } 097 098 final Class<?> testClass() { 099 return testClass; 100 } 101 102 /** 103 * Returns a <code>{@link Description}</code> showing the tests to be run by the receiver. 104 * @return a <code>Description</code> showing the tests to be run by the receiver. 105 */ 106 public Description getDescription() { 107 Description spec = createSuiteDescription(testClass.getName()); 108 for (Method method : testMethods) 109 spec.addChild(descriptionOf(method)); 110 return spec; 111 } 112 113 private Description descriptionOf(Method method) { 114 return createTestDescription(testClass, method.getName()); 115 } 116 }