package base; import java.io.File; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.ihe.gazelle.test.data_structure.LoginProfile; import net.ihe.gazelle.test.enums.Languages; import net.ihe.gazelle.test.page.MainPage; import net.ihe.gazelle.test.tool.ErrorChecker; import net.ihe.gazelle.test.tool.Loader; import org.apache.commons.io.FileUtils; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.firefox.FirefoxBinary; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.firefox.FirefoxProfile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.Assert; /** *
* Base class for every test. Contains the WebDriver and the data set. Contains the method used to restart the database and perform the test *
* *
* There are two important methods : run()
and testScenario()
.
*
* run()
is the {@literal @}Test method for every scenario class and is overriden in every child class : dataSet initializations are made there. Then super.run()
is called. In the super.run()
are called several all-time
* initializations : webDriver and database. After those initializations, super.run()
will call try{ testScenario() }
several times, until it returns successfully.
*
* BaseTest.testScenario()
is "abstract" and is destined to be overriden in every child class. In every child class, testScenario()
contains all scenario's instructions and
* assertions.
*
* This allows concentrate initializations and error filtering in the same place (BaseTest) and to have all specific code in each specific class. *
* * @author sbs * */ public abstract class BaseTest { private static WebDriver driver; private LoginProfile loginProfile; private Object[][] dataSets; private static Logger log = LoggerFactory.getLogger(BaseTest.class); public static WebDriver getDriver() { return driver; } public static void withDriver(WebDriver d) { driver = d; } public Object[][] getDataSets() { return dataSets; } public BaseTest withDataSets(Object[][] ds) { dataSets = ds; return this; } public LoginProfile getTestAccount() { return loginProfile; } public BaseTest withTestAccount(LoginProfile testAccount_) { loginProfile = testAccount_; return this; } /** * Logout inside a try */ public void safetyLogout() { try { new MainPage(driver, new LoginProfile("sballuais", "azerty", Languages.ENGLISH)).logout(); } catch ( Exception e ) { System.out.println("couldn't logout"); e.printStackTrace(); } } /** * Sleeps for a given time in milliseconds * @param millis */ public void pause(int millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { } } /** * Performs universal initializations like database restart and webDriver creation. * Calls testScenario() until it succeeds or until the max amount of trials has been reached */ public void run() { WebDriverException lastException = null; boolean properlyFinished = false; int trials = 0; final int MAX_TRIALS = Integer.parseInt(Loader.instance().config("test.max.trials")); // Get the child class name (without the whole path) String testCaseName = ""; try{ Matcher m = Pattern.compile("\\.([^.]+)$").matcher(Thread.currentThread().getStackTrace()[2].getClassName()); if(m.find()) testCaseName = m.group(1); } catch (Exception e) { testCaseName = "No-name"; } while(trials < MAX_TRIALS && !properlyFinished) { try { // SETUP initDatabase(); initWebDriver(); checkForError(); // EXECUTION log.info("Executing the test : " + testCaseName); for(Object[] ds : dataSets) testScenario(ds); properlyFinished = true; } catch (WebDriverException e) { if(Loader.instance().config("Debug").equals("true")) e.printStackTrace(); lastException = e; log.warn("There were non-managed WebDriverException during the execution." + " Trying again to run this test (" + trials + "/" + MAX_TRIALS + ")"); trials++; } catch (AssertionError e) { log.warn("Test failed"); closeWebDriver(); throw e; } finally { // TEAR DOWN try { closeWebDriver(); } catch(Exception ex) {log.warn("couldn't close the driver");} } } if(!properlyFinished) { if(lastException != null) { lastException.printStackTrace(); Assert.fail("The test run didn't finish without exception"); } } } public void takeDebugScreenshot() { File scrFile = ((TakesScreenshot)getDriver()).getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(scrFile, new File("./screen.png")); } catch (IOException e) { e.printStackTrace(); } } /** * Destined to be overriden in every child test class. testScenario() is called by run(). It contains all the scenario code. * @param ds TODO */ public void testScenario(Object[] ds) { } /** * Calls for database restore and jboss restart. * Calls for Command.Database.Restore, it it takes more than 500s, calls for Command.Jboss.Restart * Commands are configurable in config.properties * Returns when command returned or when timed out (500 for the database restore + 200 for the jboss restart. */ public void initDatabase() { if(Loader.instance().config("Auto.DataBase.Restore").equals("true")) { log.info("Restoring database..."); try { executeCommand(Loader.instance().config("Command.Database.Restore"), 500); log.info("Database restored"); } catch (Exception e) { log.error("Error during the call of the restoration command, restarting jboss"); try { executeCommand(Loader.instance().config("Command.Jboss.Restart"), 200); log.info("Jboss restarted"); } catch(Exception ex) { log.error("Couldn't restart jboss"); } e.printStackTrace(); } } } /** * Initialize the webDriver according to options set in config.properties. */ public void initWebDriver() { WebDriver result; FirefoxProfile firefoxProfile = new FirefoxProfile(); firefoxProfile.setPreference("browser.download.folderList", 2); firefoxProfile.setPreference("browser.download.manager.showWhenStarting", false); // The download directory firefoxProfile.setPreference("browser.download.dir", Loader.instance().config("firefox.download.directory")); // The list of MIME types firefox will automatically download without showing a prompt window firefoxProfile.setPreference("browser.helperApps.neverAsk.saveToDisk", "text/csv" + ",application/vnd.ms-excel" + ",application/pdf" + ",application/xml" + ",application/zip" + ",text/plain" + ",application/vnd.oasis.opendocument.text" + ",application/vnd.oasis.opendocument.spreadsheet" + ",application/vnd.oasis.opendocument.presentation" + ",application/vnd.oasis.opendocument.graphics" + ",application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" + ",application/vnd.ms-powerpoint" + ",application/msword" + ",application/vnd.openxmlformats-officedocument.wordprocessingml.document"); if (Loader.instance().config("headless").equals("true")) { FirefoxBinary firefoxBinary = new FirefoxBinary(); firefoxBinary.setEnvironmentProperty("DISPLAY", System.getProperty("Importal.xvfb.id", ":1")); result = new FirefoxDriver(firefoxBinary, firefoxProfile); } else { result = new FirefoxDriver(firefoxProfile); } result.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); driver = result; } public void closeWebDriver() { driver.close(); driver = null; } private static void executeCommand(String command, long timeoutInSeconds) throws Exception { ExecutorService service = Executors.newSingleThreadExecutor(); Process process = Runtime.getRuntime().exec(command); try { Callable