This module integrates Selenium into a jUnit test. Because of this integration you can use the full stack of features of Unitils when you use its runner.

GUI testing

In this chapter we'll talk about automating tests for classic web
application. When we talk about classic web application we mean html based applications, so no flash generated sites.
The tests we're talking about are not unit tests but system tests. We'll test a whole system. And because the test runs against a gui, the html pages, we'll often use the word Gui tests. You could mock out the backend and just test the frontend but that is an effort we discourage you to do.

Two schools:
There are mainly two different approaches to create automated Gui test.
- You can use a tool to record and playback tests
- You can program yourself an automated test using an automation api

The reason why there are two approaches is explained by the fact that there are mainly two types of people doing the job.
You have functional people who understand the business and are best placed to define the testcases. Often they also execute the testcases to validate that the application acts as they expect. Recording and playback tools will help ease the task of test automation for these people. There are a lot of tools on the market, commercial and opensource.
People with a technical background can choose another option: programming the automation scripts. This approach allows you to create much cleaner code. It will also force you to think of scriptcode reusage which will reduce script maintanance. In this chapter we'll defend this statement.
Record and Playback:
Using a tool to record testcases will allow you to create a lot of scripts in a record period of time. In this power lays directly the danger. The more you create the more you have to maintain.

NOTE:
You can download the selenium-ide add-on for Firefox. You can
record some moves and than it will replay it. But even when you want to use the unitils-selenium module, it can be handy. When you go to options, then to clipboard format and if you select the option JUnit 4 (Webdriver) than you can copy paste all the commands into your eclipse and you will see that you already have the ids of the different components of your html page. This is one option, but there
are other posibilities like firebug.

Domain Specific Language (DSL)
You can use inheritance \& composition to avoid code duplication and to limit the code to maintain to a minimum. You can create a base page with all the items in the header, that all other pages must extend.

Selenium Module load artifact (maven)

    <dependency>
        <groupId>org.unitils.selenium</groupId>
        <artifactId>unitils-selenium</artifactId>
        <version>1.0.8</version>
    </dependency>

Selenium Module project config

unitils.modules = [ other modules  ], webDriver

unitils.module.webDriver.className=
org.unitils.selenium.WebDriverModule  
unitils.module.webDriver.runAfter=  
unitils.module.webDriver.enabled=true

org.unitils.selenium.browser.name=FIREFOX 
org.unitils.selenium.baseUrl= ???
# optional values: This is only needed when you want to download a file with Selenium.
org.unitils.selenium.downloadpath = ??? # (f.e.: C:\\Temp)
org.unitils.selenium.filetype= ???

browser
There are several web drivers that you can choose from: Internet Explorer (IE),
HtmlUnit(HTMLUNIT), firefox (FIREFOX), Chrome (CHROME), remote web driver (REMOTE).

downloadpath
The downloadpath can be absolute or relative.

file types

The default value for org.unitils.selenium.filetype: application/pdf, application/vnd.fdf, application/x-msdos-program, application/x-unknown-application-octet-stream, application/vnd.ms-powerpoint, application/excel, application/vnd.ms-publisher, application/x-unknown-message-rfc822, application/vnd.ms-excel, application/msword, application/x-mspublisher, application/x-tar, application/zip, application/x-gzip,application/x-stuffit,application/vnd.ms-works, application/powerpoint, application/rtf, application/postscript, application/x-gtar, video/quicktime, video/x-msvideo, video/mpeg, audio/x-wav, audio/x-midi, audio/x-aiff, application/octet-stream

But you can override this property in the unitils.properties.

Remote web driver
In version 1.0.6 we have added the option to choose for the remote web driver from selenium.
You only have to add two properties.

org.unitils.selenium.browser.name=REMOTE 
org.unitils.selenium.remotedriver.capabilities = FIREFOX 
org.unitils.selenium.remotedriver.url  = ...

How does a test work?

