Quantcast
Channel: Selenium – Vinsguru
Viewing all 69 articles
Browse latest View live

Keyword Driven Framework for Localization Testing using Selenium WebDriver

$
0
0

In this article, I would like to show how I have implemented my Keyword driven framework using Selenium-WebDriver for automated localization testing of a web based application.

Localization Testing can be defined as a process of customizing a software application to support any language. In localization, native language string is translated to target language & software GUI is modified appropriately & the different functionalities of a software application is verified for a particular locale. It includes verifying all the content translation, date format, number format, currency format, images, online help documents etc for the target audience.

Finalize Scope: Before working on the framework, at first, we need finalize the scope of our localization testing – (It is applicable for any work – not only for localization testing). For ex, languages to be verified, platform to be tested, functionalities to be covered as part of automated testing etc.

Identify the Test cases: Once the testing scope has been finalized, Identify the test cases to be automated. It should cover all the labels, images, number & date formats, currency formats, UI element’s field level validation, error messages, documents, help contents. The application should be able to handle all the special/accented/non-English characters properly.

Language Translation: Once the test cases have been identified, prepare a spreadsheet/property files which contains all the translation for each content of the application for the different languages, the application will support. (In my case, I get a spreadsheet from the BA in below format which I can directly include in my project).

loc01

The above key-value mapping is for the below page in our application.

For US English users  :  loc1b

For Spanish users     :   loc1a

 

Keyword Driven Framework: It is also called table-driven framework – in which the test script for an application is created using a set of keywords in a table format (usually using spreadsheet). This framework does not depend either on the automation tool  or the actual application under test itself.

Even though Keyword driven frameworks might take more time to create, there are many advantages in the framework.

  • Automation tool independent
  • Application independent
  • Programming language independent
  • Easy to read test scripts
  • Easy to add new test scripts & increases user productivity.
  • Very easy to maintain
  • No scripting knowledge is required to create test script
  • Test script can be created even when the application is not ready for test

Sample Keyword driven localization test script:

loc04

Step Step description for reporting purpose
Object Name Either object property of an element / Variable name containing the properties to find the element.
Action Action to be done on the element. like Click on a button, Enter some value in thetextbox etc.
  • In my Keyword Executor library – VerifyText action compares the innertext of the element against the vale in the ‘Param‘.
Param Parameters to be passed to the action.
  • ${label.new.examinee.firstname} : Contains the key from the translation file. So based on the language passed to the test, it reads the translations from the spreadsheet for the given key.
  • #{VARIABLE} : Any variable.
  • TEXT : If the Param does not have ${..} or #{..}, then the value in the cell is considered as the parameter to the action for the step.

 

Identify the Web Elements: In automated testing identifying a right test element is very important. We need some properties like id, name, xpath etc to uniquely identify an element. As I was a HP’s QTP (now it is called UFT) user before, I like its Object Repository concept to keep the properties to identify an element away from the test script. So, I create separate properties file for each page of the application – I still use Page Object Model. But properties are not hard-coded in the class file itself & instead it is read from the properties file – so that I do not need to build the class files in case of property change.

Sample Object Repository file for the above page:

loc03

 

How It Works:

  • First all the key value pairs for the language are read & stored in a HaspMap/Dictionary object.
  • All the steps from the spreadsheet for the given test case are read.
  • The application is launched for the particular language (In my case, I can adjust the language by adding locale code as parameter in the URL)
  • TestScriptExecution engine gets all the TestSteps & execute them one by one using KeywordLibrary

KeywordLibrary should handle all the possible actions. For example – ‘VerifyText’ – the below piece of code gets executed everytime.

key01

 

High Level Framework Design:

loc07

 

  • User is responsible for creating the test scripts in the keyword driven format in a spreadsheet as shown above.
  • Object repository file is updated once the application is ready.
  • Keyword driven tests refer to both Object repository file & translation files to execute a step.
  • BaseTest.java is a TestNG base class which has all the common methods. for ex to read the test script from the spreadsheet.
  • Locale is passed to the BaseTest via TestNG suite from Jenkins as given below.

loc09

Summary:

Thus a keyword driven framework for localization framework is implemented – all the test scripts are executed for the given test Environment, for the given Browser & for the given Language by the user using Jenkins.


Share This:


Continuous Regression Testing – Best Practises

$
0
0

In this post, I would like to show how I have implemented automated continuous regression testing process in my project. It is based on the Hybrid framework, I had implemented. I would request you to read the post on Hybrid Framework first if you have not.

Problem Statement:

  • We follow agile methodology & we have a release once in every 4 weeks. For every release, we push tons of new features into the existing application.As part of the addition of new features/requirements, we also introduce new defects in the existing application.
  • When we have 2 weeks for development, 1 week for QA & 1 week for deployment activities for a release, It is very hard to complete all the testing on all the new requirements & the regression testing to ensure that existing requirements of the application are still working as expected.
  • New code is pushed to the QA environment daily! So, even if some test cases pass today, they might fail the next day as code is frequently modified!!!
  • No one wants defect to be found in the last min as it is very costly to fix & it will also affect the release plan and subsequent releases. Detect defects as soon as they are introduced!!

Continuous Integration :

While developing a software, developers might check-in their code very often a day (at least once). This integration should be verified (using build tools, unit & integration tests) to ensure that software is not broken/developers do not introduce any defect. This process is called Continuous Integration & It is development practice to detect these code integration related issues as early as possible in the software development life cycle.

Above process is helpful in finding all the unit testing / integration testing related issues earlier. It might not find all the functional issues. Why do we, automation engineers, not follow the similar process to detect application functional defects earlier?

Automated Continuous Regression:

I have 3000 test cases in our automation regression suite which, an automated testing tool ,will take 90 hours to execute all the test cases as most of the test cases are very complex!!! All the 3000 test cases are split into multiple suite files based on the business functionality as given below in the picture 1.

hy007

We create a separate jenkins job for each suite file.(We use QTP for a project & Selenium-WebDriver for other. We use hybrid framework for both. So this process is not specific to QTP projects. It can be used for any automation testing project).

arch

Each jenkins job is scheduled to run daily @ 7PM by then we would have received the latest build from the development for the day with all the defect fixes. We have 10 slave machines connected to the jenkins master. So the entire automated regression suites are run daily by the jenkins master on different slave machines. By next day morning, All the 3000 test cases would have been executed & results would be ready ready for analysis.

Advantages:

  • Huge effort saving by automating 3000 test cases.
  • 0 hr spent in regression testing + few hours for result analysis.
  • Reduced time to market
  • Improved the code Qualtity.
  • Any new defects introduced today will be caught by next day morning.
  • It has greatly reduced the unnecessary dependency on the QA team for the Regression status.
  • Testing team focuses more on testing the new features planned for the release.

Dashboard:

We also have created below dashboard to display all the test case execution results for the past few weeks. This is helpful in triaging failed test cases. To know the build version in which a functionality was broken.

qdashbaord

Share This:

Selenium WebDriver – Blackbox Automated Testing using Arquillian Framework

$
0
0

I have been using Arquillian Graphene framework for more than a year for automated functional testing using Selenium WebDriver. I absolutely LOVE this framework. It is so easy to use and really helpful to keep your tests neat and clean by maintaining the test config in a separate file, by injecting the resources at run time when it is required etc.

 

What is Arquillian?

Arquillian is an integration/functional testing framework for testing JVM based application. It nicely integrates with other testing frameworks like JUnit/TestNG and helps to manage life cycle of the test and provides many other useful extensions. For functional browser automation, Arquillian provides Drone and Graphene extensions – both are built on top of Selenium WebDriver.

Arquillian is simply an extension to JUnit/TestNG frameworks. So If you already use JUnit and TestNG, you can just inlcude Arquillian w/o affecting your tests. Drone is for WebDriver managementGraphene is a wrapper around WebDriver with very nice utilities. So when you use all these, you do not miss any existing features of Junit/testNG/Selenium/WebDriver. You can add the jars and continue not to use any features of Arquillian Graphene if you do not like. Ie, your old code will still work fine. It does not force you to do anything! But please give sometime and You will love it!! [ It took some time for me 🙂 ]

Initially it was a bit hard for me to understand how it works as it was very confusing and I failed few times in finding all the maven dependencies to make it work. I am going to make it easy for you by showing you a very simple ‘Google Search’ project using Arquillian [the client mode].

 

Test run Modes:

Arquillian can run the tests in below modes.

  • Container
    • runs tests with container, manages life cycle of container including deployment.
    • Useful for developer’s integration tetsing
  • Stand-alone / Client
    • runs tests without container integration, only lifecycle of extensions is managed
    • allows to write tests independently of Arquillian containers and deployment management
    • For automated blackbox functional testing. [This is the mode we would be using for our tests]

Drone:

Drone is an Arquillian extension to manage the life cycle of the browser in the Arquillian tests. It helps to keep all the browser related test configuration in a separate file called ‘arquillian.xml’ outside of the java code. Drone simply takes care of WebDriver instance creation and configuration and then it delegates this session to Graphene.  Check here for more info.

Graphene:

Graphene is designed as set of extensions for Selenium WebDriver that focuses on rapid development and usability in Java environment. It has below nice features.

  • Page Objects and Page Fragments – Grahpene lets you write tests in a consistent level of abstraction using Page Objects and Page Fragments.
    • Better, robust and readable tests.
  • Guards the requests to the server which was raised by the interaction of the user with the browser.
  • Improved waiting API.
  • JQuery selectors as a location strategy.
  • AngularJS support
  • Browser/Driver injection to the test on the fly.
  • Can take screenshots while testing (see screenshooter extension), and together with other useful info generate neat reports (see Arquillian Recorder extension).

Lets create a simple project for WebDriver automation using Arquillian Grpahene.

Maven Dependency:

Include below mvn dependencies to bring the power of Aruqillian graphene into your existing Java-Webdriver automation framework. [I used TestNG extension for Arquillian framework. You can also use the JUnit extension]

