UI Automation using Appium and WinAppDriver

Introduction to Appium

Appium is an open source cross platform test automation framework for use with native, hybrid and mobile web apps. It drives iOS, Android, and Windows apps using the WebDriver protocol. Platforms supported are:

  •  iOS
  • Android
  • Windows
  • FirefoxOS

Step 1: Installing Appium in Windows machine

npm install -g appium  // get appium
npm install wd   // get appium client
appium &         //Start appium

Appium install

Note: Appium will install WindowsAppDriver automatically.

You can explicitly install WindowsAppDriver.exe from 

https://github.com/Microsoft/WinAppDriver/releases

Step 2: Writing your Test code( classic Windows app)

You can use any Selenium supported language and specify the full executable path for the app under test in the app capabilities entry. In my example I will be using C#.

Following is a sample code to create test session for Windows Notepad.

 If you are using Appium as mentioned in Step 1, do not forget to add /wd/hub in ur URL.

You can get the complete sample project at my Github site.

namespace NotepadExample
{
    [TestClass]
    public class NotepadBase
    {
        // Note: append /wd/hub to the URL if you're directing the test at Appium
        protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723/wd/hub";
        protected static WindowsDriver<WindowsElement> NotepadSession;

        [ClassInitialize]
        public static void NotepadBaseSetup(TestContext testcontext)
        {
            if (NotepadSession == null)
            {
               //launch the Notepad app
               DesiredCapabilities appCapabilities = new DesiredCapabilities();
               appCapabilities.SetCapability("deviceName", "WindowsPC");
               appCapabilities.SetCapability("app", @"C:\Windows\System32\notepad.exe");
               NotepadSession = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
            }
        }
        [TestMethod]
        public void TestMethod1()
        {
          NotepadSession.FindElementByClassName("Edit").SendKeys("This is an automated text......");
          Assert.IsNotNull(NotepadSession);
        }
        [ClassCleanup]
        public static void NotepadBaseTearDown()
        {
            if (NotepadSession != null)
            {
                NotepadSession.Dispose();
                NotepadSession = null;
            }
        }
    }
}

Using Appium you can write tests with any WebDriver compatible language such as Java, C#, Nodejs, PHP, Phython, Ruby or Perl With the Selenium WebDriver API. It removes limitation of Selenium by providing support to Windows based desktop applications.

Watch the video for easy reference.

 

Selenium Ruby Binding – how ?

Good part of selenium is that the selenium tests can be written in multiple programming languages like c#, Java, Perl, PHP, Ruby etc. I normally hear saying that “This Java project, so we can write tests in Java as well”.  The only advantage I see with this is that you can get help from development team incase you are stuck somewhere. But if you are good at c# or any other language it should not be an hindrance. Test framework will be different that coding framework unless you want to integrate it.

I covered Java and C# in most of my previous posts. Here I will be using Ruby to write the Selenium tests.

 A simple Ruby Test

require "selenium-webdriver"
driver = Selenium::WebDriver.for :firefox
driver.navigate.to "http://www.google.com"
element = driver.find_element(:name, 'q')
element.send_keys "Hello Selenium WebDriver!"
element.submit

require “selenium-webdriver”  – This is similar to import in Java and using in c#

The above example is without using any Test framework. In Ruby you can use Test Framework as you do with C# ( NUNIT test framework) and Java( JUNIT or TestNG framework).

In Ruby you can use minitest or BDD framework  RSpec or Cucumber

Structure of RSpec test

load File.dirname(__FILE__) + '/test_helper.rb' 
#'describe' marks the a test group
describe "Selenium Ruby Tests" do 
include TestHelper
 # 'it' marks the start of a test case, ends with the matching 'end'
it "Start Chrome" do
 browser = Selenium::WebDriver.for(:chrome) browser.navigate.to(site_url)
 sleep 1
 browser.quit
end
it "Start FireFox" do
browser = Selenium::WebDriver.for(:firefox) browser.navigate.to(site_url)
 sleep 1
 browser.quit
end
it "Start IE" do
 browser = Selenium::WebDriver.for(:ie) browser.navigate.to(site_url)
 sleep 1
 browser.quit
end 
end

For more information on RSPec click here .

Using Selenium to Scroll on pages

