Tuesday, December 23, 2014

Selenium WebDriver - Building a Continuous Integration System with Java Tools

Introduction

As we promise, this week we will explain how to integrate java, webdriver, intellij idea, junit, maven, hudson. The objective is to have a continuous integrated system, to run the automated tests during night.

The following will be covered:
  • Installing Java, Intellij IDEA, Maven, Firefox 
  • Configuring Intellij IDEA and Maven for Selenium WebDriver. Also, we will show you how to create your first project in Intellij IDEA
  • Installing Hudson for continuous integration 
  • Using Hudson and Maven for test execution
Installing Java, Intellij IDEA, Maven, Firefox

Below you can see a diagram with the required tools in order to use WebDriver with Java


As we already mentioned, we will use Maven, Intellij.
Installing Firefox and the necessary plugins
  • Go to getfirefox.com and download Firefox
  • Install the following plugins: firebug (debugger used to identify objects), Selenium IDE (used to record actions; beginner users can use this), firepath (used to identify the absolute/relative path  and Element locator for WebDriver (very usefull to identify by xpath an element and can be used with element right-click-->Java locators)
Installing Java
  • Check first if java is not already installed on your computer (open a command prompt and type java - version)
  • If not, than go to the oracle site and install the correct version of java: http://www.oracle.com/technetwork/java/javase/downloads/index.html
  • Go to Environment variables (Computer --> Properties --> Advanced System Settings --> Environment variables) and check if the java variable  (location to bin installation folder; e.g. C:\Program Files\Java\jdk1.8.0_25\bin\) is added to the system path
  • Now, when you type  java - version you will see that java was installed

Installing Maven
  • Download latest Maven corresponding to you system from http://maven.apache.org/download.cgi
  • Place the unzip file under folder C:\Program Files\Apache Software Foundation 
  • Create the user variable M2_HOME (Computer --> Properties --> Advanced System Settings --> Environment variables --> New User variable - not a system variable). Pay attention, if the maven version changes, then you should update this variable)
  • Create M2 user variable that points to the Maven bin folder


  • Add the user variable path (not a system) variable that contains the path to Maven bin folder %M2_HOME\bin%


  • Create JAVA_HOME user variable that points to java root directory


  • Reopen the command prompt and check that maven was installed mvn--version


Installing Intellij

Configuring Intellij IDEA and MAven for Selenium WebDriver

In order to work with Maven, we need to create a new Maven Intellij project and to set the path to the jdk location. Then give a group and artifact id and then the project name and location.


When the project is generated, it is important to enable auto import. By doing this (message appears on the top right corner), all maven dependencies will automatically be imported.


In order to write selenium tests we need to bring first junit and then selenium in our maven pom.xml file. The following information should be added:
Now we can add our first test. Create a Test class from Java-->New Class and name the class. It is important that the class name contains in it's name the word test so that maven can run tests from this class.


Installing Hudson for Continuous Integration System

Now that we found out how we can write the tests, we should be able to use a continuous integration system that can automatically run our tests. There are different tools that can be used like TFS build, Hudson, Teamcity.
Hudson is a CI server for the Java development community. Running tests with Hudson and and Maven needs both tools installed on the server.
  • The tool can be downloaded from here: http://hudson-ci.org/
  • The .war file should be deployed on the server where you want to run your tests. 
  • Create a .bat file on your desktop that contains this java -jar "...path to the file\hudson-3.1.2.war"

Using Hudson and Maven for Test Execution 

  • Access you Hudson page by using this link http://localhost:8080/. You can access Hudson from other workstation. To do this just replace 'localhost' with the server host name.
  • Add a new hjob and select Maven 2/3 option



  • Go to the job configuration page and in Advanced Job page set the maven workspace that you are going to use





  • Go to Build area and add 2 steps: one that has as goal the cleaning of the project before the build and the other the running of the tests. For both steps we need to set the path to the pom.xml file.





  • If your project is under a source control system you need to adjust the settings from Source Code Management group
  • If you want to build your project at a specific hour go to Build Triggers group and make the changes in Build periodically field
  • Save the configuration
This is the end oh the story. Next time we will see how to integrate Selenium WebDriver in Visual Studio.

Happy testing and... make it green, becomes a dream :).

Wednesday, December 17, 2014

Selenium WebDriver with Java - Create Helper Classes (2)

Introduction