Creating a simple Arquillian Project: 

  • Create a maven project in your favorite editor.
  • Include above maven dependencies in the pom file.
  • Add ‘arquillian.xml’ file to keep all your test configuration as shown here.

arq-01

  • We will use Firefox browser in our webdriver tests.
  • Creating a simple Google page object as shown here.

@Location("https://www.google.com")
public class Google {

    @Drone
    private WebDriver driver;

    @FindBy(name = "q")
    private WebElement searchBox;

    @FindBy(name = "btnG")
    private WebElement searchbutton;

    @FindByJQuery(".rc")
    private List <WebElement> results;

    public void searchFor(String searchQuery) {

        //Search
        searchBox.sendKeys(searchQuery);

        //Graphene gurads the request and waits for the response
        Graphene.guardAjax(this.searchbutton).click();

        //Print the result count
        System.out.println("Result count:" + results.size());

    }
}

  • Create a simple TestNG test to test Google search functionality.

@RunAsClient
public class Test1 extends Arquillian{

	  @Test(dataProvider = Arquillian.ARQUILLIAN_DATA_PROVIDER)
	  public void googleSearchTest(@InitialPage Google GooglePage) {
		 GooglePage.searchFor("Arquillian Graphene"); 
  }
}


  • If we run this test now, We can see TestNG doing the following.
    • automatically launches the firefox browser
    • access the Google site
    • searches for ‘Arquillian Graphene’
    • prints the search result count

Arquillian Graphene Features:

    • Driver Injection: If you notice the above Google page object / TestNG test class, We have not created any instance of the WebDriver.
      • This is because, Arquillian maintains all the test configuration in a simple file called ‘arquillian.xml’ where we mention we will invoke Firefox browser.
      • Now simply change the browser property to phantomjs to run this test on PhantomJS without touching Java code.
      • Check here for more information.
    • Request Guards:
      • Graphene provides a nice set of APIs to handle the HTTP/AJAX requests browser makes to the server.
      • We do not need to use any implicit/explicit WebDriver wait statements. Graphene takes care of those things for us.
      • Check here for more information.
    • JQuery Selectors:
      • Graphene also provides a JQuery location strategy to find the elements on browser.
      • My example above was very simple. To understand this better, include below code in the google page object.
      • Without JQuery selectors, If we need only the visible links, then we need to get all links and iterate all links objects and find only visible links.
      • With JQuery selectors, Grphene makes it very easy for us to find only visible elements. It improves the overall performance of your tests drastically.
 
   @FindByJQuery("a") 
   private List<WebElement> allLinks; 
   
   @FindByJQuery("a:visible")
    private List<WebElement> allVisibleLinks; 
  • Page Injection:
    • Like WebDriver/Browser injection, Graphene also injects the page objects on the fly.
    • You do not need to create an instance of the Page classes yourself in the code. Graphene takes care of those things for us.
    • Consider below example to see how Graphene makes the test readable and elegant.
    • Graphene ensures that Page objects are injected only when it is invoked in your tests. So All the elements of the page class will be available for you when you need it.
      • Grphene injects an instance of Order page into OrderPage variable only when this statement gets executed. OrderPage.enterPaymentInformation() in the below code.
      • There is no ‘new’ keyword anywhere in the script which makes the script looks neat 🙂

@RunAsClient
public class NewTest extends Arquillian {
	
	@Page
	Login LoginPage;
	
	@Page
	Search SearchPage;
	
	@Page
	Order OrderPage;
	
	@Test
	public void f() {  
		LoginPage.LoginAsValidUser();
		SearchPage.searchForProduct();
		OrderPage.enterPaymentInformation();
		OrderPage.confirmOrder();  
	}
}

  • Page Fragments:
    • Like Page Objects, Graphene lets you encapsulate certain elements & its behavior / decouple a HTML structure from the Page Object.
  • Javascript Interface:
    • Graphene lets you inject a custom Javascript code on the DOM and directly access the JavaScript object like a Java object in the code.
  • AngularJS application automation:
    • Protractor framework is not the only solution for AngularJS applications. Arquillian has a nice extension for finding angular elements.
    • Check here for more information.
  • SauceLabs / BrowserStack support:
    • Arquillian has an extension for BrowserStack. That is, the above script we have created can be simply run on any mobile device / platform / browser just by updating the arquillian.xml by including the browserstack account details.
    • I was just blown away when I was able to run all my tests w/o any issues in BrowserStack w/o touching the code.
    • Check here for more information.
  • Custom extension:
    • You can also implement your custom extension and include it in the framework.

Summary:

We saw the basic features of Arquillian Graphene framework and how it makes our test more readable with its browser and page objects injection on the fly and handling the HTTP/AJAX requests etc.

To know more check more posts under ‘WebDriver‘ category of this site.

Ex: How can we create a page object which requires less maintenance?

Check here for the answer : http://www.testautomationguru.com/arquillian-graphene-page-fragments/

 

Happy testing 🙂

Share This:

Selenium WebDriver – Advanced Page Object Pattern with Page Fragments using Arquillian Graphene

$
0
0

This is second post in Arquillian Graphene series. So, I would request you to read this post first if you have not already to get basic understanding of what Graphene is! Please note that Graphene is a framework / wrapper for Selenium WebDriver. So you do not miss any features of the WebDriver when you use Graphene. 

 

Problem with Page Objects:

Page objects is a well known design pattern, widely accepted by the automation engineers, to create separate class file for each page of the application to group all the elements as properties and their behaviors / business functionalities as methods of the class. But it might not be a great idea always, especially when the page has more / different sets of elements / complex element like a grid / calendar widget / a HTML table etc.

Code Smell – Large Class:

When you try to incorporate all the elements of a page in one single page class, it becomes too big to read, maintain etc. The class might contain too many responsibilities to handle. It should be restructured and broken into smaller classes.

I would expect my page objects to satisfy the Single Responsibility Responsible.

I personally prefer to create multiple levels of abstractions to satisfy that when I create my framework to come up with a robust, reliable, readable tests. I would like to show how It can be achieved using Arquillian Graphene – page fragments concepts.

Why Abstract:

  • Single Responsibility – A class should have one, and only one, reason to change.
  • Separation of concerns
  • Very easy to read code
  • Very easy to maintenance
  • Avoid redundancy

Page Fragments:

Concept wise it is same like Page Objects. Both Page Objects and Page Fragments, encapsulate some elements in the page and behaviors. Main difference between them is – When Page object encapsulates  a specific page, a page fragment encapsulates a component/element/widget in the page. So our page object contains all the page fragments instead of the page elements.

 

advanced-page-object-model

Google Search Page Object:

Lets consider the same google search page object we had created in the previous post.


@Location("https://www.google.com")
public class Google {
 
    @Drone
    private WebDriver driver;
 
    @FindBy(name = "q")
    private WebElement searchBox;
 
    @FindBy(name = "btnG")
    private WebElement searchbutton;
 
    @FindByJQuery(".rc")
    private List <WebElement> results;
 
    public void searchFor(String searchQuery) {
 
        //Search
        searchBox.sendKeys(searchQuery);
 
        //Graphene gurads the request and waits for the response
        Graphene.guardAjax(this.searchbutton).click();
 
        //Print the result count
        System.out.println("Result count:" + results.size());
 
    }
}

The above page object looks OK.

But did I consider all the navigation, elements or behaviors of the page? No!

If I try to add the Google search suggestions , search navigation etc then this class file becomes a very large class which is one of the code smells. It also becomes very difficult to maintain and make it less readable & less reliable.

This is where page fragments come into picture!!

Instead of placing all the elements we see in this page in a single class file, we encapsulate them in a different class file and make it available as part of the main page class.

Google Search Navigation:

Lets consider below section in google search page and see how it can be included in our test.

arq-page-frag-google-02

Create a separate class just like a page object – only consider those elements and their behaviors as part of the class.

public class GoogleSearchNavigation{
	
	@FindByJQuery("div.hdtb-mitem:contains('All')")
	private WebElement all;
	
	@FindByJQuery("div.hdtb-mitem:contains('Videos')")
	private WebElement videos;
	
	@FindByJQuery("div.hdtb-mitem:contains('Images')")
	private WebElement images;
	
	@FindByJQuery("div.hdtb-mitem:contains('Shopping')")
	private WebElement shopping;

	public void goToVideos(){
		System.out.println("Clicking on Videos");
		Graphene.guardAjax(videos).click();
	}
	
	public void goToImages(){
		System.out.println("Clicking on Images");
		Graphene.guardHttp(images).click();
	}
	
	public void goToShopping(){
		System.out.println("Clicking on Shopping");
		Graphene.guardAjax(shopping).click();
	}
		
	public void goToAll(){
		System.out.println("Clicking on All");
		Graphene.guardHttp(all).click();
	}	
}

Google Search Suggestion:

Lets consider below section in google search page and see how it can be included in our test.

arq-page-frag-google-03

Create a separate class as we did above for navigation part.


public class GoogleSearchSuggestions {
	
	@FindBy(css="li div.sbqs_c")
	private List<WebElement> suggesions;
	
	public int getCount(){
		return suggesions.size();
	}
	
	public void show(){
		for(WebElement s: suggesions)
			System.out.println(s.getText());
	}

}

I am just trying to print all the suggestions in the above example.

Google Search Result:

Lets include google search result section as well in our test.

I would like to consider only the blue color title and content in black color in my class.


public class GoogleSearchResults {

	@FindByJQuery(".rc")
	private List<GoogleSearchResult> results;
	
	public int getCount(){
		return results.size();
	}
	
	public void show(){
		System.out.println("\nResults:\n");
		for(GoogleSearchResult result: results)
			System.out.println(result.getResultHeader());	
	}
	
}

public class GoogleSearchResult {
		
	@FindBy(css="h3 a")
	private WebElement resultHeader;
	
	@FindBy(css="span.st")
	private WebElement resultText;
	
	public String getResultHeader(){
		return resultHeader.getText();
	}
	
	public String getResultText(){
		return resultText.getText();
	}	
}

Google Search Widget:

Lets also create a separate class for search text box and button.

arq-02


public class GoogleSearchWidget {
	
