DDTTestRunner.java Source code

Java tutorial

Introduction

Here is the source code for DDTTestRunner.java

Source

import org.openqa.selenium.WebElement;

import javax.xml.transform.TransformerException;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Hashtable;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

/**
 * Created by BeyMelamed on 2/13/14.
 * Selenium Based Automation Project
 *
 * =============================================================================
 * Copyright 2014 Avraham (Bey) Melamed.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 *
 * Description
 * <p>
 *    The driver that interprets the input source, activates, interrogates and validates the AUT
 *    The processTestItems method is the main loop 'where the rubber meets the road'
 *    Note various done, fail, pass, skip counters - there are three sets of those:
 *    Instance level - these represent the count for a given test runner instance (a collection of steps at a given level in the hierarchy)
 *    Class level -    there represent the counters for an entire test session
 *    These come in two flavors (as the user may have set some non-verification steps as 'do not report me'
 *    rpt...      - This is the reportable items count
 *    non rpt...  - This flavor counts all steps, reported and not reported steps count
 * <p/>
 * When      |Who            |What
 * ==========|===============|========================================================
 * 01/13/14  |Bey            |Initial Version
 * ==========|===============|========================================================
 */
public class DDTTestRunner {

    public enum TestEventType {
        INIT, INFO, PASS, FAIL, SKIP
    }

    // ======================================= Class properties section =====================================
    private static DDTReporter reporter;
    private static Long nSessionSteps = 0L;
    private static Long nReportedSessionSteps = 0L;
    private static boolean shouldQuitTestSession;
    private static DDTTestContext varsMap;
    private static Hashtable<String, WebElement> elementsMap;

    // The test session variables hashtable is maintained by DDTTestRunner instance.
    private static Hashtable<String, TestItem> currentTestItem = new Hashtable<String, TestItem>();

    // done, pass, fail, skip counters - on the Test Session level - reset when a new TestRunner session is launched
    private static int[] tsCounters = { 0, 0, 0, 0 };

    // done, pass, fail, skip counters - on the TestRunner instance level - reset when a new TestRunner instance is created
    private static int[] trCounters = { 0, 0, 0, 0 };

    // done, pass, fail, skip counters - on the Reporter instance level - reset when session is initiated and after a Reporter generates a report
    private static int[] rptCounters = { 0, 0, 0, 0 };

    // Most Recent Web element to be propagated across testItem instances for steps requiring previously found 'anchor' elements.
    // Static as it may be set by one instance and accessed by another instance of TestRunner
    private static WebElement mrElement;

    private static String sessionFailBlurb;
    private static String sessionPassBlurb;

    private static int nDone() {
        return trCounters[0];
    }

    private static int nPass() {
        return trCounters[1];
    }

    private static int nFail() {
        return trCounters[2];
    }

    private static int nSkip() {
        return trCounters[3];
    }

    private static int nRptDone() {
        return rptCounters[0];
    }

    private static int nRptPass() {
        return rptCounters[1];
    }

    private static int nRptFail() {
        return rptCounters[2];
    }

    private static int nRptSkip() {
        return rptCounters[3];
    }

    private static void setNextStep() {
        nSessionSteps++;
    }

    private static void setNextReportingStep() {
        nReportedSessionSteps++;
    }

    public static void setSessionFailBlurb(String value) {
        sessionFailBlurb = value;
    }

    public static String getSessionFailBlurb() {
        if (isBlank(sessionFailBlurb))
            setSessionFailBlurb("");
        return sessionFailBlurb;
    }

    public static void setSessionPassBlurb(String value) {
        sessionPassBlurb = value;
    }

    public static String getSessionPassBlurb() {
        if (isBlank(sessionPassBlurb))
            setSessionPassBlurb("");
        return sessionPassBlurb;
    }

    // ======================================= Class logic section =====================================

    public static void endSession() {
        if (isNotBlank(getSessionFailBlurb()))
            runFailed(getSessionFailBlurb());
        testEnded(getSessionPassBlurb());
    }

    private static void runFailed(String s) {
        System.out.println(s);
        System.exit(-1);
    }

    private static void testEnded(String s) {
        System.out.println(s);
        System.exit(0);
    }

