Tuesday, 10 May 2016

How To Highlight Locators In WebDriver Test Cases

It's likely that you'll run into odd test behavior that makes you question the locators you're using in a test. But how do you interrogate your locators to make sure they are doing what you expect?
By leveraging some simple JavaScript and CSS styling, you can highlight a targeted element on the page so you can visually inspect it to make sure it's the one you want.

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;

public class HighlightElement {
    WebDriver driver;
    JavascriptExecutor js;

    @Before
    public void setUp() throws Exception {
        driver = new FirefoxDriver();
        js = (JavascriptExecutor) driver;
    }
    @After
    public void tearDown() throws Exception {
        driver.quit();
    }
// filename: HighlightElement.java
    private void highlightElement(WebElement element, int duration) throws InterruptedException {
        String original_style = element.getAttribute("style");

        js.executeScript(
                "arguments[0].setAttribute(arguments[1], arguments[2])",
                element,
                "style",
                "border: 2px solid red; border-style: dashed;");

        if (duration > 0) {
            Thread.sleep(duration * 1000);
            js.executeScript(
                    "arguments[0].setAttribute(arguments[1], arguments[2])",
                    element,
                    "style",
                    original_style);
        }
    }
   @Test
    public void highlightElementTest() throws InterruptedException {
        driver.get("http://the-internet.herokuapp.com/large");
        WebElement element = driver.findElement(By.id("sibling-2.3"));
        highlightElement(element, 3);
    }
}

Tuesday, 19 April 2016

Hybrid and Native Apps ?


The moment you consider investing in a mobile app, you’re immediately faced with a barrage of terminology. What’s the difference between iOS and Android? What are native, hybrid and web apps? More importantly, which is most appropriate for your and your app?

Native Apps

Native apps are what typically springs to mind when you think of an app. You download them from the App Store or Google Play, they sit within your device’s applications and you launch them by tapping their icon.

Developing Native Apps

Each mobile platform offers developers their own development tools, interface elements and standardised SDK. This should enable any professional developer to develop a native app relatively easily.
There are a number of advantages to writing apps in this way:
  They offer the fastest, most reliable and most responsive experience to users.
  They can tap into the wider functionality of the device; including the camera, microphone, compass, accelerometer and swipe gestures.
  Publishers can make use of push-notifications, alerting users every time a new piece of content is published or when their attention is required. This is a key method of engagement. You get the opportunity to continually bring your audience back for more.
  Users spend time on apps. The popularity of apps has increased enormously and is continuing to rise.

It’s not just about access to core device capabilities though, native apps, when well designed, respect the design patterns and standards of each platform. It goes beyond a left-aligned header on Android vs a center-aligned header on iOS, there’s hundreds of small differences in the design of user interactions on each platform. Taking them all into account means designing apps that are intuitive to use and play well with the rest of that platform’s ecosystem. Overall, going for native apps helps you create apps that are designed to delight your users.
The main downside of a native app is that it will not work with other kinds of devices. If you write an app in Objective-C for iOS, it’s not going to run on Android without being completely re-written in Java. When building for multiple platforms, developing a native app therefore can be quite expensive (when done from scratch), as it will require you to build and maintain multiple, separate versions of your app. It’s also common for developers to specialise in one platform, so often you’ll have to find different coders for each platform you want your app to be available for.
If your budget allows it, native apps are the ideal, offering the best user experience. When building from scratch and when multi-platform support is key, then be aware this can also be the most costly option.
What are Hybrid Apps?

Somewhere between native and web apps you’ll find hybrid apps. They are usually quicker to build (and thus cheaper) than native apps, but a step-up from what you can expect out of browser-based web apps. Is the hybrid app the best of both worlds?

The bulk of the app is built using cross-compatible web technologies, such as HTML5, CSS and Javascript — the same languages used to write web apps. Some native code is used however to allow the app to access the wider functionality of the device and produce a more refined user experience. For native apps, instead only native code is used. The advantage of this approach is obvious: only a portion of native code has to be re-written to make the app work on the different kinds of devices available.

An advantage that hybrid apps have over native is that it’s faster and easier to develop. It’s also easier to maintain and you can change platforms. The app itself will not be as fast as a native app as it still depends on the browser speed.

Getting your hybrid app to run appropriately on each platform generally takes substantial work. In some situations, the total cost might become comparable to that of fully native apps, rendering the cost benefits negligible. It all depends on how close you want to get to the “native user experience” or how simple your app is.

When the user accesses your web content online through a hybrid app, performance will be sluggish when compared with a native app.

Still, there’s one big advantage in hybrid apps.  Being built on one single core, you can add functionality and have multiple versions of the app all benefit from it. On the contrary, with native apps, for every new functionality you want to introduce, the feature will have to be replicated on each platform


Tuesday, 8 March 2016

How To Access Basic Auth with Selenium

The Problem

Sometimes you'll work with applications that are secured behind Basic HTTP Authentication ( Basic Auth). In order to access them you'll need to pass credentials to the site when requesting a page. Otherwise you'll get a system level pop-up prompting you for a username and password -- rendering Selenium helpless.
Before Selenium 2 we were able to accomplish this by injecting credentials into a custom header. But now the cool kid way to do it it was something like BrowserMob Proxy. Some people are solving this with browser specific configurations too.
But all of this feels heavy. Instead, let's look at a simple approach that is browser agnostic and quick to setup.

A Solution

By specifying the username and password in the URL when visiting a page with Selenium, we can a side-step the system level dialog box from Basic Auth and avoid the need to set up a proxy server. This approach will work for both HTTP or HTTPS pages.
Let's take a look at an example.

An Example

First let's import our requisite classes (for annotations (e.g.,org.junit.After, etc.), driving the browser with Selenium (e.g.,org.openqa.selenium.WebDriver, etc.), and matchers for our assertions (e.g., org.hamcrest.CoreMatchers, etc.)) and start our class with some setup and teardown methods.
// filename: WorkWithBasicAuth.java
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxDriver;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;

public class WorkWithBasicAuth {
    WebDriver driver;

    @Before
    public void setUp() throws Exception {
        driver = new FirefoxDriver();
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
    }


Now to add our test.

// filename: WorkWithBasicAuth.java
// ...
    @Test
    public void workWithBasicAuthTest() {
        driver.get("http://admin:admin@the-internet.herokuapp.com/basic_auth");
        String pageMessage = driver.findElement(By.cssSelector("p")).getText();
        assertThat(pageMessage, containsString("Congratulations!"));
    }

}
In the test we're loading the page by passing in the username and password in the front of the URL (e.g., http://admin:admin@). Once it loads we grab text from the page to make sure we ended up in the right place.
Alternatively, we could have accessed this page as part of the test setup (after creating an instance of Selenium). This would have cached the Basic Auth session in the browser, enabling us to visit the page again without having to specify credentials. This is particularly useful if you have numerous pages behind Basic Auth.
Here's what that would look like.
// filename: WorkWithBasicAuth2.java
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxDriver;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;

public class WorkWithBasicAuth2 {
    WebDriver driver;

    @Before
    public void setUp() throws Exception {
        driver = new FirefoxDriver();
        driver.get("http://admin:admin@the-internet.herokuapp.com/basic_auth");
    }

    @After
    public void tearDown() throws Exception {
        driver.quit();
    }

    @Test
    public void workWithBasicAuthTest2() {
        driver.get("http://the-internet.herokuapp.com/basic_auth");
        String pageMessage = driver.findElement(By.cssSelector("p")).getText();
        assertThat(pageMessage, containsString("Congratulations!"));
    }

}
NOTE: If your application serves both HTTP and HTTPS pages from behind Basic Auth then you will need to load one of each type before executing your test steps. Otherwise you will get authorization errors when switching between HTTP and HTTPS because the browser can't use Basic Auth credentials interchangeably (e.g. HTTP for HTTPS and vice versa).

Friday, 26 February 2016

Find out broken links / images on website using webDriver



Broker Links: 

By just seeing the Links in the UI, we may not be able to confirm if that link is working or not until we click and verify it.

To achieve this, we can use HttpClient library to check status codes of the URLs on a page.


If request was NOT processed correctly, then the HTTP status codes may not return 200 status code. We can easily say whether the link is broken or not with status codes.
Now let us jump into the example, First we will try to find all anchor tags on the page by using Webdriver. By using the below syntax:
We need to iterate through each link and verify request response Status codes and it should be 200 if not, we will increment invalid links count
Let us look into the example :


package com.linked; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClientBuilder; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FindBrokenLinksExample { private WebDriver driver; private int invalidLinksCount; @BeforeClass public void setUp() { driver = new FirefoxDriver(); driver.get("http://google.com"); } @Test public void validateInvalidLinks() { try { invalidLinksCount = 0; List<WebElement> anchorTagsList = driver.findElements(By .tagName("a")); System.out.println("Total no. of links are " + anchorTagsList.size()); for (WebElement anchorTagElement : anchorTagsList) { if (anchorTagElement != null) { String url = anchorTagElement.getAttribute("href"); if (url != null && !url.contains("javascript")) { verifyURLStatus(url); } else { invalidLinksCount++; } } } System.out.println("Total no. of invalid links are " + invalidLinksCount); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); } } @AfterClass public void tearDown() { if (driver != null) driver.quit(); } public void verifyURLStatus(String URL) { HttpClient client = HttpClientBuilder.create().build(); HttpGet request = new HttpGet(URL); try { HttpResponse response = client.execute(request); // verifying response code and The HttpStatus should be 200 if not, // increment invalid link count //We can also check for 404 status code response.getStatusLine().getStatusCode() == 404
if (response.getStatusLine().getStatusCode() != 200) invalidLinksCount++; } catch (Exception e) { e.printStackTrace(); } } }

-------------------------------------------------------------------------


Broken Images:

package com.linked; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClientBuilder; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.firefox.FirefoxDriver; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FindBrokenImages { private WebDriver driver; private int invalidImageCount; @BeforeClass public void setUp() { driver = new FirefoxDriver(); driver.get("http://google.com"); } @Test public void validateInvalidImages() { try { invalidImageCount = 0; List<WebElement> imagesList = driver.findElements(By.tagName("img")); System.out.println("Total no. of images are " + imagesList.size()); for (WebElement imgElement : imagesList) { if (imgElement != null) { verifyimageActive(imgElement); } } System.out.println("Total no. of invalid images are " + invalidImageCount); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); } } @AfterClass public void tearDown() { if (driver != null) driver.quit(); } public void verifyimageActive(WebElement imgElement) { try { HttpClient client = HttpClientBuilder.create().build(); HttpGet request = new HttpGet(imgElement.getAttribute("src")); HttpResponse response = client.execute(request); // verifying response code he HttpStatus should be 200 if not, // increment as invalid images count if (response.getStatusLine().getStatusCode() != 200) invalidImageCount++; } catch (Exception e) { e.printStackTrace(); } } }