By using selenium to scroll on pages, you can do automated testing of a page which is dynamically loaded. Something like linkedin or facebook where you get the updates as you scroll down the page. To scroll throught the page in Selenium you can use JavaScript function called scrollBy. Here is the code for it.

for (int x= 0;; x++) {
 ifx >=60){
 break;
 }
 driver.executeScript("window.scrollBy(0,200)", "");
 Thread.sleep(1000);
 }

The above code uses the JavaScript method “scrollBy” to scroll on the page. The for loop runs for 60 sec and calls the scrollBy function every second. This makes the selenium to scroll on the page.
If you have a test where you need to scroll on the page and check whether an element is loaded dynamically or not you can put a isElementPresent like function after the “driver.executeScript” to check visibility of your element.

Following code snippet shows the above function in linkedin.

package Sample;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.AfterSuite;
public class ScrollingSample {
 public RemoteWebDriver driver;
 @Test
 public void ScrollTest() throws InterruptedException {
 driver.get("http://www.linkedin.com");
 driver.findElement(By.id("session_key-login")).click();
 driver.findElement(By.id("session_key-login")).clear();
 driver.findElement(By.id("session_key-login")).sendKeys("pintushaw@gmail.com");
 driver.findElement(By.id("session_password-login")).clear();
 driver.findElement(By.id("session_password-login")).sendKeys("prisha@9033");
 driver.findElement(By.id("signin")).click();

//Following is the code that scrolls through the page
 for (int second = 0;; second++) {
 if(second >=60){
 break;
 }
 driver.executeScript("window.scrollBy(0,200)", "");
 Thread.sleep(3000);
 }
 }
@BeforeSuite(alwaysRun = true)
 public void beforeSuite() {
 driver = new InternetExplorerDriver(); 

 }
>@AfterSuite(alwaysRun = true)
 public void afterSuite() {
 driver.quit();
 }
}

Note: You can use similar approach and use other Javascript functions.

Using Selenium with JMeter

To use Selenium Webdriver with JMeter, install “Webdriver” plugins. The WebDriver sampler is useful if you want to test for performance AJAX or GWT based web applications.

Download WebDriver plugins from http://jmeter-plugins.org/downloads/all/

Unzip the files and copy in the lib folder under JMeter home directory.

To test if WebDriver plugins installed open Jmeter and test if there is jp@gc – Firefox Driver Config.

*If not, check your JMeter’s lib folder.
 Selenium Webdriver SamplerAdd the Webdriver sampler and Firefox or chrome driver config element. Insert the following code to launch Bing search and search for a text. Also add tree listener to view the result.