    /**
     *
     * @param args [0] = provider type, [1] provider source, [2] test steps container (optional)
     */
    public static void runOn(String[] args) throws Throwable {
        // Populate the instance's dictionary with current date variables
        addVariable("datevars", "%date%");

        String[][] testItemStrings = new String[0][0];

        try {

            // Test Items Strings provider - String[n][] where each of the n rows is a collection of strings making up a TestItem instance.
            // stringProviderSpecs contains information about the test item strings provider - err out if it is invalid.
            TestStringsProviderSpecs stringProviderSpecs = new TestStringsProviderSpecs(args);
            if (stringProviderSpecs.isSetupValid()) {

                // With valid stringProviderSpecs, attempt to get the strings making up the new test and err out if not successful
                testItemStrings = TestStringsProvider.provideTestStrings(stringProviderSpecs,
                        DDTSettings.Settings().dataFolder());
                if (testItemStrings.length > 0) {
                    // A new test items aggregate
                    TestItem.TestItems testItems = new TestItem.TestItems();
                    // assemble TestItem[] array in the new aggregate
                    testItems.setItems(TestItem.assembleTestItems(testItemStrings));
                    // start a new test runner instance with the test items aggregate instance
                    DDTTestRunner runner = new DDTTestRunner();

                    runner.setTestItems(testItems);
                    // let the runner process its test items.
                    runner.processTestItems();
                } // if some test strings were provided
                else {
                    System.out.println("Failed to get test item strings from Test Strings Provider!");
                }
            } // if valid specs
            else {
                System.out.println("Invalid Test Strings Provider - " + stringProviderSpecs.getErrors());
            }
        } catch (Exception e) {
            System.out.println("Failed to 'runOn' default TestItemsProvider " + e.getMessage().toString());
        }
    }

    /**
     * Invoke a Test Runner using the defaults specified by the ddt.properties file (or the hard coded defaults)
     * @return
     */
    public static void invokeDefaults() {
        DDTSettings.reset();

        // Use the default test items provider
        try {
            // Get the initial test items specified in the properties file or the command line
            String tmp[] = DDTSettings.Settings().inputSpecsArrayWithDataFolder();
            runOn(tmp);
            generateReportIfNeeded();
            if (Driver.isInitialized()) {
                System.out.println("End of Test Session - Closing Driver");
                Driver.getDriver().close();
            }
        } catch (Throwable ex) {
            System.out.println("Exception encountered running defaults: " + ex.getMessage().toString());
        }
    }

    /**
     * This is called from the generateReport vocabulary entry
     * @param description    - Optional descripton of the report
     * @param emailBody      - Optional additional text the user set on this step to be displayed in the body of the email message to the recipients
     * @throws IOException
     * @throws TransformerException
     */
    public static void generateReport(String description, String emailBody)
            throws IOException, TransformerException {
        getReporter().resetCounters(nRptDone(), nRptPass(), nRptFail(), nRptSkip());
        getReporter().generateReport(description, emailBody);
    }

    /**
     *
     * @param testItem  - The current item at the current level
     * @param addOrRemove - Indicator whether the item should be added to the hashtable (do for each item at a given level) or removed from it (end of test case)
     */
    public static void maintainCurrentTestItem(TestItem testItem, String addOrRemove) {
        String key = testItem.getLevelKey();

        TestItem tmp = currentTestItem.get(key);
        if (tmp instanceof TestItem) {
            // Upon starting a new level, make sure the current testItem is reflected at that level - Need to remove the current item
            // Upon ending a level - Need to remove the current item
            currentTestItem.remove(key);
        }
        if (addOrRemove.equalsIgnoreCase("add")) {
            currentTestItem.put(key, testItem);
        }
    }

    public static void resetRptCounters() {
        rptCounters = new int[] { 0, 0, 0, 0 };
    }

    public static DDTTestContext getVarsMap() {
        if (varsMap == null)
            setVarsMap(new DDTTestContext());
        return varsMap;
    }

    public static void setVarsMap(DDTTestContext aMap) {
        varsMap = aMap;
    }