Last week we stated to present an automation testing framework by using: java, webdriver, intellij idea, junit, maven, log4j, hudson. This week we will continue creating a class that will contain functions in order to work with controls.

ControlUtils

In this chapter we will write functions for working with controls and also how to use them.

FluentWait

Before starting we need a way to wait an element on the page until it will be displayed. We may either use an implicit wait, by waiting a number of seconds or either waiting the element until is displayed on the page.

- implicit wait

public static void wait_time(long fWait){
    try {
        Thread.sleep(fWait);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Use it like this:
wait_time(1000); --> this will wait 1 second

- explicit wait

public static WebElement fluentWait(final By locator){
    long timeStart = System.currentTimeMillis();

    Wait<WebDriver> wait = new FluentWait<WebDriver>(selenium)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

    WebElement foo = wait.until(
            new Function<WebDriver, WebElement>() {
                public WebElement apply(WebDriver driver) {
                    return driver.findElement(locator);
                }
            }
    );

    long timeEnd = System.currentTimeMillis();
    logger.info("Element waited for: " + (timeEnd - timeStart) + " ms.");

    return  foo;
};


Functions for Controls

- get_text
public static String get_text(By byValue) {
    WebElement element = fluentWait(byValue);
    String elementText = null;
    elementText = element.getText();

    return elementText;
}

This function will get the control's text and can be used like this:
String submitButton = ControlUtils.get_text(By.id("loginBtn"));

- verify text
public static boolean verify_text(By byValue, String fText) {

    String fTextOut = fluentWait(byValue).getText();
    if (fTextOut.equals(fText)) {
        return true;
    } else {
        return false;
    }
}

This function will return true or false and will check if the control's text is correct. You can use it like this.
boolean submitButton = ControlUtils.verify_text(By.id("loginBtn"), "Sign in");
Assert.assertEquals("Submit button text is not correct", true, submitButton);

- element_present
public static boolean element_present(By byValue) {
    if (fluentWait(byValue).isDisplayed()) {
        return true;
    } else {
        return false;
    }
}

This function will return true or false and will check if the control is present or not on the page. You can use it like this.
Assert.assertEquals("Delete button is not present", true, ControlUtils.element_present(By.id("btnLeaveDelete")));

- click_element
public static void click_element(By byValue)
{
    WebElement element = fluentWait(byValue);
    element.click();
}

This function will click an element on the page. Use it like this:
ControlUtils.click_element(By.id("loginBtn"));

- double_click_element
public static void double_click_element(By byValue){
    WebElement elementToDoubleClick = fluentWait(byValue);

    Actions action=new Actions(selenium);
    action.doubleClick(elementToDoubleClick);
    action.perform();
}

This is used to double-click an element. Usage:
ControlUtils.double_click_element(By.id("loginBtn"));

- get_attribute
public static String get_attribute(By byValue, String fAttribute) {
    return fluentWait(byValue).getAttribute(fAttribute);
}

The function will get a specific attribute from a control. Usage:
String startDateText = ControlUtils.get_attribute(By.id("inputleaveStartDate"), "value");

- is_attribute_present
public static boolean is_attribute_Present(WebElement element, String attribute)
{
    Boolean result = false;
    try {
        String value = element.getAttribute(attribute);
        if (value != null){
            result = true;
        }
    } catch (Exception e) {}

    return result;
}


This will check if an attribute of a control is present or not. Imagine for example that you have to test if a control is or not disabled. Usage:
WebElement disapproveButton = fluentWait(By.id("btnLeaveDisapprove"));
Assert.assertEquals("Disapprove button is not disabled", true, ControlUtils.isAttributePresent(disapproveButton, "disabled"));

- send_keys
public static void send_keys(By byValue, String fText)
{
    WebElement element = fluentWait(byValue);
    element.sendKeys(fText);
}

This function will write some text in a control. Usage:
ControlUtils.send_keys(By.id("inputleaveStartDate"), "01-01-2014");

- refresh_page
public static void refresh_page() {
    Actions actionObject = new Actions(selenium);
    actionObject.keyDown(Keys.CONTROL).sendKeys(Keys.F5).perform();
}

If you need to refresh the page use this function.

- functions for selection controls
// Clear all selected entries. This is only valid when the SELECT supports * multiple selectionspublic static void select_deselect_all(By byValue, String fxPath){
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.deselectAll();
}

//Select none the option at the given index. This is done by examining the * "index" attribute of an element, and not merely by countingpublic static void select_deselect_by_index(By byValue, int index) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.deselectByIndex(index); }

//Select none all options that have a value matching the argument. */public static void select_deselect_by_value(By byValue, String value) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.deselectByValue(value);
}

