001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 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 * Contributors: 017 * <a href="mailto:grenard@nuxeo.com">Guillaume</a> 018 */ 019 020package org.nuxeo.functionaltests; 021 022import static org.nuxeo.functionaltests.AbstractTest.NUXEO_URL; 023import static org.nuxeo.functionaltests.Constants.ADMINISTRATOR; 024 025import java.io.File; 026import java.lang.reflect.Field; 027import java.lang.reflect.Method; 028import java.util.List; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.junit.internal.runners.statements.RunAfters; 033import org.junit.rules.TestWatchman; 034import org.junit.runners.model.FrameworkMethod; 035import org.junit.runners.model.Statement; 036import org.nuxeo.client.api.Client; 037import org.nuxeo.client.api.NuxeoClient; 038import org.nuxeo.common.utils.URIUtils; 039import org.openqa.selenium.remote.RemoteWebDriver; 040 041import okhttp3.Response; 042 043/** 044 * Watchman to log info about the test and create snapshot on failure. 045 * 046 * @since 5.8 047 */ 048public class LogTestWatchman extends TestWatchman { 049 050 protected static final Log log = LogFactory.getLog(AbstractTest.class); 051 052 protected String lastScreenshot; 053 054 protected String lastPageSource; 055 056 protected String filePrefix; 057 058 protected RemoteWebDriver driver; 059 060 protected String serverURL; 061 062 public LogTestWatchman(final RemoteWebDriver driver, final String serverURL) { 063 this.driver = driver; 064 this.serverURL = serverURL; 065 } 066 067 public LogTestWatchman() { 068 } 069 070 @Override 071 @SuppressWarnings("unchecked") 072 public Statement apply(final Statement base, final FrameworkMethod method, Object target) { 073 return new Statement() { 074 @Override 075 public void evaluate() throws Throwable { 076 starting(method); 077 try { 078 if (base instanceof RunAfters) { 079 // Hack JUnit: in order to take screenshot at the right 080 // time we add through reflection an after 081 // function that will be executed before all other 082 // ones. See NXP-12742 083 Field fAtersField = RunAfters.class.getDeclaredField("fAfters"); 084 fAtersField.setAccessible(true); 085 086 List<FrameworkMethod> afters = (List<FrameworkMethod>) fAtersField.get(base); 087 if (afters != null && !afters.isEmpty()) { 088 try { 089 // Improve this and instead of finding a 090 // special function, we could register 091 // functions specially annotated. 092 FrameworkMethod first = afters.get(0); 093 Method m = AbstractTest.class.getMethod("runBeforeAfters", (Class<?>[]) null); 094 FrameworkMethod f = new FrameworkMethod(m); 095 if (first != null && !first.equals(f)) { 096 afters.add(0, f); 097 } 098 } catch (NoSuchMethodException e) { 099 // Do nothing 100 } 101 } 102 } 103 base.evaluate(); 104 succeeded(method); 105 } catch (Throwable t) { 106 failed(t, method); 107 throw t; 108 } finally { 109 finished(method); 110 } 111 } 112 }; 113 } 114 115 /** 116 * @deprecated since 5.9.2, use {@link ScreenshotTaker#dumpPageSource(org.openqa.selenium.WebDriver, String)} 117 * instead. 118 */ 119 @Deprecated 120 public File dumpPageSource(String filename) { 121 ScreenshotTaker taker = new ScreenshotTaker(); 122 return taker.dumpPageSource(driver, filename); 123 } 124 125 @Override 126 public void failed(Throwable e, FrameworkMethod method) { 127 String className = getTestClassName(method); 128 String methodName = method.getName(); 129 log.error(String.format("Test '%s#%s' failed", className, methodName), e); 130 131 if (lastScreenshot == null || lastPageSource == null) { 132 ScreenshotTaker taker = new ScreenshotTaker(); 133 134 if (lastScreenshot == null) { 135 File temp = taker.takeScreenshot(driver, filePrefix); 136 lastScreenshot = temp != null ? temp.getAbsolutePath() : null; 137 } 138 139 if (lastPageSource == null) { 140 File temp = taker.dumpPageSource(driver, filePrefix); 141 lastPageSource = temp != null ? temp.getAbsolutePath() : null; 142 } 143 144 } 145 log.info(String.format("Created screenshot file named '%s'", lastScreenshot)); 146 log.info(String.format("Created page source file named '%s'", lastPageSource)); 147 super.failed(e, method); 148 } 149 150 @Override 151 public void finished(FrameworkMethod method) { 152 log.info(String.format("Finished test '%s#%s'", getTestClassName(method), method.getName())); 153 lastScreenshot = null; 154 lastPageSource = null; 155 super.finished(method); 156 } 157 158 public RemoteWebDriver getDriver() { 159 return driver; 160 } 161 162 public String getServerURL() { 163 return serverURL; 164 } 165 166 protected String getTestClassName(FrameworkMethod method) { 167 return method.getMethod().getDeclaringClass().getName(); 168 } 169 170 protected void logOnServer(String message) { 171 if (driver != null) { 172 Client client = new NuxeoClient(NUXEO_URL, ADMINISTRATOR, ADMINISTRATOR); 173 Response response = client.get(NUXEO_URL + "/restAPI/systemLog"); 174 if (response.isSuccessful()) { 175 driver.get(String.format("%s/restAPI/systemLog?token=dolog&level=WARN&message=----- WebDriver: %s", 176 serverURL, URIUtils.quoteURIPathComponent(message, true))); 177 return; 178 } 179 } 180 log.warn(String.format("Cannot log on server message: %s", message)); 181 } 182 183 public void runBeforeAfters() { 184 if (driver != null) { 185 ScreenshotTaker taker = new ScreenshotTaker(); 186 lastScreenshot = taker.takeScreenshot(driver, filePrefix).getAbsolutePath(); 187 lastPageSource = taker.dumpPageSource(driver, filePrefix).getAbsolutePath(); 188 } 189 } 190 191 public void setDriver(RemoteWebDriver driver) { 192 this.driver = driver; 193 } 194 195 public void setServerURL(String serverURL) { 196 this.serverURL = serverURL; 197 } 198 199 @Override 200 public void starting(FrameworkMethod method) { 201 String message = String.format("Starting test '%s#%s'", getTestClassName(method), method.getName()); 202 log.info(message); 203 String className = getTestClassName(method); 204 String methodName = method.getName(); 205 filePrefix = String.format("screenshot-lastpage-%s-%s", className, methodName); 206 logOnServer(message); 207 } 208 209 @Override 210 public void succeeded(FrameworkMethod method) { 211 if (lastPageSource != null) { 212 new File(lastPageSource).delete(); 213 } 214 if (lastScreenshot != null) { 215 new File(lastScreenshot).delete(); 216 } 217 } 218 219 /** 220 * @deprecated since 5.9.2, use {@link ScreenshotTaker#takeScreenshot(org.openqa.selenium.WebDriver, String)} 221 * instead. 222 */ 223 @Deprecated 224 public File takeScreenshot(String filename) { 225 ScreenshotTaker taker = new ScreenshotTaker(); 226 return taker.takeScreenshot(driver, filename); 227 } 228 229}