    public static void addVariable(String key, String value) {
        String result = "";
        try {
            if ((getVarsMap().get(key) != null))
                getVarsMap().remove(key);

            // Consider the special case of date variables used for resetting date-specific system variables
            if (value.toString().toLowerCase().startsWith("%date")
                    && (value.toString().toLowerCase().endsWith("%"))) {
                try {
                    DDTDate referenceDate = new DDTDate();
                    referenceDate.resetDateProperties(value.toString(), getVarsMap());
                    if (referenceDate.hasException())
                        result = referenceDate.getException().getMessage().toString();
                    else
                        result = referenceDate.getComments();
                } catch (Exception e) {
                    result = "Error encountered in setting date variables: " + e.getCause().toString();
                }
            } else {
                getVarsMap().put(key.toLowerCase(), value);
                result = "Variable " + Util.sq(key.toLowerCase()) + " (re)set in the variables map to "
                        + Util.sq((value instanceof String) ? value : value.toString());
            }

        } catch (Exception e) {
            result = e.getCause().toString();
        } finally {
            System.out.println(result);
        }
    }

    public static void setElementsMap(Hashtable<String, WebElement> aMap) {
        elementsMap = aMap;
    }

    public static Hashtable<String, WebElement> getElementsMap() {
        if (elementsMap == null)
            setElementsMap(new Hashtable<String, WebElement>());
        return elementsMap;
    }

    public static void addElement(String key, WebElement value) {
        String result = "";
        String tmp = key.toLowerCase();
        try {
            if ((getElementsMap().get(tmp) != null))
                getElementsMap().remove(tmp);

            getElementsMap().put(tmp, value);
            result = "Element " + Util.sq(key.toLowerCase()) + " (re)set in the Elements map to "
                    + Util.sq(value.toString());
        } catch (Exception e) {
            result = e.getCause().toString();
        } finally {
            System.out.println(result);
        }
    }

    /**
     * Retrieve a previously stored element from the Elements Map of the test session
     * @param key
     * @return Web Element previously stored in the Elements Map
     */
    public static WebElement getElement(String key) {
        WebElement result = null;
        try {
            result = getElementsMap().get(key.toLowerCase());
        } catch (Exception e) {
            System.out.println("Web Element: " + Util.sq(key) + " not found in the Elements Map.");
        } finally {
            return result;
        }
    }

    public static int nSessionDone() {
        return tsCounters[0];
    }

    public static int nSessionPass() {
        return tsCounters[1];
    }

    public static int nSessionFail() {
        return tsCounters[2];
    }

    public static int nSessionSkip() {
        return tsCounters[3];
    }

    public static void setNextReportingStep(String actionName) {
        if (isReportableAction(actionName))
            setNextReportingStep();
        setNextStep();
    }

    public static Long currentSessionStep() {
        return nSessionSteps;
    }

    public static Long currentReportedSessionStep() {
        return nReportedSessionSteps;
    }

    public static boolean isReportableAction(String actionName) {
        return DDTSettings.isReportableAction(actionName);
    }

    public static DDTReporter getReporter() {
        if (reporter == null) {
            // DDTReporter.DDTXmlReporter reporter = new DDTReporter.DDTXmlReporter();
            reporter = new DDTReporter();
        }
        return reporter;
    }

    public static boolean shouldGenerateReport() {
        return getReporter().shouldGenerateReport();
    }

    /**
     * Create an array of various elements describing the context in which the test session ran
     * @return
     */
    public static String[][] getEnvironmentItems() {
        String[][] result = new String[5][2];
        StringBuilder sb = new StringBuilder("Environment: ");
        result[0][0] = "os";
        result[0][1] = "OS Name: " + System.getProperty("os.name") + ", " + "OS Version: "
                + System.getProperty("os.version") + ", Browser: " + DDTSettings.Settings().browserName();

        result[1][0] = "env";
        result[1][1] = "Country: " + System.getProperty("user.country") + ", Language: "
                + System.getProperty("user.language") + ", Time Zone: " + System.getProperty("user.timezone");

        result[2][0] = "java";
        result[2][1] = "Version: " + System.getProperty("java.version") + ", Home: "
                + System.getProperty("java.home");

        result[3][0] = "user";
        result[3][1] = "Name: " + System.getProperty("user.name") + ", Home: " + System.getProperty("user.home")
                + ", Project Home: " + System.getProperty("user.dir");
        // The last element is left blank on purpose - to be used by DDTReported or other modules
        return result;
    }