	@FindBy(name="q")
	private WebElement searchBox;
	
	@FindBy(name="btnG")
	private WebElement searchButton;
	
	public void searchFor(String searchString){
		searchBox.clear();
		
		//Google makes ajax calls during search
		int length = searchString.length();
		searchBox.sendKeys(searchString.substring(0, length-1));
		Graphene.guardAjax(searchBox).sendKeys(searchString.substring(length-1));
	}
	
	public void search(){
		Graphene.guardAjax(searchButton).click();
	}	
	
}

Google Search Page Object:

We need to refactor our google search main page object by including these page fragments. Our Page object becomes as shown here.

public class Google {
	
	@Drone
	private WebDriver driver;
	
	@FindBy(id="sbtc")
	private GoogleSearchWidget searchWidget;
	
	@FindBy(id="rso")
	private GoogleSearchResults results;

	@FindBy(id="hdtb-msb")
	private GoogleSearchNavigation navigation;
	
	@FindBy(css="div.sbsb_a")
	private GoogleSearchSuggestions suggestions;
	
	
	public void goTo(){
		driver.get("https://www.google.com");
	}
	
	public boolean isAt(){
		return driver.getTitle().equals("Google");
	}
	
	public GoogleSearchWidget getSearchWidget(){
		return searchWidget;
	}
	
	public GoogleSearchResults getSearchResults(){
		return results;
	}
	
	public GoogleSearchNavigation getTopNavigation(){
		return navigation;
	}
	
	public GoogleSearchSuggestions getSuggestions(){
		return suggestions;
	}
}

If you notice, I still use ‘FindBy‘ annotation. But instead of using plain WebElement, I use the Page fragments classes we have created. Above Google Search page object looks better than how it would have been if we had considered all the elements of the page in one single class. As you see we do NOT use any ‘new‘ keyword to create an instance of the fragments. Graphene makes it easy for us by automatically injecting the instance of the page fragments on the fly and delegates the behaviors of the page to the corresponding page fragment classes.

TestNG Test:

Lets create a TestNG test to test this google search behavior.

@RunAsClient
public class GoogleSearchTest extends Arquillian{

	@Page
	Google google;
	
	
	@Test(priority = 1)
	public void launchGoogle(){
		
		google.goTo();
		Assert.assertTrue(google.isAt());
		
	}
	
	@Test(priority = 2)
	public void canGoogleSuggest(){
		
		google.getSearchWidget().searchFor("Arquillian");
		google.getSuggestions().show();
		
		Assert.assertEquals(google.getSuggestions().getCount(), 4);
		
	}
	
	@Test(priority = 3)
	public void canGoogleShowResult(){
		
		google.getSearchWidget().searchFor("Test Automation Guru");
		google.getSearchWidget().search();		
		google.getSearchResults().show();

		Assert.assertEquals(google.getSearchResults().getCount(), 8);
		
	}	
	
	@Test(priority = 4)
	public void canGoogleNavigate(){
		
		//Navigate - assert : TBD
		google.getTopNavigation().goToVideos();
		google.getTopNavigation().goToShopping();
		google.getTopNavigation().goToImages();
		google.getTopNavigation().goToAll();
		
	}
	
}

When I run this test, I get the output as shown here.

 

arq-03

If you had noticed, I have not used any implicit / explicit  wait statements, or Thread.sleep(). Graphene has the request guards which know how long to wait for the HTTP/AJAX requests made by the application. We do not need to bang our heads against the wall for the page synchronization!!  Graphene will just take care!

Summary:

Like Page objects, Page fragments encapsulate certain components of the page and makes the test robust, reliable and readable. When a particular section of the page/class (like header / footer etc) gets repeated in other pages, We can create a class for it [page fragment] and include/inherit in all the page objects. Now, in case of any application change, we know where to update to make our test work!

Page Fragment does not have to be a single level of abstraction – We can also have multi level of abstraction using Page Fragments. [In the above example, GoogleSearchResults contains the list of GoogleSearchResult]

In Selenium WebDriver, whether a text box or a table, everything is a WebElement. But by using Graphene, we can create a reusable, application independent, Table – a page fragment for table object containing all the table specific methods like

  • getRowCount()
  • getColumnCount()
  • getCellData(row, column) etc

In your page objects, simply use FindBy annotation as you would do normally to find the table – the rest will be taken care by Graphene!!

 

Happy testing 🙂

Share This:

Selenium WebDriver – Google Voice Search automation using Arquillian Graphene

$
0
0

In this post, I would like to show you a fun project – automating google voice search using Arquillian Graphene.

 

This is 3rd post in our Arquillian Graphene series. Please read below posts if you have not already.

  1. Arquillian Graphene set up for Blackbox automated testing.
  2. Advanced Page Objects Pattern design using Page Fragments

 

Aim:

Aim of this project is to see if google voice search does really work properly 🙂 & to learn Graphene Fluent Waiting API.

Test steps:

  • Go to www.google.com
  • Then, Click on the microphone image in the search box. Wait for google to start listening.
  • Once it is ready to start listening, use some talking library to speak the given text
  • Once google stops listening, it will convert that to text and search
  • Verify if google has understood correctly

 

Talking Java:

In order to implement this project, first i need a library which can speak the given text. I had already used this library for one of my projects before. So I decided to reuse the same.

import com.sun.speech.freetts.VoiceManager;
 
public class SpeakUtil {

	static com.sun.speech.freetts.Voice systemVoice = null;
	
	public static void allocate(){
		systemVoice = VoiceManager.getInstance().getVoice("kevin16");
		systemVoice.allocate();
	}
	
	public static void speak(String text){
		systemVoice.speak(text);
	}
	
	public static void deallocate(){
		systemVoice.deallocate();
	}
}

 

Google Search Widget:

As part of this project, I would be modifying the existing page fragment we had created for google search widget. [the existing google search widget class details are here]

  • Identify the microphone element property in the google search text box & click on it.
  • Once it is clicked, google takes some time to start listening. Here we use Graphene Fluent Waiting Api. [Say no to Thread.sleep]
  • We add another method to wait for google to stop listening once the talking lib has spoken the text.
  • We need one more method to return the text from the search text box – this the text google understood.

 

After implementing all the required methods, our class will look like this

 

public class GoogleSearchWidget {
	
	@FindBy(id="gsri_ok0")
	private WebElement microphone;
	
	@FindBy(name="q")
	private WebElement searchBox;
	
	@FindBy(name="btnG")
	private WebElement searchButton;
	
	public void searchFor(String searchString){
		searchBox.clear();
		
		//Google makes ajax calls during search
		int length = searchString.length();
		searchBox.sendKeys(searchString.substring(0, length-1));
		Graphene.guardAjax(searchBox).sendKeys(searchString.substring(length-1));
	}
	
	public void search(){
		Graphene.guardAjax(searchButton).click();
	}
	
	public void startListening(){
		
		//wait for microphone
		Graphene.waitGui()
				.until()
				.element(this.microphone)
				.is()
				.present();
		
		microphone.click();
		
		//wait for big microphone image to appear
		//this is when google starts listening
		Graphene.waitGui()
				.until()
				.element(By.id("spchb"))
				.is()
				.present();
	}
	
	public void stopListening(){
		
		//wait for the microphone image to hide
		//at this point google will stop listening and start its search
		Graphene.waitGui()
				.until()
				.element(By.id("spchb"))
				.is().not()
				.visible();
	}
	
	public String getVoiceSearchText(){
		
		Graphene.waitGui()
				.until()
				.element(this.searchBox)
				.is()
				.visible();
		
		return this.searchBox.getAttribute("value");
	}
}

Chrome Options:

We need to add below chrome options while launching chrome – so that chrome can use the system microphone. Otherwise, it will show a popup to ‘Allow’ which will prevent us from automating the feature. We can add this in the arquillian.xml as shown here.

google-mic

   <extension qualifier="webdriver">
      	<property name="browser">chrome</property>
      	<property name="chromeDriverBinary">path/to/chromedriver</property>
      	<property name="chromeArguments">--use-fake-ui-for-media-stream</property>
   </extension>

 

TestNG Test:

We add a new test for this. I will pass some random text for the SpeakUtil to speak and google for search.


public class GoogleVoiceTest extends Arquillian{
	
	@Page
	Google google;
	
    @BeforeClass
    public void setup(){
    	SpeakUtil.allocate();
    }
		    
    @Test(dataProvider = "voiceSearch")
    public void googleVoiceSearchTest(String searchText){
    	
    	google.goTo();
    	
		//start listening
    	google.getSearchWidget().startListening();
		
		//speak the given text
    	SpeakUtil.speak(searchText);
		
		//wait for google to stop listening
    	google.getSearchWidget().stopListening();
    	
		//assert if google has understood correctly
    	Assert.assertEquals(searchText, 
							google.getSearchWidget().getVoiceSearchText().toLowerCase());
    }
    
    @DataProvider(name = "voiceSearch")
    public static Object[][] voiceSearchTestData() {
		
	   //test data for google voice test
       return new Object[][] {
    		   {"weather today"}, 
    		   {"show me the direction for atlanta"}, 
    		   {"magnificent 7 show timings"}, 
    		   {"will it rain tomorrow"}, 
    		   {"arquillian graphene"}
       };
    }
    
    @AfterClass
    public void deallocate(){
    	SpeakUtil.deallocate();
    }
}

Results:

Google was able to understand mostly what talking lib spoke. However It could not get ‘arquillian graphene’ 🙁

google-voice-test-results

 

Summary:

It was really fun to automate this feature – activating microphone, letting the talking lib talk and google trying to listen etc. If you are trying to do this, ensure that no one is around 🙂 & Looks like I already got my family members irritated by running this test again and again!! So I will stop this now!

All these scripts are available in github.

Happy Testing 🙂

 

Share This:

Selenium WebDriver – Running the automated test in cloud

$
0
0