var pkg = JavaImporter(org.openqa.selenium)
var support_ui = JavaImporter(org.openqa.selenium.support.ui.WebDriverWait)
var wait = new support_ui.WebDriverWait(WDS.browser, 20000)
WDS.sampleResult.sampleStart()
WDS.browser.get('http://www.bing.com/')
var searchField = WDS.browser.findElement(pkg.By.id('sb_form_q'))
searchField.click()
searchField.sendKeys(['testing'])
var button = WDS.browser.findElement(pkg.By.id('sb_form_go'))
button.click()
WDS.sampleResult.sampleEnd()
selenium_jmeter_2
Explanation of the code
  • The code starts with the import Java packages “org.openqa.selenium” and “org.openqa.selenium.support.ui.WebDriverWait” which will allow you to use the WebDriver classes.
  • WDS.sampleResult.sampleStart() and WDS.sampleResult.sampleEnd() captures sampler’s time and will track it. You can remove them, the script will still work but you will not get load time
  • WDS.browser.get(‘http://www.bing.com/’) – opens the browser with Bing search website
  • var searchField = WDS.browser.findElement(pkg.By.id(‘sb_form_q’)) – saves the search text box in searchField varialble
  • searchField.click() – Clicks the search field to make it active
  • searchField.sendKeys([‘testing’]) – Enters text to search
  • var button = WDS.browser.findElement(pkg.By.id(‘sb_form_go’)) – Saves search button in a variable
  • button.click() – clicks on the search button.

You are now ready to go. Do let us know your experience in using Selenium with JMeter

Page Object Model in Selenium

Page Object is a Design Pattern which has become popular in test automation for enhancing test maintenance and reducing code duplication. A page object is an object-oriented class that serves as an interface to a page of your Application under test. The tests then use the methods of this page object class whenever they need to interact with that page of the UI. The benefit is that if the UI changes for the page, the tests themselves don’t need to change, only the code within the page object needs to change. Continue reading “Page Object Model in Selenium”

How to Locate UI Elements (WebElements) in Selenium

To Locate UI elements in Selenium each of the language bindings expose a “Find Element” and “Find Elements” method. The first returns a WebElement object otherwise it throws an exception. The latter returns a list of WebElements, it can return an empty list if no DOM elements match the query.

Following are the list of ways by which you can locate UI elements in selenium

By ID

This is the most efficient and preferred way to locate an element. Common issue with this is that the id’s are not unique on a page or is auto-generated. Both this should be avoided. A class on an html element is more appropriate than an auto-generated id.

Example:

<input id="searchText" type="text" name="q" value="" maxlength="256" placeholder=""></input>
WebElement element = driver.findElement(By.id("searchText "));

By Class Name

“Class” in this case refers to the attribute on the DOM element. Often in practical use there are many DOM elements with the same class name, thus finding multiple elements becomes the more practical option over finding the first element.

Example:

<div><span>Cheddar</span></div><div class="xyz"><span>Gouda</span></div>
List<WebElement> xyz = driver.findElements(By.className("xyz"));

Note: you can use class name to find single element also, if the className attribute is unique.

By Tag Name

The DOM Tag Name of the element.

 

By Name

Find the input element with matching name attribute.

Example:

<input id="searchText" type="text" name="q" value="" maxlength="256" placeholder=""></input>
WebElement search = driver.findElement(By.name("q"));

By Link Text

Find the link element with matching visible text.

Example:

<a href="http://www.google.com/search?q=selenium">Selenium</a>
WebElement linktext = driver.findElement(By.linkText("Selenium "));

 

By CSS

Like the name implies it is a locator strategy by css. Native browser support is used by default, so refer to w3c css selectors <http://www.w3.org/TR/CSS/#selectors> for a list of generally available css selectors.

Beware that not all browsersare equal, some css that might work in one version may not work in another.

By XPATH

At a high level, WebDriver uses a browser’s native XPath capabilities wherever possible. This should be used very carefully and should be the last resort. HtmlUnit driver and IE uses lower case where as Firefox is case sensitive.

Example:

<input type="text" name="example" /> 
<INPUT type="text" name="other" />
List<WebElement> inputs = driver.findElements(By.xpath("//input"));

Using JavaScript

You can execute arbitrary javascript to locate UI elements and as long as you return a DOM Element, it will be automatically converted to a WebElement object.

Example – Finding all the input elements to the every label on a page

List<WebElement> labels = driver.findElements(By.tagName("label"));
List<WebElement> inputs = (List<WebElement>) ((JavascriptExecutor)driver).executeScript("var labels = arguments[0], inputs = []; for (var i=0; i < labels.length; i++){" + "inputs.push(document.getElementById(labels[i].getAttribute('for'))); } return inputs;", labels);

Selenium – The AndWait and the waitFor Commands

Difference between “AndWait” and the “waitFor” Commands

The difference between a command and its AndWait alternative is that the regular command (e.g. click) will do the action and continue with the following command as fast as it can, while the AndWait alternative (e.g. clickAndWait) tells Selenium to wait for the page to load after the action has been done.

The AndWait alternative is always used when the action causes the browser to navigate to another page or reload the current page.

Note that, if you use an AndWait command for an action that does not trigger a navigation/refresh, your test will fail. This happens because Selenium will reach the AndWait‘s timeout without seeing any navigation or refresh being made, causing Selenium to raise a timeout exception.

In AJAX driven web applications, data is retrieved from server without refreshing the page. Using andWait commands will not work as the page is not actually refreshed. Pausing the test execution for a certain period of time is also not a good approach as web element might appear later or earlier than the stipulated period depending on the system’s responsiveness/Performance etc, leading to test failures. The best approach would be to wait for the needed element in a dynamic period and then continue the execution as soon as the element is found.

This is done using waitFor commands, as waitForElementPresent or waitForVisible, which wait dynamically, checking for the desired condition every second and continuing to the next command in the script as soon as the condition is met.

Selenium WebDriver – 5 Minute Getting Started Guide

Selenium 2.0 is commonly called as Selenium WebDriver  as it is integrated with WebDriver API. WebDriver is designed to provide a simple and concise programming interface in addition to addressing some limitations in the Selenium-RC API. Selenium WebDriver support dynamic web pages where element of a Page may change without the page itself being reloaded. Selenium-WebDriver makes direct calls to the browser using each browser’s native support for automation.

Continue reading “Selenium WebDriver – 5 Minute Getting Started Guide”

Page Load time using Firebug and Selenium

Firebug is a well known tool for debugging and page load time.It provides detailed timing information about Http traffic initiated by the page. The Net panel which collects all the data can be used to export it into HAR file.

Prerequisites

  1. Firebug – a Firefox plugin
  2. NetExport – Firebug extension for exporting data collected by the Net panel.
  3. Selenium 2 – Selenium is a suite of tools specifically for automating web browsers.

The sample test is developed using Java language. You can use any other language supported by Selenium.

Steps

  1. Download and install Firebug and NetExport. Also, make sure that both the files are kept in the same folder.
  2. Download Selenium selenium-server-standalone-X.XX.X.jar.

Below is the sample code.

import java.io.*;
import java.lang.InterruptedException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxProfile;

public class FirebugPerf {
public static void main(String[] args) {
FirefoxProfile profile = new FirefoxProfile();
File firebug = new File(“firebug-1.11.2-fx.xpi”);
File netExport = new File(“netExport-0.8.xpi”);
try
{
profile.addExtension(firebug);
profile.addExtension(netExport);
}
catch (IOException err)
{
System.out.println(err);
}
// Set default Firefox preferences
profile.setPreference(“app.update.enabled”, false);
String domain = “extensions.firebug.”;
// Set default Firebug preferences
profile.setPreference(domain + “currentVersion”, “2.0”);
profile.setPreference(domain + “allPagesActivation”, “on”);
profile.setPreference(domain + “defaultPanelName”, “net”);
profile.setPreference(domain + “net.enableSites”, true);
// Set default NetExport preferences
profile.setPreference(domain + “netexport.alwaysEnableAutoExport”, true);
profile.setPreference(domain + “netexport.showPreview”, false);
profile.setPreference(domain + “netexport.defaultLogDir”, “C:\\Firebug_Automation\\output\\”);
WebDriver driver = new FirefoxDriver(profile);

try
{
// Wait till Firebug is loaded
Thread.sleep(5000);

// Load test page
// You can add more scenarios and pages as required
driver.get(“http://google.com”);

// Wait till HAR is exported
Thread.sleep(60000);
}
catch (InterruptedException err)
{
System.out.println(err);
}

driver.quit();

}

}

Compile it and run it. You will get the .har file in output folder as defined in the preference.

profile.setPreference(domain + “netexport.defaultLogDir”, “C:\\Firebug_Automation\\output\\”);

Note: If you are using Selenium for functional automation you can modify above code and integrate it with your existing functional test.
Limitations

  1. This code is dependent on Firebug and hence will run only in FireFox
  2. The output is in .har file and to view this you need har file viewer.

For more info on this visit
http://www.softwareishard.com/blog/firebug/automate-page-load-performance-testing-with-firebug-and-selenium/

How to configure and use Selenium with C#

Step 1: Download Selenium Core, Selenium IDE and Selenium RC from the website http://seleniumhq.org/download/

Step 2: Installing the IDE. It consists of an XPI file that needs to be added in Firefox.

Step 3: Unzip the Selenium RC folder.

Step 4: To record Scripts, Open the IDE. To run the Selenium IDE, open Firefox and Select it from Firefox tools menu. Refer the screenshot below.

http://digitalab.org/wp-content/uploads/2014/08/IMG-20140706-00002.jpg

To start recording, click on the Red icon ( )

Step 5:

After recording the script, select C# format to convert the scrip in C# format.

ide

Step 6: Configure the .Net client driver.
.Net Client driver can be used with Microsoft Visual Studio. Launch Visual Studio and select new project of type Class Library.
Copy the converted code in the Class1.cs(default name) file and rename the file as required.
Add reference to the following dlls.
nunit.framework.dll
ThoughtWorks. Selenium.Core.dll
ThoughtWorks.Selenium.IntegrationTests.dll
ThoughtWorks.Selenium.UnitTests.dll

Step 7: Build the application.