The annotations:
BaseUrl:
You can define the base url in the unitils.properties or you can define it with this annotation.
TestWebDriver:
This annotation creates the driver. With the property "org.unitils.selenium.browser.name" in the unitils.properties file you define which browser you want to use for your tests. So if you define that you want to use firefox, than you get a FirefoxDriver.
WebPage:
The field with this annotation represents a web page. this means that it contains the webelements of a webpage.It uses the webdriver (field with @TestWebDriver) to initialize the elements.

Example

If the webpage has a menu, you should make a base page with all the menu items and all the pages extends this base page. If you know the id, path ... of the webelement, you can use the FindBy annotation.
In this example there is a menu with a link to a search page and a create page.

 public class BasePage {

    @FindBy(id="navigationForm:menuCreate")
    private WebElement createElement;


    @FindBy(id="navigationForm:menuSearch")
    private WebElement searchElement;

    public void gotoCreate() {
        createElement.click();

    }

    public void gotoSearch() {
        searchElement.click();
    }


 }

The Searchpage of the following example extends from the BasePage and contains all the important web elements of that specific webpage.

public class SearchPage extends BasePage {

    @FindBy(id = "createForm:name")
    private WebElement nameField;
    @FindBy(id = "createForm:firstName")
    private WebElement firstName;
    @FindBy(id = "createForm:tolerance")
    private WebElement tolerance;
    @FindBy(id = "createForm:searchButton")
    private WebElement searchButton;
    @FindBy(id = "searchResults")
    private WebElement table;

    public void searchByName(String strFirstName, String lastName){
        nameField.sendKeys(lastName);
        firstName.sendKeys(strFirstName);

        searchButton.click();

    }

    public void checkFirstLine(String firstName1, String lastName){
        //searchByName(firstName1, lastName);
        List<WebElement> elements = table.findElement(By.tagName("tbody")).findElement(By.tagName("tr")).findElements(By.tagName("td"));

        Assert.assertEquals(firstName1, elements.get(0).getText());
        Assert.assertEquals(lastName, elements.get(1).getText());

    }
}

In the example the nameField and firstName are textboxes and it will put the correct string into the text box.

The best way to create your tests, is creating a base web test class. In this class you can put your web driver and base URL.

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class AbstractWebTest {


    @TestWebDriver
    private WebDriver driver;

    @BaseUrl
    private String baseUrl;

    public AbstractWebTest(){
    }

    public WebDriver getDriver() {
        return driver;
    }


    public String getBaseUrl() {
        return baseUrl;
    }


}

All your other tests have to extends this base test class, just like in the following example.

@RunWith(UnitilsJUnit4TestClassRunner.class)
public class SearchScenarioTest extends AbstractWebTest {

    @WebPage
    SearchPage searchPage

    @Test
    public void test() throws InterruptedException {
        getDriver().get(getBaseUrl());
        Thread.sleep(10000);
        searchPage.gotoCreate();
        searchPage.gotoSearch();

        searchPage.searchByName("Jeroen", "Horemans");

        Thread.sleep(10000);
        searchPage.checkFirstLine("Jeroen", "Horemans");
    }
}

Screenshots

There is a new feature in unitils-selenium 1.0.4: taking screenshots.
The ScreenshotTakingWebDriver is an extension of the WebDriverBackedSelenium and makes it possible to create screenshots and safe them in a specific folder or if the test has a Testlink ID than it will be automatically saved in Testlink.

Videos

In unitils-selenium 1.0.8 there is a new module that you can enable that creates videos from your tests. If a test goes wrong than you can see second by second what happens in your test and where it goes wrong.

unitils.modules = [… other modules … ], video 
unitils.module.video.className = org.unitils.selenium.screenrecorder.ScreenRecordingModule
unitils.module.video.runAfter=
unitils.module.video.enabled=true

By default, the recordings are saved in the /target/screenRecordings/[name of the test method]/ScreenRecording [date] at [time].avi.

You can open the files with an advanced video player like VLC.

If you want to override any of these properties, you can create your own ScreenRecorderFactory. Activate your factory with this property:

org.unitils.selenium.screenrecorder.factory=#fully qualified name of your own ScreenRecorderFactory implementation

Drivers

Sometimes selenium cannot find the correct driver and unitils-selenium makes sure that it can find a driver.
There are default drivers given by unitils-selenium, but this should be the last option.
The best solution is to pinpoint your system variables to the correct driver locations.

  • Chrome driver property: webdriver.chrome.driver
  • Firefox driver property: webdriver.firefox.bin
  • IE driver property: webdriver.ie.driver

But if you don't have the rights to do this, than you can set the drivers as followed in the unitils.properties.

org.unitils.selenium.firefoxbinary= ? #location of the firefox driver
org.unitils.selenium.chromebinary= ? #location of the chrome driver
org.unitils.selenium.iebinary= ? #location of the ie driver

If you have to download other drivers than you can find them here:

Logging

This feature enables you to get the logging of the webdriver.
Selenium keeps information from the client, browser, driver, performance, server.
You can use the java.util.logging.Level list to decide which level you want to choose:

  • ALL
  • SEVERE
  • WARNING
  • INFO
  • CONFIG
  • FINE
  • FINER
  • FINEST
  • OFF

Each type can be configured like this:

 org.unitils.selenium.logging.enabled=true #prints the console output after a test and before the @After method begins
 org.unitils.selenium.logging.performance= ? #default: OFF
 org.unitils.selenium.logging.browser= ? #default: OFF
 org.unitils.selenium.logging.client= ? #default: OFF
 org.unitils.selenium.logging.driver= ? #default: OFF
 org.unitils.selenium.logging.profiler= ? #default: OFF
 org.unitils.selenium.logging.server= ? #default: OFF


 org.unitils.selenium.logging.file= ? #The output can also be printed in a file, if you give the location of the file.

(This feature is not yet available for Internet Explorer).

Chrome Binary

Use this feature if you want to use another location then the default location of the Chrome binary.

org.unitils.selenium.chromebinary = C:\\Tools\\lkl\\Apps\\Chrome\\ChromeLKL.exe

Downloading files with Selenium

(version 1.0.8)
Downloading files with Selenium can be a little bit tricky.
For Firefox and Chrome it's quite easy... just add the download folder property in your unitils.properties and the files are downloaded in that folder. The filetype property can be set, but it is only needed if you want to download a specific type of file. (see: file types in "Selenium Module project config" paragraph)

org.unitils.selenium.downloadpath = ??? # (f.e.: C:\\Temp)
org.unitils.selenium.filetype= ???

But if you want to test your application with Internet Explorer than it can be more difficult, because there appears a window that you can't get rid off.

There are a few options, you can work with AutoIt or you can use a robot.

We created a robot for downloading files with Internet Explorer 9.
But if you use another Internet Explorer that downloads his files in another way, than you only have to set the following property and RobotDownloaderFactory.createDownloaderIE() will create the correct RobotDownloader for your type of IE.

org.unitils.selenium.downloader.RobotDownloader = ????

This example will try to download a file with IE, verifies if the file actually exists and deletes the file at the end of the test.

@RunWith(UnitilsBlockJUnit4ClassRunner.class)
public class DownloadFileManualExampleTest {

    @TestWebDriver
    private WebDriver driver;
    private RobotDownloader robotDownloaderIE;

    @Before
    public void setUp() {
        robotDownloaderIE = RobotDownloaderFactory.createDownloaderIE();
    }

    @Test
    public void testDownloadFile() throws Exception {

        driver.get("http://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/");
        WebElement downloadLink = driver.findElement(By.linkText("spring-framework-ref..>"));
        robotDownloaderIE.clickAndSaveFileIE(downloadLink);
        robotDownloaderIE.checkIfDownloadedFileExists(downloadLink);

        robotDownloaderIE.deleteDownloadedFile(downloadLink);
    }
}

If you know the link and you only want to test how the file looks like, than you can check it another way.

@Test
public void testDownloadUrl() throws Exception {
    URL url = new URL("http://www.urlFileToDownload.be/fileToDownload.pdf");

    File tempFile = File.createTempFile("expectedTempFile", ".pdf");
    FileUtils.copyURLToFile(url, tempFile);
    Assert.assertTrue(tempFile.exists());
}

The files (downloaded with the RobotDownloader) are downloaded in the user downloads folder.

 

Last edit: Willemijn Wouters 2015-12-10