//Select none all options that display text matching the argumentpublic static void select_deselect_by_visible_text(By byValue, String matchingArgument) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.deselectByVisibleText(matchingArgument);
}

//Gets all selected options belonging to this select tag.public static String select_get_all_selected_options(By byValue) {
    Select selectBox = new Select(fluentWait(byValue));
    List<WebElement> selectOptions = selectBox.getAllSelectedOptions();
    String selectText = "";
    String cumulatedSelectText = "";
    for (WebElement temp : selectOptions) {
        selectText=temp.getText();
        cumulatedSelectText= cumulatedSelectText + " " + selectText;
        System.out.println("cumulatedSelectText: " + cumulatedSelectText);
    }

    return cumulatedSelectText;
}

//Gets the first selected option in this select tag (or the currently * selected option in a normal selectpublic static String select_get_first_selected_option(By byValue) {
    Select selectBox = null;
    selectBox = new Select(fluentWait(byValue));
    System.out.println(selectBox.getFirstSelectedOption().getText());

    return selectBox.getFirstSelectedOption().getText();
}
//Gets all options belonging to this select tagpublic static void select_get_options(By byValue) {
    Select selectBox = new Select(fluentWait(byValue));
    List<WebElement> selectOptions = selectBox.getOptions();
    for (WebElement temp : selectOptions) {
        System.out.println("getText" + temp.getText());
    }
}

//Whether this select element support selecting multiple options at the * same time? This is done by checking the value of the "multiple" * attribute.public static void select_is_multiple(By byValue) {
    Select selectBox = new Select(fluentWait(byValue));
    System.out.println(selectBox.isMultiple());
}

//Select all options that have a value matching the argument.public static void select_select_by_value(By byValue, String value) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.selectByValue(value);
}

//Select the option at the given indexpublic static void select_select_by_index(By byValue, int index) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.selectByIndex(index);
}

//Select all options that display text matching the argumentpublic static void select_select_by_visible_text(By byValue, String matchingArgument) {
    Select selectBox = new Select(fluentWait(byValue));
    selectBox.selectByVisibleText(matchingArgument);
}

Next week we will present how to install and set java, webdriver, intellij idea, junit, maven, log4j, hudson. I hope you liked this article. Happy testing and... make it green, becomes a dream :).

Monday, December 8, 2014

Selenium WebDriver with Java - Create Helper Classes (1)

Introduction

In this article we will start presenting a Selenium WebDriver framework. The following are used:
- Java
- Intellij IDEA 14 Community edition IDE
- Junit for tests
- maven
- log4j library for logging
- Hudson for continuous integration
In a future article we will present how to install and integrate all these components.

DriverUtils

First of all we can create a DriverUtils class that will contain functions for starting the web driver, getting the browser, opening the desired url, closing browser, login, logout, functions to be executed before and after all tests are run or after all test from a class are run. Also, we can include here a function that will log, at the beginning of each test, a name and a description.
Let's start!

Start WebDriver

public static void open_driver(String bName)
{
    logger.info("Opening selenium driver");
    selenium = null;
    String path = System.getProperty("user.dir");

    if(bName.equals(ConstantsHelpers.firefoxBrowser))
    {
        FirefoxProfile firefoxProfile = new FirefoxProfile();
        selenium = new FirefoxDriver(firefoxProfile);
        selenium.manage().window().maximize();
    }
    else if(bName.equals(ConstantsHelpers.ieBrowser))
    {
        DesiredCapabilities caps = DesiredCapabilities.internetExplorer();
        caps.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
        System.setProperty("webdriver.ie.driver", path + "\\IEDriver\\IEDriverServer.exe");
        selenium = new InternetExplorerDriver(caps);
        selenium.manage().window().maximize();
    }
    else if(bName.equals(ConstantsHelpers.chromeBrowser))
    {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--disable-web-security");
        DesiredCapabilities caps = DesiredCapabilities.chrome();
        caps.setCapability(ChromeOptions.CAPABILITY, options);
        System.setProperty("webdriver.chrome.driver", path + "\\ChromeDriver\\chromedriver.exe");
        selenium = new ChromeDriver(caps);
        selenium.manage().window().maximize();
    }

    else if(bName.equals(ConstantsHelpers.safariBrowser))
    {
        selenium = new SafariDriver();
        selenium.manage().window().maximize();
    }
}