    /**
     * JSON represetation of the environment
     * @return
     */
    public static String getEnvironmentItemsAsJSON() {
        String[][] items = getEnvironmentItems();
        StringBuilder sb = new StringBuilder("");
        for (int i = 0; i < 4; i++) {
            sb.append(Util.dq(items[i][0]) + ":" + (Util.dq(Util.jsonify(items[i][1]))) + (i < 3 ? "," : ""));
        }
        return Util.dq("environment") + ":{" + sb.toString() + "}";
    }

    public static String getSessionStatsAsJSON() {

        StringBuilder sb = new StringBuilder("");
        sb.append(Util.dq("passedSteps") + ":" + String.valueOf(nPass()) + ",");
        sb.append(Util.dq("failedSteps") + ":" + String.valueOf(nFail()) + ",");
        sb.append(Util.dq("skippedSteps") + ":" + String.valueOf(nSkip()) + ",");
        sb.append(Util.dq("totalSteps") + ":" + String.valueOf(nDone()) + ",");
        sb.append(Util.dq("sessionDuration") + ":" + Util.dq(getReporter().sessionDurationString()));
        return Util.dq("stats") + ":{" + sb.toString() + "}";
    }

    public static String getSessionSummaryAsJSON() {
        return "{" + getEnvironmentItemsAsJSON() + "," + getSessionStatsAsJSON() + "}";
    }

    public static void reportSessionSummaryAsJSON() {
        String fileName = DDTSettings.asValidOSPath(getReporter().sessionTestsFolderName(), true) + File.separator
                + "sessionsummary.json";
        Util.fileWrite(fileName, getSessionSummaryAsJSON());
    }

    /**
     * Generate the report only if it was not generated yet and there are some steps to report on.
     */
    public static void generateReportIfNeeded() {
        if (shouldGenerateReport())
            try {
                getReporter().generateReport("Final Report", "");
            } catch (Exception e) {
                e.printStackTrace();
            }
    }

    // ======================================= Instance properties =====================================

    private int level = 0;
    private Long parentStepNumber; // For all but level 0 items this is > 0;
    private String errors = "";

    private String inputSpecs;
    private TestItem.TestItems testItems;

    public void setParentStepNumber(Long value) {
        parentStepNumber = value;
    }

    public Long getParentStepNumber() {
        if (parentStepNumber == null)
            setParentStepNumber(0L);
        return parentStepNumber;
    }

    public DDTTestRunner() {
        resetTrCounters();
    }

    public void setInputSpecs(String value) {
        inputSpecs = value;
    }

    public String getInputSpecs() {
        if (isBlank(inputSpecs)) {
            setInputSpecs(DDTSettings.Settings().inputSpecs());
        }
        return inputSpecs;
    }

    public int nItems() {
        return testItems.getSize();
    }

    private void resetTrCounters() {
        trCounters = new int[] { 0, 0, 0, 0 };
    }

    private void incrementDone() {
        tsCounters[0]++;
        trCounters[0]++;
        rptCounters[0]++;
    }

    private void incrementPass() {
        tsCounters[1]++;
        trCounters[1]++;
        rptCounters[1]++;
    }

    private void incrementFail() {
        tsCounters[2]++;
        trCounters[2]++;
        rptCounters[2]++;
    }

    private void incrementSkip() {
        tsCounters[3]++;
        trCounters[3]++;
        rptCounters[3]++;
    }

    private void setError(String value) {
        errors = value;
    }

    public void setLevel(int aNumber) {
        level = aNumber;
    }

    public int getLevel() {
        return level;
    }

    public void setTestItems(TestItem.TestItems items) {
        testItems = items;
    }

    public boolean failed() {
        return (nFail() > 0 || (!isBlank(errors)));
    }

    public boolean passed() {
        return !failed();
    }

    public String getErrors() {
        return errors;
    }

    /**
     * Executes each of the active TestItem instances in the current TestRunner instance.
     */
    public void processTestItems() throws InvocationTargetException, IllegalAccessException {
        boolean shouldQuitTestCase = false;
        String pad = "";
        String quitBlurb = "";
        int stepNo = 0;
        // testItem's PostTestPolicy may set stepsToSkip to a positive number of steps to skip (
        // when a test fails, passes or when skipping steps unconditionally)
        int stepsToSkip = 0;

        if (testItems != null && nItems() > 0) {
            for (TestItem testItem : testItems.getItems()) {
                stepNo++;

                // Skip empty rows in the data source
                if ((testItem == null) || testItem.isEmpty())
                    continue;

                // Allow for developer's debugging
                if (testItem.shouldDebug()) {
                    // Place a breakpoint on the next statement...
                    boolean isDebugging = true;
                }

                // Perform some initialization tasks...
                testItem.setLevel(getLevel());
                testItem.setParentStepNumber(getParentStepNumber());
                testItem.setParentTestItem(testItems.getParentItem());

                testItem.initialize(stepNo);

                // Maintain the current test item list
                maintainCurrentTestItem(testItem, "add");

                // potentially, set the MostRecentlyUsed element
                if (mrElement instanceof WebElement)
                    testItem.setMrElement(mrElement);

                // Add this step to the reporter and maintain reporter's first and last reporting and session numbers for this reporting session
                if (getReporter().firstSessionStep() < 1L)
                    getReporter().setFirstSessionStep(currentSessionStep()); // Done only once
                getReporter().setLastSessionStep(currentSessionStep()); // Keeps incrementing

                // If any steps to skip (due to some prior test item's PostTestPolicy) - set the step to non-active and add a comment to this effect.
                if (stepsToSkip > 0) {
                    testItem.setActive("no");
                    stepsToSkip--;
                    testItem.addComment(
                            "Skipped due to PostTestPolicy of prior step " + stepsToSkip + " more steps to skip.");
                    System.out.println("Skipping Item Id: " + testItem.getId() + ", Description: "
                            + testItem.getDescription() + " (Skipped due to PostTestPolicy of prior step - "
                            + stepsToSkip + " more steps to skip.)");
                }

                // Process active or inactive steps as needed
                if (testItem.isActive()) {
                    try {
                        Vocabulary.invoke(testItem);
                    } catch (NullPointerException e) {
                        if (!testItem.hasException())
                            testItem.setException(e);
                    } catch (Exception e) {
                        if (!testItem.hasException())
                            testItem.setException(e);
                    } finally {

                        if (isReportableAction(testItem.getAction())) {
                            getReporter().addDDTest(new DDTReportItem(testItem));
                            if (getReporter().firstReportStep() < 1L)
                                getReporter().setFirstReportStep(currentReportedSessionStep()); // Done only once - reported steps
                            getReporter().setLastReportStep(currentReportedSessionStep()); // Keeps incrementing - reported steps
                        }

                        incrementDone();
                    }

                    // If settings indicates pausing after a UI step, do it
                    if (!isBlank(testItem.getLocSpecs()))
                        pause();

                    if (isBlank(pad))
                        pad = testItem.pad();

                    if (testItem.isFailure()) {
                        incrementFail();
                        testItem.addFailEvent("Step Failed");
                        // Handle screen shots based on settings - but only if this is a UI test
                        if (testItem.isUITest()) {
                            if (DDTSettings.Settings().takeImageOnFailedStep() && Driver.isInitialized()) {
                                String imageFileOrError = Util.takeScreenImage(Driver.getDriver(), "",
                                        testItem.getId());
                                if (!(imageFileOrError.toLowerCase().contains("error:"))) {
                                    // Add it to the error - not Comments as error has occured
                                    testItem.setScreenShotFileName(imageFileOrError);
                                    testItem.addError(
                                            "Screen Image " + testItem.getScreenShotFileNameAsHtml() + " taken!");
                                }
                            } else
                                testItem.addComment(
                                        "'Screen Image on step failure' feature is turned off or Driver not initialized - no image taken.  To turn feature on, change the relevant Settings' (takeImageOnFailedStep) property");
                        }
                    } else {
                        testItem.addPassEvent("Step Passed");
                        incrementPass();
                        if (testItem.getElement() instanceof WebElement) {
                            // Preserve the most recent web element
                            mrElement = testItem.getElement();
                        }
                    }

                    // Report the current step
                    testItem.setCurrTime();
                    System.out.println(testItem.report());
                    // Consider Test and Session termination
                    shouldQuitTestCase |= testItem.shouldQuitTestCase();
                    shouldQuitTestSession |= testItem.shouldQuitTestSession();
                    stepsToSkip = testItem.getStepsToSkip();
                } // if testItem.active
                else {
                    testItem.addSkipEvent("Step Skipped");
                    incrementSkip();
                }
                // Consider Termination at the test case or test session level
                if (shouldQuitTestCase || shouldQuitTestSession) {
                    String ptpBlurb = "";
                    if (testItem.getPostTestPolicy() instanceof PostTestPolicy) {
                        ptpBlurb = "Post Test Policy: " + Util.sq(testItem.getPostTestPolicy().toString());
                    }

                    if (shouldQuitTestCase)
                        quitBlurb = "Level " + testItem.getLevel()
                                + " - Test Case Terminated at test item with ID: " + testItem.getId();

                    if (shouldQuitTestSession) {
                        quitBlurb += (isBlank(quitBlurb)
                                ? ("Level " + testItem.getLevel()
                                        + " - Test Session Terminated at test item with ID: " + testItem.getId())
                                : " (Test Session Terminated as well)");
                    }

                    quitBlurb += (isBlank(ptpBlurb) ? "" : " - " + ptpBlurb);

                    if (failed()) {
                        testItem.addError(quitBlurb);
                        setError("Test Case failed at test item with ID: " + testItem.getId()
                                + (isBlank(ptpBlurb) ? "" : " - " + ptpBlurb));
                    } else
                        testItem.addComment(quitBlurb);

                    break;
                } // Should Quit Test or Session

                maintainCurrentTestItem(testItem, "remove");
            } // For all test items.

            /**
             * Create a JSON file of the items that ran at this level - one JSON file for each level
             */
            testItems.reportAsJSON();

            // Test Case completed - take action based on level (level 0 means we are done)

            // Test case level stats
            String str;
            if (nFail() > 0)
                str = "Test Failed (level " + getLevel() + "): " + nFail() + " test step(s) out of " + nDone()
                        + " step(s) failed (" + nSkip() + " step(s) skipped)\n";
            else {
                str = "Test Passed (level " + getLevel() + "): " + nPass() + " test step(s) out of " + nDone()
                        + " step(s) passed (" + nSkip() + " step(s) skipped)\n";
            }

            str += quitBlurb;

            System.out.println(pad + str);

        }

        // Test session level stats
        if (getLevel() < 1) {
            // Final Report ...
            reportSessionSummaryAsJSON();
            if (nSessionFail() > 0) {
                //This quits the process... - no return from here...
                setSessionFailBlurb("Test Session Failed: " + nSessionFail() + " test step(s) out of "
                        + nSessionDone() + " step(s) failed (" + nSessionSkip() + " step(s) skipped)\n");
            } else {
                //This quits the process... - no return from here...
                setSessionPassBlurb("Test Session Pass: " + nSessionPass() + " test step(s) out of "
                        + nSessionDone() + " steps passed (" + nSessionSkip() + " step(s) skipped)\n");
            }
        }
    }