We have been using Selenium WebDriver, QTP, JMeter etc in our organization for the automated functional and performance testing. I setup the complete test automation infrastructure and used to do the maintenance. Initially it was fun and later managing everything (Selenium, QTP, JMeter,Influx, Grafana etc) started eating up most of my time. I had to do the testing on multiple browsers and platforms.  On top of that we also wanted to add mobile testing in the scope. Setting up a mobile-lab is not fun. There are so many devices in the market. We can not keep buying new devices every time & update the OS etc. Then I realized that spending money on cloud based services are cost effective and scalable. It will free us our time to concentrate more on developing new tests instead of maintaining the infrastructure.

Now I have been using BrowserStack for our web automated testing on various OS, browsers, mobile devices (iOS and android).

In this post, I would like to show how I achieve this easily using arquillian-drone & graphene.

Arquillian Graphene:

This is 4th post in our arquillian-graphene series. Please read below posts as well if you have not.

  1. Arquillian Drone – Setup
  2. Graphene – Advanced Page Objects using Page fragments
  3. Graphene – Handling Ajax Calls – Fluent Wait API

Arquillian Graphene is a simple wrapper around Selenium WebDriver which gives very powerful utilities for your selenium tests. If you use java for WebDriver automation, then you should definitely give a try. As it is a wrapper, it does not mess up with your existing test scripts. If you want any of the arquillian-drone/graphene features, you can use, otherwise ignore.

Why Arquillian framework:

Arquillian is a simple extension to JUnit/TestNG frameworks. Arquillian itself comes with many extensions and easy to write your own extension.

Arquillian framework maintains all the test configuration in a xml file called arquillian.xml.

We simply maintain all the WebDriver related configurations in this xml file. Whenever we need the driver instance in our test, we use this @Drone annotation as shown below to get the driver injected. So we do not have to write a lot of code to instantiate different browser drivers. Arquillian takes care of all these things for us. All the browser capabilities can be added in the arquillian xml.

	@Drone
	private WebDriver driver;
	
	public String getTitle(){
		return driver.getTitle();
	}

Running Test Remotely:

I am going to reuse the same test which I had already created as part of this post. Graphene – Advanced Page Objects using Page fragments

Arquillian framework comes with an extension for BrowserStack / SauceLabs.  As I already have BrowserStack subscription, I would be using the BrowserStack extension.

I only had to do 2 updates in my framework to get my tests executed remotely by BrowserStack. 

  • Add Maven dependency for arquillian-browserstack extension
    <dependency>
        <groupId>org.jboss.arquillian.extension</groupId>
        <artifactId>arquillian-drone-browserstack-extension</artifactId>
    </dependency> 
  • Add below properties in the arquillian.xml to run the test on MAC os in chrome browser
	<extension qualifier="webdriver">
        <property name="browser">browserstack</property>
        <property name="username">***********</property>
        <property name="automate.key">**************</property>
        <property name="browserName">chrome</property>
        <property name="platform">MAC</property>
        <property name="browserstack.debug">true</property>
   </extension>	

That is it!! I am set to run all my tests remotely in BrowserStack. I do not have to touch my existing code at all.

 

 

If I need to run my tests on a mobile device, I do not need appium/selendroid. Arquillian + BrowserStack will take care of it just by updating the arquillian.xml as shown here.

   <extension qualifier="webdriver">
        <property name="browser">browserstack</property>
        <property name="username">***********</property>
        <property name="automate.key">**************</property>
        <property name="browserName">iPad</property>
        <property name="platform">MAC</property>
        <property name="os">ios</property>
        <property name="device">iPad Pro</property>
        <property name="browserstack.debug">true</property>
   </extension>

Summary:

Arquillian is the best framework I have ever used for JVM/Functional testing. It helps us to write very neat, clean code by keeping the webdriver configurations in a separate file. For the page objects, We do not need a page factory to give us the page object. ‘@Page‘ annotation will give us the page object where ever you need it. Instead of creating a complex page object it also help us to create different page fragments – by decoupling the HTML structure of the page. Check here for more info.

Happy Testing 🙂

 

Share This:

Selenium WebDriver – Automating Custom Controls – JQuery Slider

$
0
0

As an automation engineer, you might very well know how to interact with default HTML elements like text box, radio button, image, check box etc. Selenium WebDriver considers all these elements as WebElement & provides a set of methods to play with these elements.

Sometimes It adds unnecessary confusions. For ex: While working with a radio button, webdriver identifies this as a WebElement. This interface has a getText method which does not seem to add any value for a radio button. As per the implementation, getText method returns the innetText of an element. As radio buttons, made of HTML INPUT tag, can not hold any text inside. So, It will always return null. For this element, we would be mostly interested in getting the value attribute. Not the innerText. This particular issue is applicable for check boxes and text boxes as well.

In order to avoid this confusion, we can add another level of abstraction to the WebElement using ‘Composition over inheritance’ principle. One such example would be drop down boxes in Selenium WebDriver. A drop down box is mostly used as a Select instead of WebElement. So only the required methods are available for Select.

Select s = new Select(webelement);
s.selectByVisibleText(txt);

So, a text box can also be designed as shown here.  By wrapping the WebElement with TextBox, we hide all the unwanted methods from client accidentally invoking it.

This same idea can be used to automate custom controls as well.

Custom Controls:

Modern web applications with the use of HTML5 / CSS3 / JavaScript API / JQuery UI come with many stunning, user friendly, specially made controls to interact with the applications. Lets consider JQuery Slider for example. JQueryUI with the help of css and js make a div and span elements look like a real slider.

 

Sometimes, these elements could be present in multiple pages in our application. So, It makes perfect sense for us to wrap this as a Slider element to include in our Page Object Model instead of identifying them as WebElements. Otherwise we might end up having duplicate codes or multiple helper classes etc.

Page Object with a Slider:

Lets create a simple Page Object Model for this page. Our aim here is to test only the slider. Lets assume other contents in the pages are always fine – so we can ignore them.

My Page Object Model for this page would be as shown here.

The above POM has a Slider & its implementation is as shown here.

 

Thus all the unwanted methods of WebElement has been removed for the user.

Lets test if the slider is working as expected.

 

After the test execution, the result came as success.

slider-001

Summary:

To model a Slider, we added an abstraction layer for a WebElement. Using the same concept, we can also model other complex elements like Date Picker, Progress bar etc. By doing so, we improve the code readability, maintainability & re-usability. Now If even these elements are present in multiple pages, we can simply find them as Slider as shown below.

@FindBy(id="slider")
private Slider slider;

 

Happy Testing & Subscribe 🙂

 

 

Share This:

Best Practices – Building Robust Test Automation Framework

$
0
0

Test Automation – A Brief History:

I still remember – It was sometime in 2004. I was thrilled when I first saw QTP (now it is UFT) playing the recorded script – launching a browser, entering test data and submitting the page etc. QTP was dominating the test automation world at that time and It was very expensive. Not everyone could afford. That is when I had started my career in IT.

Most of the people had no idea about test automation frameworks at that time. Developers were not involved in test automation & QA people were mostly doing record and playback with simple parameterization. They would come up with some best practices & improve their tests based on their past mistakes. Mostly the scripts required more maintenance work due to poor design. Most of the QA people would not have any idea about the design patterns/principles.

Suddenly the mobile devices started popping up everywhere, cloud technologies came up, many complex web-based applications were built, agile methodology was followed…etc. During this time everyone understood the importance of test automation. Once Selenium WebDriver has been introduced which is FREE and Open source in the same time, It got everyone’s attention. Some QA/Dev became SDET (Software Development Engineer in Test), introduced design principles and built better frameworks.

Role Of SDET:

SDET’s role is very significant in building a robust test automation framework. Once I had a chance to take a look at the test framework created by a Software Architect who was architect of the application under test. They had implemented all the latest technologies like micro services at that time which was great. But the test framework was created like a unit/integration testing framework. They were using DB dump files for data provisioning. Before they start the automated test, they need to get rid of all the data and table structure from the DB and they recreate all the test data using the file. This process used to take 30-45 mins every time.  Obviously they were able to run their tests only in the lower environment. They can not run these tests in the higher environments due to DB access. The tests were tightly coupled with this DB import process.

In order to build a robust test automation framework, We should have both the mindset of both QA + Dev & have a very good understanding of 

  • OOPs concepts
  • Design principles
  • Design patterns
  • QA specific challenges

 

Basic Requirements of a Test Automation Framework:

  • Tests should be easy to read and follow.
    • I personally do not prefer any ‘new’ keywords in my tests. No variables / objects initialization in the tests.
    • Anyone/less technical person should be able to contribute in test automation
    • Keywords/BDD style should help here
  • Ability to add new tests
    • Time to add a new test into the existing suite should be less.
    • Design patterns / SOLID design principles should help here.
    • Use business keywords to build new tests like login,logout, search, order, edit, cancel etc
  • Abstract away low level commands.
    • Use Advanced Page Object design pattern
    • Tests should talk to Page Objects, Page Objects talk to Page Forms / Components / Fragments which in turn talks to WebDriver API
    • There should not be any driver.findElement() in the tests.
    • No thread.sleep anywhere in the tests
    • Use fluent wait APIs for page synchronization

advanced-page-object-model

  • Separate locator from page objects
    • Separate the locators from the page objects – keep them in a separate files like properties /XML / JSON / CSV
  • Separate test data from tests
    • Do not use any hard coded test data in the tests / page objects
    • Test data should be maintained in a separate files like XML / JSON / CSV
    • This will make your tests data-driven
  • Easy data provisioning
    • Tests might expect some data to present in the application. Such data should be created by the tests itself automatically.
    • Each tests should have a setUp and tearDown methods to create and delete the test data.
    • Avoid direct DB calls for data provisioning which will make your tests run only in the lower environments.
    • Use the application APIs – This is the best approach for data provisioning.
    • Use the application features like import/export for data provisioning.
  • Easy maintenance
  • Ability to integrate with other tools like junit/testng/ant/maven/jenkins etc
    • The tool/framework we choose should support CI/CD process.
  • Version Control
    • Keep track of all the changes
  • Ability to run the automated test scripts in any given environment like QA, Pre-Production, Production
    • As part of CI/CD process, the test automated tests should be able to run in any environment – including production.
    • Use of config files – one of each test environment
    • Jenkins should be able to override these configs at run time.

ufts-09

  • Ability to perform multiple types of testing
    • from a simple smoke test to full regression tests
  • Ability to execute specific suites/modules
    • Huge automated tests should be categorized based on the modules / business functionalities – so that a specific module can be run at any time.
    • Each suite/module should be a separate job in Jenkins
  • Ability to execute tests in parallel
    • In order to minimize the overall test execution time, our test automation framework should support parallel test execution.
    • We need to be careful that the test data used by 1 test does not affect other test which could run in parallel.
    • If tests are dependent for some reason, then they all should be in the same suite.
  • Continuous Integration / Delivery process
    • The automated tests should get triggered as part of CI/CD pipelines.
    • As soon as the new version code is promoted to an environment, a smoke test should also be performed automatically.
    • Based on the changes in module of the application, a corresponding regression suite should get triggered.
    • It helps us to reduce the overall QA cycle time drastically.
  •  Easy to share the results
    • As soon as a smoke test is performed, send out an email notification with the status to all the team members
    • Create a nice HTML report with steps performed

asm002

  • Easy to debug
    • Report should have all the steps performed with time stamps + screenshots for easy debugging the failed tests.
    • Results history should be maintained in a separate DB

 

Summary:

We should consider the above capabilities while designing our test automation framework to come up with a more reliable, robust automation scripts to test products/features we launch. By using business keywords/feature files, we should be able to add new tests. CI process helps us to detect any defects as soon as it has been introduced. Thus overall time to market is greatly reduced.

 

Happy Testing & Subscribe 🙂

 

 

Share This:


Selenium WebDriver – Automating Custom Controls – JQuery Sortable Elements

$
0
0

We already have seen automating a custom control – JQuery Slider – in this article. I would request you to read that article first, if you have not already. We are going to see automating JQuery Sortable Elements in this post.

Goal:

To model a wrapper element for these sortable items. So that user can move items by index or item name.

JQuery Sortable Element:

It is basically a list of WebElements with drag and drop support. Our aim here is to make an element move to a new position by the index or the text.

Since we are going to find an element by text, I use a map and store the elements reference.

Page Object:

This is a very simple page object which just contains only a Sortable Element. Where ever a sortable element is found, We find by them using @FindBy mechanism as we do for a simple WebElement.

Test:


Summary:

By simply adding an abstraction layer, we control a complex element like a simple WebElement.  Now if the behavior changes / a new feature has to be added, modifying Sortable element class will do the trick for us.

Happy Testing & Subscribe 🙂

 

 

Share This:

Selenium WebDriver – Finding WebElements Using Map

$
0
0

In this article, Lets see how we could find elements using Selenium WebDriver when there are no proper locators.

Problem Statement:

I have a web application in which I have around 1800 HTML elements to deal with! It is a very heavy page. The challenge is here not only the number of elements – but also the locators. Most of elements do not have any proper locators. I had to find the elements using the associated label. But the labels itself are dynamic!!! In my BDD style framework, I will get the associated label of the element to interact with. It could be anything which I can not hard code in my test. The approach had to be generic.

Hopefully you get the challenge I had!!

I was asked to find a better solution here – I was looking for some robust approach, then I ended up having – Find-By-Map – approach which works just great!

As I might not be able to share my actual application details, Lets use some common application to understand my approach better.

Demo Application:

Lets consider this sample application – http://phptravels.net/admin – This is a sample application to practice selenium.

Credentials:

username : admin@phptravels.com

password : demoadmin
Lets go to this page – http://phptravels.net/admin/locations

demo-application-001

Complexity wise, it is not very close to my actual application. But I can explain the approach using the above table. Each city in this table has a check box, edit button and delete button. It also has other information – Lets ignore that. Cities are dynamic. City name could be anything. Lets assume you have a requirement to click on a check box / edit button / delete button for a given city.

For ex:

  • Click on Edit button for Atlanta
  • Click on the Delete button for Delhi etc.

For each city, I had to collect the check box, Edit button and Delete button.

demo-application-003

Creating a JavaScript Map:

I wanted to create a map as shown here.

So that I could use the map to get the element. That is,

map.get("Atlanta").get("CheckBox").click()

In order to create the above map, I inject below javascript code.

 

I verified my javascript in the chrome console.

demo-application-005

 

Once JavaScript is verified in your chrome console, we can use JavascriptExecutor to convert the HTMLElements to WebElements.

Find Elements Using Map:

That is it!!! You have found all the elements, we are interested in, on the page and created a map. Now Lets test this. (I ignored the navigation part to test this page)

I could get the city name and element to be clicked as parameters to do operations on this table. It just works great!!

If you do not like to inject JavaScript. We could find this using java itself as shown below.

Demo:

Summary:

I prefer JavaScript approach. Because, I was looking for a very generic approach. So that I could have my own annotation to inject and convert the HTMLElements to WebElements. The complexity to find elements is hidden in the js file.

@FindByJS("js-injection-file.js")
private Map map;

JavaScript approach is littler bit faster. But nobody cares of performance in Functional Test automation which makes sense. Another advantage is you could inject JQuery like libs to make use of the lib features in your JavaScript file.

 

Happy Testing & Subscribe 🙂

 

 

Share This:

Selenium WebDriver – Design Patterns in Test Automation – Factory Pattern

$
0
0

Overview:

As a software engineer, We all encounter some problems while designing a software. So what do we do when we face a problem? We google for solutions immediately. Don’t we? We google because we know that we would not be alone and someone would have already found the solution, for the problem we are facing now, which we could use to solve.

Design patterns are the solutions for the problems which you might face in your software design!!

Design Patterns are well optimized and reusable solutions to a given problem in software design. It helps us to show the relationship among the classes and the way in which they interact. Design pattern is a template which you have to carefully analyze and use it in appropriate places.

More information on design pattern can be found here.

 

Design Patterns in Test Automation:

As an automated test engineer, should we really care about design principles and patterns? Why do we need to learn/use Design Patterns in functional test automation?

After all, Test automation framework/automated test case is also a software which is used to test another software. So, we could apply the same design principles/patterns in our test automation design as well to come up with more elegant solution for any given design related problem in the test automation framework.

Remember that Design Patterns are NOT really mandatory. So you do not have to use them! But when you learn them, you would know exactly when to use! Basically these are all well tested solutions. So when you come across a problem while designing your framework/automated test cases, these design patterns could immediately help you by proving you a formula / template & saves us a lot of time and effort.

Note: Your aim should not be to implement a certain pattern in your framework. Instead, identify a problem in the framework and then recognize the pattern which could be used to solve the problem. Do not use any design pattern where it is not really required!!

In this article, We are going to see where we could use the Factory Pattern.

 

Factory Pattern:

Factory Pattern is one of the creation Patterns. It is mostly used when we need to create an object from one of several possible classes that share a common super class / implements an interface. It creates objects without exposing the instantiation logic to the user. We, as the user, refer to the newly created object through a common interface.

Best example is – WebDriver.

fac001

As all these Chrome/Firefox/Safari/IE driver concrete classes implement this WebDriver interface, We are able to refer to the, ChromeDriver/FirefoxDriver etc, instance through the WebDriver interface without much change in the code.

Problem in Creating WebDriver Instance:

Even though the above concrete classes implements a common interface, We need to follow different approaches in creating an instance from one of these concrete classes which depends on the browser instance we might want to use.

For ex: ChromeDriver requires a Driver Server setup but Firefox (till version 45) does not need anything.

WebDriver driver = new FirefoxDriver();

The above code simply works – but the below code might not unless we set driver server executable.

WebDriver driver = new ChromeDriver();

But we know how to solve!!

The easiest solution is – to put all the logic in a if else block!! right?

It might look like an easy solution. But it is really NOT. When we have to start/stop the Driver Service ourselves, the code becomes significantly larger and very difficult to maintain.

Factory Pattern in Creating WebDriver Instance:

Lets see, How we can address this using a Factory Pattern. Test classes, as the users, should not really care how the drivers are actually created. What it needs is just a WebDriver instance to execute the given test case. So we come up with our own abstract class – DriverManager – which test classes could use to get a driver instance from it and use them in their tests.

fac002

Lets see the sample concrete implementation.

 

Driver Manager:

Chrome Driver Manager:

Driver Types:

Driver Manager Factory:

Factory Pattern Test:

 

fac003

If the test class has to use Firefox, just use as given below.

driverManager = DriverManagerFactory.getManager(DriverType.FIREFOX);

 

Summary:

By using Factory Pattern, we completely hide the creational logic of the browser / service instances to the test classes. If we get a new requirement to add a new browser, say PhantomJS, should not be a big deal. We just need to create a PhantomJSDriverManager which extends DriverManager. [Ofcourse you have to add PhantomJS in DriverType]

Design Pattern is a very good tool for effective communication. How? As soon as we name a pattern, Others can immediately picture the high-level-design in their heads & get the solution for the given problem. Thus, Design Pattern enables us to explain the design in a much better way.

Happy Testing & Subscribe 🙂

 

 

Share This:

Selenium WebDriver – Design Patterns in Test Automation – Strategy Pattern

$
0
0

Overview:

As a software engineer, We all encounter some problems while designing a software. So what do we do when we face a problem? We google for solutions immediately. Don’t we? We google because we know that we would not be alone and someone would have already found the solution, for the problem we are facing now, which we could use to solve.

Design patterns are the solutions for the problems which you might face in your software design!!

Design Patterns are well optimized and reusable solutions to a given problem in software design. It helps us to show the relationship among the classes and the way in which they interact. Design pattern is a template which you have to carefully analyze and use it in appropriate places.

More information on design pattern can be found here.

 

Design Patterns in Test Automation:

As an automated test engineer, should we really care about design principles and patterns? Why do we need to learn/use Design Patterns in functional test automation?

After all, Test automation framework/automated test case is also a software which is used to test another software. So, we could apply the same design principles/patterns in our test automation design as well to come up with more elegant solution for any given design related problem in the test automation framework.

Remember that Design Patterns are NOT really mandatory. So you do not have to use them! But when you learn them, you would know exactly when to use! Basically these are all well tested solutions. So when you come across a problem while designing your framework/automated test cases, these design patterns could immediately help you by proving you a formula / template & saves us a lot of time and effort.

Note: Your aim should not be to implement a certain pattern in your framework. Instead, identify a problem in the framework and then recognize the pattern which could be used to solve the problem. Do not use any design pattern where it is not really required!!

In this article, We are going to see where we could use the Strategy Pattern which is one of the Behavioral Patterns.

Strategy Pattern:

Goal: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.

That is, Strategy Pattern is useful when we have multiple algorithms for specific task and we want our application to be flexible to choose any of the algorithms at run time for specific task.

Still confused? No Worries!

Lets take Google application as always we do.
We could search with simple keywords by typing in the text box. Or We could say few keywords using voice search. In both cases, Google does the search and shows us the results.
So, Google has implementations for 2 different strategies to get the input from user. As a user, it is up to you to choose the search method – either voice search or text search. Then Google uses appropriate strategy to collect the keywords and send it to its engine to fetch the results.

strategy-uml

Yet another example, Lets assume in your test framework, you want to create some custom reporting utility. You want this utility to create the report in any of these HTML/JSON/XML/CSV formats. You should have a strategy for each format. Then you choose the strategy for the format you need to create the report.

If you find any other similar requirement, Strategy Pattern will be extremely useful there.

 

Strategy Pattern in Google Page object:

We are going to create a Google Page object and we will use these different strategies for the search. We do not want the Page object to do any search. Instead, It will contain an object which is implementing the interface ‘SearchStrategy’.  Google page class will delegate the search work to the object.

strategy-pattern

SearchStrategy:

 

Text Strategy:

 

Voice Strategy:

Check here for actual implementation.

Google Page Object:

Strategy Pattern Test:

Test Results:

strategy-results

Summary:

By using Strategy Pattern, we completely hide the search algorithm in the Google page class. Test classes choose the search method they want. In future, If we need to add different Search Strategy, you need to create a new class implementing the interface. You do not modify any existing classes you have created already which is cool. If we touch a working code for modification, there is a chance that we introduce a new defect!! By using composition, Google page simply delegates the search work and make the Google page class very flexible.

Design Pattern is a very good tool for effective communication. How? As soon as we name a pattern, Others can immediately picture the high-level-design in their heads & get the solution for the given problem. Thus, Design Pattern enables us to explain the design in a much better way.

Happy Testing & Subscribe 🙂

 

Share This:

Selenium WebDriver – Dependency Injection using Guice

$
0
0

In this article, we will see the use of Dependency Injection using Guice lib and how it helps us to come up with more readable, reusable page objects and tests.

Dependency Injection:

Lets this consider this simple Page Object for Google page.

public class Google {

    private final WebDriver driver = new ChromeDriver();

    public void goTo() {
        this.driver.get("https://wwww.google.com");
    }

}

Assuming chrome driver server system properties have been set already, there is nothing wrong here. The code will just work fine.

Google google = new Google();
google.goTo();

But what will happen if we need to make the test work for a different browser? We have to modify the class, right? Because it is tightly coupled. How many classes will we modify like this?
Lets see if we could modify slightly as shown below.

public class Google {

    private final WebDriver driver;

    public Google(WebDriver driver) {
        this.driver = driver;
    }

    public void goTo() {
        this.driver.get("https://wwww.google.com");
    }

}

In this above class, we do not want to create the new instance of the WebDriver. But it is a dependency required for this class to function as expected. So, We have designed the class in such a way that this dependency will be injected by the test / whoever creates the instance of this class. This approach makes the classes loosely coupled, but the dependencies have to be injected by the invoking classes. If it is a page object, the testng/junit tests should take care of creating the WebDriver instance and pass it to the constructor of this class.

Google google = new Google(driver); //constructor injection
google.goTo();

We could also inject the dependency by using setters method.

Google google = new Google();
google.setDriver(driver); //setter injection
google.goTo();

The Google page object has the hard coded URL. But in reality, we need to run our automated tests in Dev / QA / Staging / PROD environments. So we can not hard code the URL in our page objects. So even the URL should be injected.

public class Google {

    private final WebDriver driver;
    private final String URL;

    public Google(WebDriver driver, String URL) {
        this.driver = driver;
        this.URL = URL;
    }

    public void goTo() {
        this.driver.get(URL);
    }
}

Hm… It looks better now, rt?  Yeah, the page object might look better. What about the junit/testng test class which is going to use it? The test class has to take care of all the dependencies required for this page object. With all the driver instance creation logic, fetching the url from some property files etc, the test class will look ugly for sure!!!

As part of our functional test automation, we might have created tons of page objects with a lot of other dependencies.  Creating & maintaining the life cycle of the driver, page objects, utility classes like property file readers, reporting utility, logger etc make the framework very difficult to maintain.

Creating instances are painful sometimes. For ex: WebDriver.  If you are not using a Factory Pattern as mentioned in this article and you are directly creating a WebDriver instance in the Test class/Page object itself, It will make your class bloated, less readable and difficult to maintain.

How can we have an automated dependency injection in the framework? How can we write less number of code & achieve whatever we wanted to have?

There is a library from Google which could help us here.

Guice (pronounced as ‘juice’)

Guice is a Dependency Injection framework and most of the Java developers use it in their applications. Lets see how we can take advantage of Guice in Functional Test automation frameworks.

This article might not be able to cover all the features of Guice. I would suggest you to spend some time here in reading more about Guice.

Guice – Binding:

Guice can directly inject the instance of a class with default constructor when you use @Inject annotation.

For ex:

Google google = new Google();

can be replaced by simply using

@Inject
Google google;

But I use a Factory Pattern for a WebDriver instance creation. I need to map the ChromeDriverManager.class to the DriverManager.class. When you have constructor with arguments or try to map a concrete class to an interface/abstract class, then we need to do few configurations as shown here.

public class DriverModule extends AbstractModule {

    @Override
    protected void configure() {

        bind(DriverManager.class)
            .to(ChromeDriverManager.class)
            .in(Scopes.SINGLETON);

    }

}

Now Guice can inject an instance of ChromeDriverManager.class into the driverManager variable.

@Inject
DriverManager driverManager;

If I had to code to get a required instance, I could use @Provides method. For ex, I might not be really interested in DriverManager.class. But I need that to get the WebDriver instance.

public class DriverModule extends AbstractModule {

    @Override
    protected void configure() {

        bind(DriverManager.class)
            .to(ChromeDriverManager.class)
            .in(Scopes.SINGLETON);

    }
    @Provides
    public WebDriver getDriver(DriverManager driverManager) {
        return driverManager.getDriver();
    }

}

Now Guice can inject an instance of ChromeDriver directly into the driver variable by hiding a lot of code for the creation logic.

@Inject
WebDriver driver;

If you need different browser instances in the same test for some reason, Guice can inject that too!!

@Inject @Chrome
WebDriver chrome;

@Inject @Firefox
WebDriver firefox;

Here @Chrome and @Firefox are custom annotations for Guice to understand what to inject. More information is here.

Not only the WebDriver instance. We might be interested in Actions, JavascriptExecutor,Logger etc. So Guice can inject these instances too from the WebDriver instance we create. It can even the inject the value of a property from your property files.

Guice – Usage In Test Framework:

Lets assume that We keep all our application url, user credentials, any other input parameters in a property file as shown here.

guice001

We could also maintain 1 property file for each environment where we run our automated tests.

ufts-04

As I use Google search functionality for example, I design page objects as shown here by using Single Responsibility principle.

guice002

GoogleSearchWidget class will look like this. WebDriver instance will be injected by Guice. So, I add an @Inject in the constructor.

public class GoogleSearchWidget {

    @FindBy(name = "q")
    WebElement searchBox;

    @FindBy(name = "btnG")
    WebElement searchButton;

    @Inject
    public GoogleSearchWidget(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public void searchFor(String txt) {
        searchBox.sendKeys(txt);
        searchButton.click();
    }

}

GoogleSearchResult class will look like this. I again add an @Inject in the constructor.

public class GoogleSearchResult {

    @FindBy(className = "rc")
    private List results;

    @Inject
    public GoogleSearchResult(WebDriver driver) {
        PageFactory.initElements(driver, this);
    }

    public int getCount() {
        return results.size();
    }

    public void displayResult() {
        results.stream()
            .map(WebElement::getText)
            .forEach(System.out::println);
    }
}

Google class should have the instance of these above 2 classes and few other instances like JavascriptExecutor, Actions etc. To get the property value, We need to use @Named(property-key). So the private String URL in the below class will have the value of the ‘application.url’ which is ‘https://google.com’.

public class Google {

    private final WebDriver driver;

    @Inject
    @Named("application.url")
    private String URL;

    @Inject
    private GoogleSearchWidget searchBox;

    @Inject
    private GoogleSearchResult searchResult;

    @Inject
    private Actions actions;

    @Inject
    private JavascriptExecutor jsExecutor;

    @Inject
    public Google(WebDriver driver) {
        this.driver = driver;
    }

    public void goTo() {
        this.driver.get(this.URL);
    }

    public GoogleSearchWidget getSearchWidget() {
        return searchBox;
    }

    public GoogleSearchResult getResults() {
        return searchResult;
    }

    public Object execute(String script) {
        return jsExecutor.executeScript(script);
    }

}

Now It is time for us to modify the config module class as shown below. GoogleSearchResults / GoogleSearchWidget does not need any config. But the JavascriptExecutor/Actions are created from WebDriver instance. So, we need to help guice how it has to create the instance.

public class DriverModule extends AbstractModule {

    @Override
    protected void configure() {

        //DriverManager config
        bind(DriverManager.class)
            .to(ChromeDriverManager.class)
            .in(Scopes.SINGLETON);

        //My test input properties
        try {
            Properties props = new Properties();
            props.load(new FileInputStream("uat.properties"));
            Names.bindProperties(binder(), props);
        } catch (IOException e) {
            //skip
        }

    }

    @Provides
    public WebDriver getDriver(DriverManager driverManager) {
        return driverManager.getDriver();
    }

    @Provides
    public Actions getActions(WebDriver driver) {
        return new Actions(driver);
    }

    @Provides
    public JavascriptExecutor getExecutor(WebDriver driver) {
        return (JavascriptExecutor)(driver);
    }
}

That is it. We are good to use these page objects and properties in our tests. I use Testng framework which has support for including Guice module.

@Guice(modules = {
    DriverModule.class
})
public class GuiceTest {

    @Inject
    Google google;


    @Test(dataProvider = "google-test")
    public void f(String txt, String color) throws InterruptedException {

        google.goTo();
        
        //change the color of the google page
        google.execute("document.body.style.backgroundColor='" + color + "';");

       //do search and show results
        google.getSearchWidget().searchFor(txt);
        google.getResults().displayResult();

    }

    @DataProvider(name = "google-test")
    public static Object[][] primeNumbers() {
        return new Object[][] {
            {
                "guru",
                "blue"
            }, {
                "guice",
                "green"
            }
        };
    }

}

Now my test class looks neat and clean. If I need any object in my test/page objects, I could just use @Inject.

Summary:

By injecting all the dependencies automatically, Guice can increase our productivity. It makes our code readable, reusable. Due to these benefits, The code becomes easy to maintain as well.

 

Happy Testing and Subscribe 🙂

 

Share This:

Selenium WebDriver – Design Patterns in Test Automation – Template Method Pattern

$
0
0

Overview:

As a software engineer, We all encounter some problems while designing a software. So what do we do when we face a problem? We google for solutions immediately. Don’t we? We google because we know that we would not be alone and someone would have already found the solution, for the problem we are facing now, which we could use to solve.

Design patterns are the solutions for the problems which you might face in your software design!!

Design Patterns are well optimized and reusable solutions to a given problem in software design. It helps us to show the relationship among the classes and the way in which they interact. Design pattern is a template which you have to carefully analyze and use it in appropriate places.

More information on design pattern can be found here.

Design Patterns in Test Automation:

As an automated test engineer, should we really care about design principles and patterns? Why do we need to learn/use Design Patterns in functional test automation?

After all, Test automation framework/automated test case is also a software which is used to test another software. So, we could apply the same design principles/patterns in our test automation design as well to come up with more elegant solution for any given design related problem in the test automation framework.

Remember that Design Patterns are NOT really mandatory. So you do not have to use them! But when you learn them, you would know exactly when to use! Basically these are all well tested solutions. So when you come across a problem while designing your framework/automated test cases, these design patterns could immediately help you by proving you a formula / template & saves us a lot of time and effort.

Note: Your aim should not be to implement a certain pattern in your framework. Instead, identify a problem in the framework and then recognize the pattern which could be used to solve the problem. Do not use any design pattern where it is not really required!!

In this article, We are going to see where we could use the Template Method Pattern which is one of the Behavioral Patterns.

Template Method Pattern:

Goal: Define the skeleton of an algorithm in an operation, deferring some steps to client sub classes. Template Method lets sub classes redefine certain steps of an algorithm without changing the algorithm’s structure.

If we consider this below example, all the workers have same routine. getup, eat breakfast and so on. But type of work could be different for each worker.  [source: https://sourcemaking.com/design_patterns/template_method]

Template_method_example

Lets see where we could use design pattern in Test automation.

Template Method Pattern in Test Automation:

Lets consider this – PHPTravels – application. Lets also assume that we need to automate this application’s Hotel and Car reservation workflow. As part of the business workflow, we need to below steps.

  • enter the locaiton
  • enter the dates
  • click on the search
  • sort the results by the price
  • pick the lowest price
  • pay
  • get the confirmation number.

The above steps are applicable for both hotel and car reservations workflow. They have significant similarities. However screens are different, car reservation might require 2 locations one for pickup and one for dropoff which is different from just 1 location for Hotel.

Considering the workflow, We could create a template like this.

Hotel Page Object:

Car Page Object:

Hotel Reservation Workflow:

Car Reservation Workflow:

TestNG Test:

Summary:

By using Template Method Pattern, we create a skeleton for the reservation functionality.  If there is any common functionality, then it can be kept in the Template class itself.  Hotel, Car, Flight etc any reservation can implement this template by overriding abstract methods of the Template. So, there is no code duplication.

Design Pattern is a very good tool for effective communication. How? As soon as we name a pattern, Others can immediately picture the high-level-design in their heads & get the solution for the given problem. Thus, Design Pattern enables us to explain the design in a much better way.

Happy Testing & Subscribe 🙂

 

Share This:

Selenium WebDriver – A Disposable Selenium Grid Infrastructure Setup using Docker

$
0
0

Selenium Grid – Overview:

Selenium Grid is used to run our tests on different OS/browsers in parallel. It basically uses master-slaves (or hub-nodes) concept – where there is one master/hub and there are few slaves/nodes registered to the master/hub. When we send our tests to the master/hub for execution, based on the browser/OS requirements of the test, master will route the request to the appropriate nodes and get them executed. Thus it minimizes the overall execution time of the tests.

 

grid001

 

Selenium Grid – Setup:

  • Install Java
  • Download  the latest selenium-server-standalone-X.XX.jar from Selenium-Downloads site.
  • Start the hub

java -jar selenium-server-standalone-3.3.1.jar -role hub

  • Register a node

java -jar selenium-server-standalone-3.3.1.jar -role node -hub http://localhost:4444/grid/register

  • Install the required browsers for your test in the node
  • Download the browser’s driver executable.
  • Register the node including the path for the executable as shown below.

java -jar selenium-server-standalone-3.3.1.jar -role node -hub http://localhost:4444/grid/register -Dwebdriver.chrome.driver=.\chromedriver.exe

Then, we could run our test as shown below.

DesiredCapabilities dc = DesiredCapabilities.firefox();
dc.setPlatform(Platform.WINDOWS);

RemoteWebDriver driver=new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), dc);
driver.get("https://www.google.com");

Challenges:

Setting up selenium grid & maintaining is not very easy.

  • Downloading and setting up all the dependencies for each node.
  • Java process – will eventually run out-of-memory.
  • Manually restarting the nodes in case of issues.
  • Maintenance is expensive.
  • Scalability issues.

Docker:

What is the use of docker here?

Docker is a bit like a virtual machine. But unlike a virtual machine, rather than creating a whole virtual operating system, Docker allows applications to use the same Linux kernel as the system that they’re running on and only requires applications be shipped with things not already running on the host computer. This gives a significant performance boost and reduces the size of the application – source: opensource.com

Docker is a manager of Infrastructure. It will be able to package a software and all its dependencies to run as a container. You can deploy the software, packaged as a docker image, in any machine where docker is installed. It, kind of, separates the software from the hardware – so the developer / test engineer can rest assured that the application will run on any machine regardless of any customized settings that machine might have that could differ from the machine used for writing and testing the code.

Please check the official docker site for installation.

Selenium Grid Setup using Docker:

Selenium official has already setup docker images for you to setup the selenium grid. Once you have installed docker in a machine,

  • Setup Hub

sudo docker run -d -p 4444:4444 --name selenium-hub selenium/hub

  • Setup nodes with Chrome & Firefox and register to the hub

sudo docker run -d --link selenium-hub:hub selenium/node-chrome
sudo docker run -d --link selenium-hub:hub selenium/node-firefox

The above commands takes care of downloading already built image (with all the dependencies like java, chrome, firefox, selenium-server-standalone jar etc… required to run your selenium tests).

You can access the selenium-grid console using http://localhost:4444/grid/console

docker-grid

If you need one more chrome node instance, run this command.

sudo docker run -d --link selenium-hub:hub selenium/node-chrome

It creates one more container with chrome and all the dependencies and registers to the hub. Issuing sudo docker ps command will show the running containers.

grid002

To shutdown the docker-grid infrastructure, run the below commands.

sudo docker stop $(sudo docker ps -a -q)
sudo docker rm $(sudo docker ps -a -q)

Docker has greatly simplified the selenium-grid setup process. However there is still some manual work.

Challenges:

  • Need to start/stop the containers one by one to setup the hub and nodes.

Selenium Grid Setup using Docker-Compose:

As part of our Selenium Grid we need to have 1 hub and few nodes like chrome and firefox. We can define all these services in a file called docker-compose.yml file and bring the entire infrastructure up and running by using a single command. Docker provides a tool for that – Docker-Compose.

Please check the steps here for the installation of docker-compose.

Once installed, create a new directory and create a docker-compose.yml file with below content.

docker-compose file:

Issue below command

sudo docker-compose up -d

grid003

sudo docker-compose ps

grid004

Now, do you need 5 instance of chrome? Not a big deal!! docker will take care of creating 4 more instances of chrome within few seconds. Just issue below command.

sudo docker-compose scale chrome=5

grid005

sudo docker-compose ps

grid006

The selenium grid console will look like this

docker-grid-002

Now the entire grid can be brought down by issuing a single command.

sudo docker-compose down

grid007

 

Summary:

Managing selenium grid infrastructure is a pain. By using docker, we could reduce the significant amount of effort in setting the up the selenium grid. We can bring this infrastructure up and down anytime by issuing a single command and It is highly scalable as well.

 

Happy Testing & Subscribe 🙂

 

Share This:


Selenium WebDriver – Managing Selenium Grid Infrastructure using Arquillian Cube

$
0
0

In the previous article, we saw how easily we could set up the selenium-grid infrastructure using docker.

By using docker-compose file, we can setup the containers for the selenium grid. Then we can start our automated functional tests using the grid. Once the execution is done, we can issue a simple command to bring the entire selenium grid infrastructure down. However these docker containers have to be managed (starting/stopping etc) by us either manually or some custom script.

Can this be simplified further?

Yes, That is what we are going to see in this article!

Arquillian Cube:

Arquillian provides a nice extension – Arquillian-Cube – by which we can integrate docker and Arquillian, so that docker containers life cycle can be managed directly by Arquillian itself.

Arquillian Drone + Cube:

I am going to use one of my existing Arquillian drone project for this article.

I add below maven dependencies in my maven project.

 

Then I define the infrastructure information we need in a docker-compose.yml file as shown here.

Then I add the docker server, compose file and drone information in the Arquillian.xml

That’s it! We are set to control the docker-containers directly as part of our automated tests.

Did you notice? One cool thing here is – I do not have to modify anything in the test. That is the power of Arquillian. It helps us to keep the config completely away from the script. In future, If you do not want to use docker or selenium grid in future, you just need to update the arquillian.xml. Nothing else.  This is cool..Why would I not love Arquillian, then? 🙂

Now If I start my test, Arquillian first launches all the required containers, waits for the containers to be up and running, then it starts my tests.

I tried to record the simple test to show you all how it works – I have my eclipse IDE open where I have my arquillian drone tests + cube. My putty is connected to the remote ubuntu server where docker server is running. I keep on issuing ‘sudo docker ps -a‘ on putty to show all the containers in the remote server.

 

You could see in putty that initially there were no containers. Before the test starts 3 containers were created as given in the docker-compose file.then the test starts. Once the test finishes, there is no sign of any docker containers running in the machine.

Summary:

Docker has already saved us a lot of effort in setting up infrastructure quickly. Arquillian by managing docker’s containers life cycle, it makes our job even more easier. Our Arquillian test itself launches the required containers for the test, runs the test and shuts the containers down!!

 

Happy Testing & Subscribe 🙂

 

Share This:

Selenium WebDriver – Automating Custom Controls – DatePicker

$
0
0

Overview:

We already have seen automating below complex controls.

In this article, we will see how we could automate Calendar / DatePicker.

Goal:

To model a wrapper element for the DatePicker / Calendar. So that user can identify the datepicker field as any other field by the locator and select any given date without injecting Javascript.

Injecting Javascript might be very easy. But that is not right way to automate as it could potentially miss some issues. It might not trigger any associated events.

date-picker-001

My use case would be to select any given date in the DatePicker/Calendar field as shown below.

DatePicker.setDate("01 Jan 2018");
DatePicker.setDate("29 Feb 2012");

JQuery DatePicker:

All the below elements make the DatePicker element.

date-picker-002

 

Lets come up with a wrapper with all the WebElements which looks like Calendar.

DatePicker / Calendar Element:

 

 

Page Object:

By using above DatePicker, I could find the date picker element – like locating a regular WebElement.

 

TestNG Test:

 

date-picker-003

 

Summary:

By adding an abstraction layer, we control Calendar/DatePicker, a complex element, like a simple WebElement. Now, I could easily share / export this as a library and share it with others who has similar requirements. I could find any DatePicker/Calendar element by using its locator as I would normally find a WebElement.

 

@FindBy(id="datepicker")
private DatePicker calendar;

 

Happy Testing & Subscribe 🙂

 

Share This:

Selenium WebDriver – Setting up the browser drivers using Spacelift

$
0
0

Overview:

One of the challenges we often face with test automation is – setting up the dependency to run the automated test scripts in all the remote virtual machines. For example, downloading & setting up the required version of browser drivers like chromedriver and adding them to the PATH. Doing this setup manually in every machine could be bit annoying.

I would suggest you to go with dockerized selenium grid approach. But in case, you do not want to use docker, You could include the drivers in your framework itself. That is, you add the required executables and push it to the central repo. [I know, some of you might hate this idea! It might increase your project size etc]. But It ensures that – all the dependency required are part of the project. So you would not miss anything in the remote machine to run the test scripts.

But there is some other better approach as well!

Spacelift:

Spacelift is a library from Arquillian Team!

Spacelift provides a set of tools (and tasks) that can be used to encapsulate execution of any command into block that can be executed asynchronously and repeated if needed. You reuse a set of existing tasks and implement your own tasks.

Spacelift comes with some very basic tools like DownloadTool, UnzipTool which can be used for setting up the browser drivers.

Features:

  • Spacelift executes the tasks in asynchronously.
  • Spacelift can block the execution by using ‘await()’ or ‘awaitAtMost(long , TimeUnit)’
  • Spacelift can execute the given task periodically until some condition / timeout is met.

Add below maven dependency to use Spacelift.

Setting up Browser Driver:

Lets consider this class to download chrome driver and unzip.

This setup will ensure that your chrome browser driver is setup in the remote machine. Your test can be as shown here.

If you like to setup the drivers this way, Then I would suggest you to use the Factory pattern as mentioned in this article.

We could modify the abstract DriverManager class to include an abstract method ‘setupDriver’ method. Each extending Driver manager class like ChromeDriverManager will imlement the download and unzip using spacelift as shown above.

 

Happy Testing & Subscribe 🙂

 

 

Share This:

Selenium WebDriver – Automating Hoverable Multilevel Dropdowns

$
0
0

Overview:

One of the challenges test automation engineers face is – automating hoverable dropdowns as shown above in this article. Lets see how it can be automated using Selenium-WebDriver & Java.

Hoverable Dropdown:

Check this site. Move your mouse pointer on the element ‘Dropdown’. We can see the list of options of the multilevel ‘Dropdown’. Some options can also show another options on hovering over!

Actions:

To perform hover action on an element using WebDriver, We would be using Actions API as shown below. Below script will the mouse to the middle of the element which is what we would like to achieve.

Actions action = new Actions(driver);
action.moveToElement(element or by).perform();

In order to automate the clicking operation on the Dropdown Submenu Link 5.4.1, I need to traverse few elements in the menu tree.

Lets create a Consumer lambda function which accepts ‘By’ as the parameter. We use ‘By’ locator here instead of the ‘WebElement’, sometimes, there is a chance the application under test might throw ‘NoSuchElementException’ if the elements are created at run time. 

hover.accept(by) – will perform for the hover operation for the given ‘by’ locator.

If you would like to use dropdown navigation as shown below in your code,

String by = "Dropdown -> Dropdown Link 5 -> Dropdown Submenu Link 5.4 -> Dropdown Submenu Link 5.4.1";

By using Java Stream API, it can be done as shown here.

 

Demo:

 

Happy Testing & Subscribe 🙂

 

 

Share This:

Selenium WebDriver – Disposable Selenium Grid Infrastructure Setup using Zalenium

$
0
0

Overview:

We already have seen the challenges related to setting up the Selenium Grid infrastructure and how docker helps us in setting up a flexible/disposable/highly scalable selenium grid within few seconds in these articles below.

In this article, We will see how Zalenium (a similar dockerized selenium grid infrastructure with few other features) helps.

Zalenium Setup:

  • Ensure that you have latest docker engine is running. You can get the instructions here on installing docker.
  • Pull below docker images.
    • docker pull elgalu/selenium
    • docker pull dosel/zalenium
  • Run the below command to start the zaleniukm-selenium-grid
  docker run --rm -ti --name zalenium -p 4444:4444 -p 5555:5555 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /tmp/videos:/home/seluser/videos \
    dosel/zalenium start
  • Zalenium is ready to use now in our tests.
 
DesiredCapabilities dc = DesiredCapabilities.firefox(); 
RemoteWebDriver driver=new RemoteWebDriver(new URL("http://10.11.12.13:4444/wd/hub"), dc);

driver.get("https://www.google.com"); 

Zalenium – Live Preview:

  • One of the cool features of zalenium is the live preview of the dockerized containers. We can access this using below URL.
    • http://ipofdockerenginer:4444/grid/admin/live#

zalenium-preview-001

  • By default, our Selenium grid will have 1 Chrome and 1 Firefox container. If you need more, say 3 chrome containers, 2 firefox then use below arguments
    • –chromeContainers 3
    • –firefoxContainers 2
  docker run --rm -ti --name zalenium -p 4444:4444 -p 5555:5555 \
    -v /var/run/docker.sock:/var/run/docker.sock \
    -v /tmp/videos:/home/seluser/videos \
    dosel/zalenium start --chromeContainers 3 --firefoxContainers 2

 

Demo:

I am running the test I had created as part of DatePicker Automation in this demo.

Dashboard:

  • Zalenium also has  a nice dashboard to show the list of recorded tests it has captured.
    • Can be accessed at this URL:  http://ipofdockerengine:5555

zalenium-dashboard-001

  • By default, name of the test has some random string which can be replaced by passing the name of test in the Desired Capabilities.
desiredCapabilities.setCapability("name", "myTestName");
  • Disable the video recording feature using below capability.
desiredCapabilities.setCapability("recordVideo", false);

 

Integrating with Cloud Testing Platforms:

  • Yet another cool feature of zalenium is – It can be integrated with cloud based testing solutions like BrowserStack/SuaceLabs.
  • Any incoming request to the hub is verified by zalenium – If it can create a container for the request, It starts a container and runs the test.
  • Otherwise, the test gets executed at the cloud testing platforms.

how_it_works

Sauce Labs:

  export SAUCE_USERNAME=<your Sauce Labs username>
  export SAUCE_ACCESS_KEY=<your Sauce Labs access key>
  docker run --rm -ti --name zalenium -p 4444:4444 -p 5555:5555 \
    -e SAUCE_USERNAME -e SAUCE_ACCESS_KEY \
    -v /tmp/videos:/home/seluser/videos \
    -v /var/run/docker.sock:/var/run/docker.sock \
    dosel/zalenium start --sauceLabsEnabled true

BrowserStack:

  export BROWSER_STACK_USER=<your BrowserStack username>
  export BROWSER_STACK_KEY=<your BrowserStack access key>
  docker run --rm -ti --name zalenium -p 4444:4444 -p 5555:5555 \
    -e BROWSER_STACK_USER -e BROWSER_STACK_KEY \
    -v /tmp/videos:/home/seluser/videos \
    -v /var/run/docker.sock:/var/run/docker.sock \
    dosel/zalenium start --browserStackEnabled true

 

For more information on Zalenium, please check here.

 

Happy Testing & Subscribe 🙂

 

Share This:

Viewing all 69 articles
Browse latest View live