All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.inftec.ju.ee.webtest.DriverRule Maven / Gradle / Ivy

Go to download

Contains helping classes for Unit Testing, supporting CDI and EE features, including DB access

There is a newer version: 4.5.1-11
Show newest version
package ch.inftec.ju.ee.webtest;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.junit.Assert;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.inftec.ju.testing.db.DbTestAnnotationHandler;
import ch.inftec.ju.testing.db.JuTestEnv;
import ch.inftec.ju.util.AssertUtil;
import ch.inftec.ju.util.JuRuntimeException;
import ch.inftec.ju.util.JuStringUtils;
import ch.inftec.ju.util.JuUrl;
import ch.inftec.ju.util.JuUtils;
import ch.inftec.ju.util.PropertyChain;
import ch.inftec.ju.util.ReflectUtils;
import ch.inftec.ju.util.ReflectUtils.AnnotationInfo;
import ch.inftec.ju.util.SystemPropertyTempSetter;
import ch.inftec.ju.util.TestUtils;

/**
 * JUnit rule to run web tests with (multiple) selenium drivers.
 * @author Martin
 *
 */
public class DriverRule implements TestRule {
	private static boolean copiedChromeDriverExe = false;
	
	private static final String PROP_DRIVER = "ju-testing-ee.selenium.driver";
	private static final String CHROME_DRIVER_EXE_PATH = "target/chromedriver.exe";
	
	private static final Logger logger = LoggerFactory.getLogger(DriverRule.class);
	
	private final WebTest testClass;
	
	private static List openDrivers = new ArrayList<>();
	private Map drivers = new LinkedHashMap<>();
	
	DriverRule(WebTest testClass) {
		this.testClass = testClass;
	}
	
	@Override
	public Statement apply(final Statement base, Description description) {
		// Handle JuTestEnv annotations
		Method method = TestUtils.getTestMethod(description);
		List> testEnvAnnos = ReflectUtils.getAnnotationsWithInfo(method, JuTestEnv.class, false, true, true);
		Collections.reverse(testEnvAnnos);
		final SystemPropertyTempSetter tempSetter = DbTestAnnotationHandler.setTestEnvProperties(testEnvAnnos);
		
		try {
			PropertyChain pc = JuUtils.getJuPropertyChain();
			
			if (this.drivers.isEmpty()) {
				// Get from the properties which drivers we should use to run the tests 
				String drivers[] = JuStringUtils.split(pc.get(PROP_DRIVER, true), ",", true);
				Assert.assertTrue(String.format("No drivers specified in property %s", DriverRule.PROP_DRIVER), drivers.length > 0);
				
				logger.debug("Initialize WebDrivers: " + Arrays.toString(drivers));
				for (String driverType : drivers) {
					WebDriver driver = null;
					
					logger.debug("Creating driver: " + driverType);
					if ("HtmlUnit".equals(driverType)) {
						boolean enableJavaScript = pc.get("ju-testing-ee.selenium.htmlUnit.enableJavascript", Boolean.class);
						driver = new HtmlUnitDriver(enableJavaScript);
					} else if ("Chrome".equals(driverType)) {
						System.setProperty("webdriver.chrome.driver", DriverRule.getChromeDriverExePath().toAbsolutePath().toString());
				        driver = new ChromeDriver();
					} else {
						throw new JuRuntimeException(String.format("Unsupported selenium driver type: %s. Check value of property %s"
								, driverType
								, PROP_DRIVER));
					}
					
					this.drivers.put(driverType, driver);
					DriverRule.openDrivers.add(driver);
				}
			}
			
			return new Statement() {
				public void evaluate() throws Throwable {
					try {
						// Run test case for with all drivers
						for (String driverType : drivers.keySet()) {
							logger.info("Running test with WebDriver " + driverType);
							testClass.driver = drivers.get(driverType);
							
							// If the evaluation fails, it will break our loop, i.e. if we want to run drivers
							// d1 and d2 and in d1, we have an exception, d2 won't be executed at all...
							base.evaluate();
						}
					} finally {
						tempSetter.close();
					}
				}
			};
		} catch (Exception ex) {
			tempSetter.close();
			throw ex;
		}
	}
	
	/**
	 * Quits all open WebDriver instances.
	 */
	public static void closeAll() {
		for (WebDriver driver : DriverRule.openDrivers) {
			driver.quit();
		}
	}
	
	private static Path getChromeDriverExePath() {
		// We'll store the chromedriver in the target directory of the current working folder
		Path chromeDriverExePath = Paths.get(DriverRule.CHROME_DRIVER_EXE_PATH);
		
		try {
			if (Files.notExists(chromeDriverExePath) || !DriverRule.copiedChromeDriverExe) {
				URL chromedriverResourceUrl = JuUrl.resource("chromedriver.exe");
				AssertUtil.assertNotNull("Couldn't find chromedriver.exe on classpath", chromedriverResourceUrl);
				
				logger.debug("Copying chromedriver.exe from resource {} to {}"
						, chromedriverResourceUrl
						, chromeDriverExePath.toAbsolutePath());
				try (InputStream is = new BufferedInputStream(chromedriverResourceUrl.openStream())) {
					Files.copy(is, chromeDriverExePath, StandardCopyOption.REPLACE_EXISTING);
				}
				
				DriverRule.copiedChromeDriverExe = true;
			}
		} catch (Exception ex) {
			throw new JuRuntimeException("Couldn't copy chromedriver.exe to " + chromeDriverExePath, ex);
		}
		
		return chromeDriverExePath;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy