If you are using maven, you can add following dependency to your project.
01 02 03 04 05 | < dependency > < groupId >org.unitils.selenium</ groupId > < artifactId >unitils-selenium</ artifactId > < version >1.0.8</ version > </ dependency > |
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.
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.
Please create unitils-local.properties, and add selenium to unitils.modules. Code as following:
01 02 03 04 05 06 07 08 09 10 | unitils.modules = [... other modules ...], webDiver 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 browsers that you can choose from: Internet Explorer (IE), HtmlUnit(HTMLUNIT), firefox (FIREFOX), Chrome (CHROME).
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
How does a test work?
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. |
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.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | 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.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class SearchPage extends BasePage { @FindBy (id = "createForm:name" ) private WebElement surname; @FindBy (id = "createForm:firstName" ) private WebElement firstName; @FindBy (id = "createForm:tolerance" ) private WebElement tolerance; @FindBy (id = "createForm:birthdate" ) private WebElement birthDate; @FindBy (id = "createForm:searchButton" ) private WebElement searchButton; /** * @param surname the surname to set */ public void setSurname(String surname) { this .surname.sendKeys(surname); } /** * @param firstName the firstName to set */ public void setFirstName(String firstName) { this .firstName.sendKeys(firstName); } /** * @param tolerance the tolerance to set */ public void setTolerance(String tolerance) { this .tolerance.sendKeys(tolerance); } /** * @param birthDate the birthDate to set */ public void setBirthDate(Date birthDate) { Calendar cal = Calendar.getInstance(); cal.setTime(birthDate); this .birthDate.sendKeys(cal.get(Calendar.MONTH) + "/" + cal.get(Calendar.DATE) + cal.get(Calendar.YEAR)); } } |
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.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @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.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | public class SearchScenarioTest extends AbstractWebTest { @Test public void test() throws InterruptedException { getDriver().get(getBaseUrl()); SearchPage searchPage = PageFactory.initElements(getDriver(), SearchPage. class ); //Thread.sleep(10000); searchPage.gotoCreate(); searchPage.gotoSearch(); //... Asserts... } } |
If a selenium test goes wrong than the framework creates automatically a new screenshot of the last screen before it kills the webdriver. If there is an @Testlink annotation on the test than he will create a screenshot with the Testlink id as name.
But if you want to make screenshots while selenium is running your test, than you can create a org.unitils.selenium.ScreenshotTakingWebDriver and call the method saveScreenshot().
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | @RunWith (UnitilsBlockJUnit4ClassRunner. class ) public class ScreenshotTakingWebdriverExampleTest { @BaseUrl private String baseUrl; @TestWebDriver private WebDriver webDriver; @Test public void testWithScreenshots() { ScreenshotTakingWebDriver screenshotWebdriver = new ScreenshotTakingWebDriver(webDriver, baseUrl); webDriver.get(baseUrl); screenshotWebdriver.saveScreenshot(); screenshotWebdriver.saveScreenshot(); } } |
The default location is under target/screenshot/[nameOfTheTest].
This is a nice feature for analists, they don't need to do stupid activities like taking screenshots anymore.
Sometimes it's possible that you don't use the correct driver for your browser.
Than you get exceptions like f.e. 'The path to the driver executable must be set by the webdriver.ie.driver system property'.
You can find the correct driver on the internet:
And you can simply add them with a Unitils property.
01 02 03 | org.unitils.selenium.firefoxbinary = ? #location of the firefox driver org.unitils.selenium.chromedriver = ? #location of the chrome driver org.unitils.selenium.iebinary = ? #location of the ie driver |
The latest drivers are also added to unitils-selenium. If the WebdriverModule cannot find a property or a good driver in your system property than he will use that driver. \
Note: You should always close the driver correctly, if you close the screen in the middle of a test, than he won't kill the driver correctly and than you must kill the driver with your taskmanager.
If you've installed youre browsers with the installer, than youre browsers are on a fixed place and unitils-selenium hasn't got problems with finding the binary (.exe file on windows).
But if your browser is on a different location or if you use something like f.e. LiberKey, than you can set the location of the binary with the following property:
01 | org.unitils.selenium.chromebinary = #location of the exe. |
You can print the selenium logging in a file or in the console.
01 02 03 04 05 06 07 08 | org.unitils.selenium.logging.console.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. |
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.
01 02 | 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. If you add the following property in your unitils.properties, than you only have to change the property if you change your Internet Explorer..
01 | org.unitils.selenium.downloader.RobotDownloader = ???? |
The following 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.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 | @RunWith (UnitilsBlockJUnit4ClassRunner. class ) public class DownloadFileExampleTest { @TestWebDriver private WebDriver driver; private RobotDownloader robotDownloaderIE; @Before public void setUp() { robotDownloaderIE = RobotDownloaderFactory.createDownloaderIE(); } @Test public void testDownloadFile() throws Exception { 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.
01 02 03 04 05 06 07 08 | @Test public void testDownloadUrl() throws Exception { 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.