Some tips about this function:
  • selenium is declared globally

public static WebDriver selenium;
  • selenium is set and get
//Function to get selenium driver
public static WebDriver getSelenium() { return selenium; }
//Function to set selenium driver
public static void setSelenium(WebDriver selenium) { DriverUtils.selenium = selenium;}
  • for working with Chrome and IE drivers we need to download the exe drivers and include them in the project. To set the path we use
String path = System.getProperty("user.dir");
  • The name of the drivers are stored in a ConstantsHelpers class 
public static String ieBrowser = "IE";
public static String firefoxBrowser = "Mozilla";
public static String safariBrowser = "Safari";
public static String chromeBrowser = "Chrome";
  • Capabilities: describes a series of key/value pairs that encapsulate aspects of a browser. You can find more information about this on the internet
Get browser
//Browser type: change constant if you want to run test on different browser//Available browsers are: IE, Chrome, Firefox, Safaripublic static String getBrowser() {
    return ConstantsHelpers.firefoxBrowser;
    //return ConstantsHelpers.chromeBrowser;    //return ConstantsHelpers.ieBrowser;    //return ConstantsHelpers.safariBrowser;
}

Open url

In order to open your url you can create a function
//Function that opens the desired url for your applicationpublic static void open_url()
{
    logger.info("Opening url " + ConstantsHelpers.url);
    selenium.get(ConstantsHelpers.url);
}

where the url is define in a ConstantsHelpers class
public static String url="http://my_url.com";

Close browser
//Closes browser/driverpublic static void close_browser()
{
    logger.info("Closing browser and driver");
    getSelenium().close();
    getSelenium().quit();
}

Wait time 
This is a function used to implicitly wait the specified amount of time in milliseconds
public static void wait_time(long fWait){
    try {
        Thread.sleep(fWait);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

You can use it like this:
wait_time(5000);

@Before, @BeforeClass, @AfterClass, @After
Depending on your project, you can set some actions to be taken:
- before starting tests @Before
- before starting tests from a class @BeforeClass
- after running all tests from a class @AfterClass
- after running all tests @After

Here are some examples:
@BeforeClassstatic public final void setUpBeforeClass() throws Exception {
    String browser = DriverUtils.getBrowser();
    open_driver(browser);
}

@Beforepublic void setUp() throws Exception
{
    open_url();
}

@AfterClassstatic public void tearDownAfterClass() throws Exception
{
    close_browser();
}

Login, Logout
Supposing you web page has a login page, you can include the Login, Logout function in @BeforeClass and @AfterClass annotations.
Below you have a login example:
public static void login(String username, String password) {
    logger.info("Logging in with '" + username + "' userName and language " + password);

    ControlUtils.send_keys(By.id("language-select"), ConstantsHelpers.language);
    ControlUtils.send_keys(By.id("username"), username);
    ControlUtils.send_keys(By.id("password"), password);

    ControlUtils.fluentWait(By.id("loginBtn")).click();
}

Test Case Description
Another function that we added in this class is the one that, in the test logs, at the beginning of each test, writes a brief description about the test to be run.
public static void TestCaseDescription(String title, String description)
{
    String browser=DriverUtils.getBrowser();

    logger.info("---------------------------------------------------------------------");
    logger.info("This test was executed in '" + browser + "' browser.");
    logger.info("---------------------------------------------------------------------");
    logger.info("Test executed in class '" + StackTraceInfo.getInvokingClassName() + "' and in method '" + StackTraceInfo.getInvokingMethodName() + "'.");
    logger.info("---------------------------------------------------------------------");
    logger.info("Test title '" + title + "'.");
    logger.info("---------------------------------------------------------------------");
    logger.info("Test description '" + description + "'.");
    logger.info("---------------------------------------------------------------------");
}

The function uses log4j library and a class for getting the class and method name. But we will talk about these in future stories
The function can be used like this: TestCaseDescription("Test name", "Test description");
and the result in the test run will look like this:

Hope you enjoyed this article.

Popular Posts