/* +----------------------------------------------------------------------+ | Class: CLauncher | | | | Developper: Eric Gavaldo (eric.gavaldo@xqual.com) | | Version: 1.13 | | License: LGPL (http://www.gnu.org/licenses/lgpl.html) | +----------------------------------------------------------------------+ */ package com.xqual.xlauncher.selenium_html; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Vector; import com.xqual.xagent.launcher.CExecutionStep; import com.xqual.xagent.launcher.CLauncher; import com.xqual.xagent.launcher.CReturnStatus; import com.xqual.xagent.launcher.runner.CRunner; import com.xqual.xagent.launcher.runner.IRunner; import com.xqual.xcommon.CAttribute; import com.xqual.xcommon.IConstantsResults; import com.xqual.xcommon.type.CParam; import com.xqual.xcommon.type.CParamParsingException; import com.xqual.xcommon.utils.CFileUtils; import com.xqual.xcommon.utils.CUtils; /** * The CLauncherImpl implementation of ILauncher for Selenium HTML. * @author egavaldo */ public class CLauncherImpl extends CLauncher implements IConstantsResults { // +==============================================================+ // | Attributes | // +==============================================================+ static final String TRACE_HEADER = "{selenium html } "; // parameters impacting executing at run time set by the test operator private String testRootPath; private String javaInstallPath; private String seleniumServerJarPath; private String seleniumServerOptions; private String browser; private String domainUrl; private String attachmentsPath; private File workingDir; private File seleniumServerReportFile; private File seleniumServerTraceFile; private static final String JAVA_INTERPRETER_EXE = CUtils.getExecutableName("java"); // +==============================================================+ // | Constructors | // +==============================================================+ public CLauncherImpl() { super(TRACE_HEADER); } // +==============================================================+ // | Methods | // +==============================================================+ @Override public CReturnStatus initialize(int sutId, String sutName, String sutVersion) { setSutDetails(sutId, sutName, sutVersion); // check the configuration sent by the manager printConfiguration(); Vector executionSteps = new Vector(); try { // retrieve the parameters we need testRootPath = getStringParamValue("General", "Test root path"); // i.e. C:/test_repository/tests/selenium/html javaInstallPath = getStringParamValue("Selenium - Html", "Java install path"); // i.e. C:/Program Files/Java/jdk1.6.0_17 seleniumServerJarPath = getStringParamValue("Selenium - Html", "Server JAR path"); // i.e. Y:/Externals/Selenium-1.0/selenium-remote-control-1.0.1/selenium-server-1.0.1/selenium-server.jar seleniumServerOptions = getStringParamValue("Selenium - Html", "Server options"); browser = getStringParamValue("Selenium - Html", "Browser"); // i.e. iehta (it can also firefox or chrome) domainUrl = getStringParamValue("Selenium - Html", "Domain URL"); // i.e. http://www.xqual.com attachmentsPath = getStringParamValue("Attachments", "Additional attachments path"); // i.e. C:/test_repository/tests/selenium/attachments } catch (CParamParsingException e) { traceln(LOG_PRIORITY_SEVERE, "parsing error during initialization"); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception during initialize: " + e.getMessage())); return new CReturnStatus(RESULT_FAILURE, executionSteps); } return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override public CReturnStatus preRun(int testId, String testPath, String testName, Vector attributes, String additionalInfo) { traceln(LOG_PRIORITY_INFO, "preRun testId=" + testId + " testPath=" + testPath + " [" + testName + "]..."); Vector executionSteps = new Vector(); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override public CReturnStatus run(int testId, String testPath, String testName, int testcaseId, int testcaseIndex, String testcaseName, Vector params, String additionalInfo) { traceln(LOG_PRIORITY_INFO, "run testId=" + testId + " testPath=" + testRootPath + "/" + testPath + "/" + testName + " testcaseIndex=" + testcaseIndex + "..."); Vector executionSteps = new Vector(); workingDir = new File(testRootPath); // parent folder of all the test classes seleniumServerReportFile = new File("selenium_server_report.html"); if (seleniumServerReportFile.exists()) seleniumServerReportFile.delete(); try { seleniumServerReportFile.createNewFile(); } catch (IOException e) { traceln(LOG_PRIORITY_SEVERE, "Could not create file \"selenium_server_report.html\"..."); } seleniumServerTraceFile = new File("selenium_server_traces.txt"); if (seleniumServerTraceFile.exists()) seleniumServerTraceFile.delete(); try { seleniumServerTraceFile.createNewFile(); } catch (IOException e) { traceln(LOG_PRIORITY_SEVERE, "Could not create file \"selenium_server_traces.txt\"..."); } if (attachmentsPath.length()>0) { File attachmentsPathFolder = new File(attachmentsPath); if (attachmentsPathFolder.exists() && attachmentsPathFolder.isDirectory()) { String[] children = attachmentsPathFolder.list(); for (int i = 0; i < children.length; i++) { boolean returnCode = CFileUtils.deleteFile(new File(attachmentsPathFolder, children[i])); if (!returnCode) { traceln(LOG_PRIORITY_SEVERE, "Could not delete file " + new File(attachmentsPathFolder, children[i]) + "..."); } } } } // +------------------------------------+ // | Run the Selenium server // +------------------------------------+ // if there is already a selenium server running that's not a problem has 2 server cannot listen on the same port this will fail nicely CRunner seleniumServer = new CRunner("[Selenium Server] ", CFileUtils.quoteFilePath(javaInstallPath + "/bin/" + JAVA_INTERPRETER_EXE) + " -jar " + CFileUtils.quoteFilePath(seleniumServerJarPath) + " " + seleniumServerOptions + " " + //(trustAllSSLCertificates ? "-trustAllSSLCertificates " : "") + //(userExtensions != null && userExtensions.length()>0 ? "-userExtensions \"" + userExtensions + "\" " : "") + "-htmlSuite \"*" + browser + "\" " + domainUrl + " " + // do not double-quote the domain URL as the URL would be detected as malformed by selenium on Linux CFileUtils.quoteFilePath(testRootPath + "/" + testPath + "/" + testName + ".html") + " " + CFileUtils.quoteFilePath(seleniumServerReportFile.getAbsolutePath()) + " " + "-log " + CFileUtils.quoteFilePath(seleniumServerTraceFile.getAbsolutePath()), workingDir); short result = seleniumServer.requestAction(IRunner.START_PROCESS, IRunner.WAIT_END_OF_EXECUTION); System.err.println("- - - - - RESULT: " + result); // +------------------------------------+ // | Run the Selenium server // +------------------------------------+ seleniumServer.killProcess(); // selenium returns 1 in case of success and 2 in case of failure // it retuns also 2 when it crashed (we detect this a bit later when there is no result file) if (result != 1 && result != 2) { System.err.println("- - - - - UNEXPECTED RETURN"); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "selenium server refused to start!")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } // +----------------------------------------------+ // | Add the output console and report to the test // +----------------------------------------------+ if (seleniumServerTraceFile.exists()) addAttachment(seleniumServerTraceFile); if (seleniumServerReportFile.exists()) addAttachment(seleniumServerReportFile); if (attachmentsPath.length()>0) { File attachmentsPathFolder = new File(attachmentsPath); if (attachmentsPathFolder.exists() && attachmentsPathFolder.isDirectory()) { String[] children = attachmentsPathFolder.list(); for (int i = 0; i < children.length; i++) { addAttachment(new File(attachmentsPathFolder, children[i])); } } } return parseResultFile(executionSteps); // even when succeeding, it looks like selenium exits with return code > 0 } @Override public CReturnStatus postRun(int testId, String testPath, String testName) { traceln(LOG_PRIORITY_INFO, "postRun testId=" + testId + " testPath=" + testPath + ":" + testName + "..."); Vector executionSteps = new Vector(); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "postRun: succeeded")); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } @Override public CReturnStatus terminate() { Vector executionSteps = new Vector(); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "Terminate")); return new CReturnStatus(RESULT_SUCCESS, executionSteps); } // +--------------------------+ // ¦ Utilities ¦ // +--------------------------+ private CReturnStatus parseResultFile(Vector executionSteps) { // length() trick: it's necessary as there sounds to be a bug in java where exists() always // returns false or true if the file in mapped on a remote network drive if (!seleniumServerReportFile.exists() || seleniumServerReportFile.length() <= 1) { traceln(LOG_PRIORITY_SEVERE, "Result file not found!"); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "selenium server probably crashed!")); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "run: report not found!")); return new CReturnStatus(RESULT_FAILURE, executionSteps); } else { executionSteps.add(new CExecutionStep(RESULT_NOT_EXECUTED, "run: result file found")); } String line; boolean errorDetected = false; try { FileInputStream fileInputStream = new FileInputStream(seleniumServerReportFile); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream)); while ((line = bufferedReader.readLine()) != null) { line = line.trim(); System.out.println(">" + line); if (line.startsWith("result:")) { line = bufferedReader.readLine().trim(); String globalResult = line.substring(4, line.length()-5); if (globalResult.equalsIgnoreCase("passed")) { executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "Result: " + globalResult)); } else { executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Result: " + globalResult)); errorDetected = true; } } else if (line.startsWith("totalTime:")) { line = bufferedReader.readLine().trim(); String totalTime = line.substring(4, line.length()-5); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "totalTime: " + totalTime)); } else if (line.startsWith("numTestTotal:")) { line = bufferedReader.readLine().trim(); String numTestTotal = line.substring(4, line.length()-5); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "numTestTotal: " + numTestTotal)); } else if (line.startsWith("numTestPasses:")) { line = bufferedReader.readLine().trim(); String numTestPasses = line.substring(4, line.length()-5); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "numTestPasses: " + numTestPasses)); } else if (line.startsWith("numTestFailures:")) { line = bufferedReader.readLine().trim(); int numTestFailures = Integer.parseInt(line.substring(4, line.length()-5)); executionSteps.add(new CExecutionStep(numTestFailures > 0 ? RESULT_FAILURE: RESULT_SUCCESS, "numTestFailures: " + numTestFailures)); } else if (line.endsWith("status_passed\">")) { line = bufferedReader.readLine().trim(); String[] array = line.split(">"); String testName = array[1].substring(1, array[1].length()-9); executionSteps.add(new CExecutionStep(RESULT_SUCCESS, "passed: " + testName)); } else if (line.endsWith("status_failed\">")) { line = bufferedReader.readLine().trim(); String[] array = line.split(">"); String testName = array[1].substring(1, array[1].length()-9); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "failed: " + testName)); } else { //traceln(LOG_PRIORITY_SEVERE, "unknown tag!"); } } bufferedReader.close(); fileInputStream.close(); } catch (Exception e) { traceln(LOG_PRIORITY_SEVERE, "exception whle parsing the result file: " + e); executionSteps.add(new CExecutionStep(RESULT_FAILURE, "Exception while parsing the result file: " + e)); errorDetected = true; } if (errorDetected) { return new CReturnStatus(RESULT_FAILURE, executionSteps); } else{ return new CReturnStatus(RESULT_SUCCESS, executionSteps); } } }