    /**
     * The starting point of the test run - use the args array or use defaults from DDTSettings.Settings()
     * @param args
     */
    public static void main(String[] args) {
        DDTSettings.reset();
        DDTTestRunner inst = new DDTTestRunner();
        String[] tmp;
        // args[] should be a ':' delimited string indicating the type of source input
        // A delimted string indicating the type of input used (at present File and Inline are the two options) followed by one or two other values
        // Example 1: File;DDTRoot.xls;Root
        // Example 2: Inline;InputGeneratorClassName;rootMethodName
        if (args.length == 1) {
            tmp = args[0].split(TestStringsProviderSpecs.SPLITTER);
        } else {
            // Use the default input
            tmp = DDTSettings.Settings().inputSpecsArray();
        }

        try {
            // Get the initial test items specified in the properties file or the command line
            runOn(tmp);
        } catch (Exception ex) {
            System.out.println(ex.getMessage().toString());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {
            if (Driver.isInitialized()) {
                System.out.println("End of Test Session - Closing Driver");
                Driver.getDriver().close();
            }
            endSession();
        }
    }

    public void pause() {
        int millisToPause = DDTSettings.Settings().defaultPause();
        if (millisToPause > 0) {
            try {
                //System.out.println("Pausing for " + String.valueOf(millisToPause + " milliseconds"));
                Thread.sleep(millisToPause);
            } catch (Exception e) {
            }
        }
    }
}