Selenium Easy - Selenium Tutorialshttp://www.seleniumeasy.com/selenium-tutorials
If you are a beginner, please Proceed here to start from the beginning.
enReading data from google spreadsheethttp://www.seleniumeasy.com/selenium-tutorials/read-data-from-google-spreadsheet-using-api
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>Until today, to perform data-driven testing, we have used libraries like <a href="http://www.seleniumeasy.com/apachepoi-tutorials">Apache POI</a>, <a href="http://www.seleniumeasy.com/jxl-tutorials">JExcel</a> etc to read/write Excel files. To work with these libraries, we have to create spreadsheet, save in a repository and we need to write much amount of code to access the spreadsheet and test all the data dependent scenarios.</p>
<p>This becomes problem in maintainability for automation test scripts when the test data is growing and keep adding files to the framework. Every time when we update the test data, we have to check-out / check-in from the framework to make sure our test works. </p>
<p>Instead of having them physically available, we can create an google spreadsheet to store the test data and access the data using Google Sheets API’s.</p>
<p><b>Why Google Spreadsheet?</b></p>
<p>1. We can maintain multiple spreadsheets which will be a central repository for automation Test Data.<br />
2. We don't to check-out/Check-in to change / update test data.<br />
3. Lesser amount of code is required to get data, Google API's made it easy for us.<br />
4. If you want to share this test data, just share the URL.<br />
5. No data loss. </p>
<p><b>Getting started with the Google Sheets API</b></p>
<p>Google Sheets is an online spreadsheet application that lets users create and format spreadsheets and simultaneously work with other team members. </p>
<p>We will try to access spreadsheet data using <a href="https://developers.google.com/sheets/api/" target="_blank">Google Sheets API v4</a>. Using this API, our code can access and update spreadsheets just like any other user. </p>
<p><b>Prerequisites :</b></p>
<p><i>1. Jave 1.7 or greater.</i><br /><i>2. Gradle 2.3 or greater / Maven</i><br /><i>3. Google account</i></p>
<p>The important step before proceeding to an example, we should first turn on the Google Sheets API.</p>
<p>a. Use <a href="https://console.developers.google.com/start/api?id=sheets.googleapis.com" target="_blank">Google Developers Console</a> wizard to create or select a project and automatically turn on the API. Click Continue, then Go to credentials.</p>
<p>b. On the Add credentials to your project page, click the Cancel button.</p>
<p>c. At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.</p>
<p>d. Select the Credentials tab, click the Create credentials button and select OAuth client ID.</p>
<p>e. Select the application type Other, enter the name "Google Sheets API for Selenium", and click the Create button.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/google_sheet_api_oauth.png" alt="Google Spreadsheet oAuth for selenium" /></p>
<p>f. Click OK to dismiss the resulting dialog.</p>
<p>g. Click the file_download (Download JSON) button to the right of the client ID.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/google_sheet_api_secret.png" alt="Google Spreadsheet client id for selenium" /></p>
<p>h. Move this file to your working directory and rename it <code>client_secret.json.</code></p>
<h3>Let's see how to use this API to read data from Spreadsheet, here we are going to use <a href="http://www.seleniumeasy.com/maven-tutorials">Maven</a> to get dependencies for Google Spreadsheet API v4.</h3>
<h4>Create a simple maven project and add below dependencies to work with Google Sheets API. </h4>
<pre><code>&lt;dependency&gt;
&lt;groupId&gt;com.google.api-client&lt;/groupId&gt;
&lt;artifactId&gt;google-api-client&lt;/artifactId&gt;
&lt;version&gt;1.22.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.oauth-client&lt;/groupId&gt;
&lt;artifactId&gt;google-oauth-client-jetty&lt;/artifactId&gt;
&lt;version&gt;1.22.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;com.google.apis&lt;/groupId&gt;
&lt;artifactId&gt;google-api-services-sheets&lt;/artifactId&gt;
&lt;version&gt;v4-rev483-1.22.0&lt;/version&gt;
&lt;/dependency&gt;</code></pre><p>
<b>Below is a sample code in Java for accessing the Google Spreadsheeet. You can also add the following jars as maven dependencies to perform an tests using selenium and testng.</b></p>
<pre><code>&lt;dependency&gt;
&lt;groupId&gt;org.testng&lt;/groupId&gt;
&lt;artifactId&gt;testng&lt;/artifactId&gt;
&lt;version&gt;6.10&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.seleniumhq.selenium&lt;/groupId&gt;
&lt;artifactId&gt;selenium-java&lt;/artifactId&gt;
&lt;version&gt;3.4.0&lt;/version&gt;
&lt;/dependency&gt; </code></pre><p>
<b>First create a class named GoogleSheetAPI.java and copy the below code:-</b></p>
<pre><code>package spreadsheetAutomation;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.Sheets;
import com.google.api.services.sheets.v4.SheetsScopes;
import com.google.api.services.sheets.v4.model.ValueRange;
public class GoogleSheetAPI {
/** Application name. */
private static final String APPLICATION_NAME = "Google Sheets API Java Quickstart";
/** Directory to store user credentials for this application. */
private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"), ".credentials/sheets.googleapis.com-java-quickstart");
/** Global instance of the {@link FileDataStoreFactory}. */
private static FileDataStoreFactory DATA_STORE_FACTORY;
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/** Global instance of the HTTP transport. */
private static HttpTransport HTTP_TRANSPORT;
/** Global instance of the scopes required by this quickstart.
*
* If modifying these scopes, delete your previously saved credentials
* at ~/.credentials/sheets.googleapis.com-java-quickstart
*/
private static final List&lt;String&gt; SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS_READONLY);
static {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
/**
* Creates an authorized Credential object.
* @return an authorized Credential object.
* @throws IOException
*/
public static Credential authorize() throws IOException {
// Load client secrets.
InputStream in =
GoogleSheetAPI.class.getResourceAsStream("/client_secret.json");
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
}
/**
* Build and return an authorized Sheets API client service.
* @return an authorized Sheets API client service
* @throws IOException
*/
public static Sheets getSheetsService() throws IOException {
Credential credential = authorize();
return new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
public List&lt;List&lt;Object&gt;&gt; getSpreadSheetRecords(String spreadsheetId, String range) throws IOException {
Sheets service = getSheetsService();
ValueRange response = service.spreadsheets().values()
.get(spreadsheetId, range)
.execute();
List&lt;List&lt;Object&gt;&gt; values = response.getValues();
if (values != null &amp;&amp; values.size() != 0) {
return values;
} else {
System.out.println("No data found.");
return null;
}
}
}</code></pre><p>
In the above class, we have defined a method 'getSpreadSheetRecords(String spreadsheetId, String range)' which does the job to return the required data based on the spreadsheetId and range we specify.</p>
<p><b>spreadsheetId: -</b></p>
<p>Method requires a spreadsheetId parameter which is used to identify which spreadsheet is to be accessed or altered. This ID is the value between the "/d/" and the "/edit" in the URL of your spreadsheet. </p>
<p>For example, consider the following URL that references a Google Sheets spreadsheet:</p>
<p><a href="https://docs.google.com/spreadsheets/d/1qpyC0XzvTcKT6EISywvqESX3A0MwQoFDE8p-Bll4hps/edit#gid=0">https://docs.google.com/spreadsheets/d/1qpyC0XzvTcKT6EISywvqESX3A0MwQoFD...</a></p>
<p><b>range: - </b></p>
<p>Method require a range in A1 notation. This is a string like <code>Sheet1!A1:B2</code>, that refers to a group of cells in the spreadsheet. You can see the name of the sheet on the tab near the bottom of the screen. It defaults to Sheet 1.</p>
<p>For example, valid ranges are: -<br />
Sheet1!A1:B2 refers to the first two cells in the top two rows of Sheet1.</p>
<p>A1:B2 refers to the first two cells in the top two rows of the first visible sheet.</p>
<p>If we specify range as "A1:B2" is represented as [['a1', 'b1'], ['a2', 'b2']] (where the strings are place holders for actual content of those cells in Sheet1)</p>
<p><b>NOTE:</b><br />
If the sheet name has spaces or starts with a bracket, surround the sheet name with single quotes ('), e.g 'Sheet One'!A1:B2. For simplicity, it is safe to always surround the sheet name with single quotes.</p>
<p><b>Below is the test Data which is in Google Spreadsheet</b></p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/google_sheet_testData.png" alt="Google Spreadsheet test data for selenium" /></p>
<p>Now let us try to create a class with one scenario to access google spreadsheet and validate data returned by selenium.</p>
<pre><code>package spreadsheetAutomation;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class automationTest {
public WebDriver driver;
public WebDriverWait wait;
String appURL = "appURL";
private String spreadsheetId = "1C6yrt6yr27luKlbclkOYFmTdL8tD5Wfh__dIen0";
private String range = "UserInfo!A3:E";
String userName = "johns";
String password = "test@123";
@BeforeClass
public void testSetup() {
System.setProperty("webdriver.gecko.driver","path of geckodriver.exe");
driver=new FirefoxDriver();
wait = new WebDriverWait(driver, 5);
}
//Verify user profile information after login
@Test
public void verifyProfileInfo() throws IOException {
login(userName,password);
String[] userProfileInfo = getProfileInfo();
List&lt;String&gt; userData = Arrays.asList(userProfileInfo);
//Get data from sheet and verify first profile info of john
GoogleSheetAPI sheetAPI = new GoogleSheetAPI();
List&lt;List&lt;Object&gt;&gt; values = sheetAPI.getSpreadSheetRecords(spreadsheetId, range);
for (List&lt;Object&gt; row : values) {
if(row.get(0).equals(userName)) {
Assert.assertEquals(userData, row);
break;
}
}
}
public String[] getProfileInfo() {
//Navigate to Profile page
driver.findElement(By.id("user-profile")).click();
String firstName = driver.findElement(By.id("firstname")).getText();
String lastName = driver.findElement(By.id("lastname")).getText();
String age = driver.findElement(By.id("user-age")).getText();
String sex = driver.findElement(By.id("user-sex")).getText();
String[] arrayUserInfo = {firstName, lastName, age, sex};
return arrayUserInfo;
}
public void login(String userName, String password) {
driver.findElement(By.id("session_key-login")).sendKeys(userName);
driver.findElement(By.id("session_password-login")).sendKeys(password);
driver.findElement(By.id("signin")).click();
}
@AfterClass
public void tearDown() {
if(driver!=null) {
driver.quit();
}
}
}</code></pre><p>
In the above code, we have single test method 'verifyProfileInfo()' which will validate user profile information firstName, lastName, age, and sex once the user login. </p>
<p>There are other two methods 'login(username,password)' which helps to login to the application and 'getProfileInfo()' will get text and returns a string array with the profile information.</p>
<p>There are two lines of code in test method 'verifyProfileInfo()' which gets the spreadsheet data for us.</p>
<pre><code>GoogleSheetAPI sheetAPI = new GoogleSheetAPI();
List&lt;List&lt;Object&gt;&gt; values = sheetAPI.getSpreadSheetRecords(spreadsheetId, range);</code></pre><p>
'values' will have all the spreadsheet data (rows and columns). We will iterate each row and verify if the username has profile information in the sheet. </p>
<p>If the username is found in the sheet, we will try to compare both the list o data. Here a list is which returned by 'getProfileInfo()' using selenium and other list is a row. </p>
<p>Google Spreadsheets have many settings that let you to interact with the spreadsheet. Reading/writing cell values only (via the <a href="https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values" target="_blank">spreadsheets.values</a> collection) and Reading/writing any aspect of the spreadsheet (via the <a href="https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets" target="_blank">spreadsheets</a> collection).</p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/excel" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Excel</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Reading data from google spreadsheet" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/read-data-from-google-spreadsheet-using-api" class="rdf-meta element-hidden"></span>Sun, 24 Sep 2017 15:31:11 +0000harrydev239 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/read-data-from-google-spreadsheet-using-api#commentsSelenium Grid Hub and Node configuration using JSONhttp://www.seleniumeasy.com/selenium-tutorials/configure-selenium-grid-using-json-config-file
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>Selenium Grid is used to speed up the execution by using multiple machines (multiple browsers with different versions, and browsers running on different operating systems) and run tests in parallel. And also to reduce the time spent for running the test suite after developers check-in their code.</p>
<p>If you just want to get started using selenium grid, you can use simple commands as we discussed in <a href="http://www.seleniumeasy.com/selenium-tutorials/how-to-configure-selenium-grid">previous article</a>. But if you need more control with advanced configuration, then we have to specify a JSON format config file to configure the hub/node and start it. </p>
<p>As said, hub/node can be configured in 2 different ways, one is by specifying command line parameters, and the other way is by specifying a json file which we are going to see here.</p>
<h3>Configuring hub using below JSON:- </h3>
<pre><code>{
"port": 4444,
"newSessionWaitTimeout": -1,
"servlets" : [],
"withoutServlets": [],
"custom": {},
"capabilityMatcher": "org.openqa.grid.internal.utils.DefaultCapabilityMatcher",
"throwOnCapabilityNotPresent": true,
"cleanUpCycle": 5000,
"role": "hub",
"debug": false,
"browserTimeout": 0,
"timeout": 1800
}</code></pre><p>
This is a sample hubconfig.json file which was made available by Selenium. You can also <a href="https://github.com/SeleniumHQ/selenium/blob/master/java/server/src/org/openqa/grid/common/defaults/DefaultHub.json" target="_blank">download</a> this file. </p>
<p><b>Start hub using below command</b> :- </p>
<pre><code>java -jar selenium-server-standalone-3.x.x.jar -role hub -hubConfig hubconfig.json</code></pre><p>
In our case, we used selenium latest version 3.4.0 and changed the json file name to <code>'gridHubConfig.json'</code>. You can also change the json file name if needed. No other changes are made.</p>
<pre><code>java -jar selenium-server-standalone-3.4.0.jar -role hub -hubConfig gridHubConfig.json</code></pre><p>
<img src="../sites/default/files/pictures/selenium/Selenuim_gridhubconfig.png" class="img-responsive" alt="Selenium grid console" /></p>
<p>Now open your browser and enter the URL either with IP address or localhost with port number. In our case it was with - <code>http://xx.xx.xx.106:4444/grid/console</code> or <code>http://localhost:4444/grid/console</code></p>
<p>You should see something like below, which indicates Grid configured successfully and is Up and running</p>
<p><img src="../sites/default/files/pictures/selenium/selenium_grid_console.png" class="img-responsive" alt="Selenium grid console" /></p>
<h3>Configuring nodes using below JSON :-</h3>
<pre><code>{
"capabilities":
[
{
"browserName": "firefox",
"maxInstances": 5,
"seleniumProtocol": "WebDriver"
},
{
"browserName": "chrome",
"maxInstances": 5,
"seleniumProtocol": "WebDriver"
},
{
"browserName": "internet explorer",
"maxInstances": 1,
"seleniumProtocol": "WebDriver"
}
],
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"maxSession": 5,
"port": 5555,
"register": true,
"registerCycle": 5000,
"hub": "<a href="http://localhost:4444&quot;,&#10;">http://localhost:4444",
</a> "nodeStatusCheckTimeout": 5000,
"nodePolling": 5000,
"role": "node",
"unregisterIfStillDownAfter": 60000,
"downPollingLimit": 2,
"debug": false,
"servlets" : [],
"withoutServlets": [],
"custom": {}
}</code></pre><p>
There is a sample nodeconfig.json file which was made available by Selenium. You can also <a href="https://github.com/SeleniumHQ/selenium/blob/master/java/server/src/org/openqa/grid/common/defaults/DefaultNodeWebDriver.json" target="_blank">download node file. </a></p>
<p>If you see above config file, we have not added 'host' parameter, though it is not mandatory but if you are trying to add multiple nodes from different machines, make sure to specify <code>-remoteHost</code> or <code>-host</code> with ip which you want to use.</p>
<p>If not specified, when the node starts, it tries to guess the ip address of the host machine. If there several network interfaces, the guessing can return the wrong address and will return error as DefaultRemoteProxy unknown version, connect to :port [/] failed: Connection timed out</p>
<p><b>NOTE:</b><br />
If you are still using Selenium version 2.x.x, then you should download and use version 2.x.x <a href="https://github.com/SeleniumHQ/selenium/blob/selenium-2.53.0/java/server/src/org/openqa/grid/common/defaults/DefaultNode.json" target="_blank">nodeconfig file</a> as the configuration { ... } object in version 2.x.x has been removed in version 3.x.x </p>
<p><b>Start node using below command :- </b></p>
<p>Before starting the below command, we need to make sure the driver executable are downloaded and available on node machines. As we need to set the path to driver executable while starting the nodes via command line. If the executable are in the some other directory, you have to pass ABSOLUTE_PATH of the driver executable</p>
<pre><code>java -Dwebdriver.chrome.driver="chromedriver.exe" -Dwebdriver.ie.driver="IEDriverServer.exe" -Dwebdriver.gecko.driver="geckodriver.exe" -jar selenium-server-standalone-3.4.0.jar -role node -nodeConfig node1.json</code></pre><p>
<img src="../sites/default/files/pictures/selenium/selenium_nodeConfig.png" class="img-responsive" alt="Selenium node config command" /></p>
<p>Now open your grid console, either with - <code>http://xx.xx.xx.106:4444/grid/console</code> or <code>http://localhost:4444/grid/console</code></p>
<p>You should see something like below, which indicates node successfully registered with grid </p>
<p><img src="../sites/default/files/pictures/selenium/selenium_grid_with_nodes.png" class="img-responsive" alt="Selenium grid console with nodes" /></p>
<p>If you just want to execute your tests on only Firefox and Chrome browser, we can remove IE capabilities from the json and then we don't have to pass IE driver executable. </p>
<pre><code>java -Dwebdriver.chrome.driver="chromedriver.exe" -Dwebdriver.gecko.driver="geckodriver.exe" -jar selenium-server-standalone-3.4.0.jar -role node -nodeConfig node1.json</code></pre><p>
All the <i>-D arguments</i> in the command line should come before the '-jar' as Java command line usage requires system properties to be specified before the -jar. If not the you may see an exception as <i>"Exception in thread "main" com.beust.jcommander.ParameterException: Unknown option:"</i></p>
<p><b>Note</b>: If you are using selenium version 2.x.x, you don't have to pass geckodriver. Geckodriver is only needed when using selenium 3.x.x.</p>
<p>If you want to check list of configuration properties in detail for Selenium hub/node, run below commands</p>
<pre><code>java -jar selenium-server-standalone-3.x.x.jar -role hub -help</code></pre><pre><code>java -jar selenium-server-standalone-3.x.x.jar -role node -help</code></pre><p>
When you are trying to launch selenium hub/node on java 1.7 using Selenium 3.x.x, you may see an exception like below, In this case you have to upgrade your JDK from Java 7 to Java 8 or higher version.<br /><i>Exception in thread "main" java.lang.UnsupportedClassVersionError: org/openqa/grid/selenium/GridLauncherV3</i></p>
<p>Hope this helps you to configure selenium grid using Json files.</p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/grid" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Grid</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Selenium Grid Hub and Node configuration using JSON" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/configure-selenium-grid-using-json-config-file" class="rdf-meta element-hidden"></span>Tue, 20 Jun 2017 17:11:30 +0000harrydev236 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/configure-selenium-grid-using-json-config-file#commentsConfigure Selenium Grid using Dockerhttp://www.seleniumeasy.com/selenium-tutorials/configure-selenium-grid-using-docker
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>Generally, to run our <a href="/selenium-tutorials/parallel-execution-in-selenium-grid">Selenium tests in parallel</a>, we use selenium grid and distribute tests across multiple physical or virtual machines which will reduce the time required for running tests.</p>
<p>To run tests in parallel, we need to <a href="/selenium-tutorials/how-to-configure-selenium-grid">configure Selenium Grid</a> with Hub and Nodes where hub is the central point which will receive test requests along with configurations or capabilities. Based on the request received, hub will distribute tests to the registered nodes.</p>
<p>Most of the organisations execute their Selenium scripts on virtual machines. Based on number of scripts, they need to increase the node machines. When the nodes increases maintaining the Grid environment will become a problem in setting up required browsers / OS combinations across these virtual machines. </p>
<p>And also, there are times were issues like <b>Browser Crashes</b>, <b>nodes running out of memory</b>, <b>Java processes run out of memory</b> etc kills our time in restating node machines/hub.</p>
<p>There are few companies who uses Cloud-based platform for automated testing of web/mobile applications like <a href="https://saucelabs.com/" target="_blank">SauceLabs</a> / <a href="https://www.browserstack.com/" target="_blank">Browserstack</a> / <a href="https://crossbrowsertesting.com/" target="_blank">CrossBrowserTesting</a> but yes these are expensive. </p>
<h3>How Docker helps?</h3>
<p>Docker is a lightweight container which can make you to run distributed applications in a minute. Docker Containers take up less space than VMs (container images are typically tens of MBs in size), and start almost instantly.</p>
<p>Where as each Virtual Machine includes a full copy of an operating system, one or more applications with necessary binaries and libraries which consumes more space and makes slow to boot.</p>
<h3>What is Docker ? </h3>
<p>Docker is an open platform for developers and system administrators to build, ship, and run distributed applications, whether on laptops, data center VMs, or the cloud.</p>
<p>In other words, Docker is a simple container that let's you to specify a complete package of components needed to run a software. </p>
<p>We will not discuss much on Docker as there are many articles available on Docker and its architecture. </p>
<p>We assume that you have already installed docker and is up running, if not please <a href="https://docs.docker.com/engine/installation/" target="_blank">install Docker</a>. Docker can be installed on Windows, macOS, Linux, and Cloud platforms. Please check the requirements and download based on environment.</p>
<p>Once the installation is completed, please test your installation by running the below command:</p>
<pre><code>docker info</code></pre><p>
The above command displays system wide information regarding the Docker installation like number of containers and images etc.</p>
<h3>Configure Selenium Grid in Docker Containers</h3>
<p>To get Selenium Grid up and running, we need to do below steps in Hub/Nodes machines</p>
<p><b>Install Java</b><br /><b>Install Required Browsers (versions if needed)</b><br /><b>Selenium server jars</b></p>
<p>Docker has many built in ways to quickly create a grid, scale nodes up or down when ever required with a single command.</p>
<p>Selenium has also made a set of Docker images which are available on Docker Hub. We have Selenium Grid, and the browser images - Chrome and Firefox (for now), also with the debug versions which will allow us to access and view test execution using VNC.</p>
<p><i>A Docker image is a read-only template with instructions for creating a Docker container.</i></p>
<p>A Docker Hub contains images from official images from organizations like Selenium, Google, Microsoft and a lot more. You can find required images by browsing the Docker Hub. Refer <a href="https://hub.docker.com/r/selenium/" target="_blank">Selenium Docker Hub</a> and <a href="https://github.com/SeleniumHQ/docker-selenium" target="_blank">Selenium Docker Github Page</a></p>
<p>In order to configure the hub on docker container, we need to pull Selenium Hub from Docker repository using below command:-</p>
<pre><code>docker pull selenium/hub</code></pre><p>
Once the pull is complete, it will show you status as 'Downloaded' at the end.</p>
<p>Now we need to Run the Hub using below command :-</p>
<pre><code>docker run -d --name selenium-hub selenium/hub</code></pre><p class="border-simple">
<img src="../sites/default/files/pictures/selenium/docker_selenium_run_hub.png" class="img-responsive" alt="Selenium run grid Hub" /></p>
<p>If you want to assign the port, run the below command</p>
<pre><code>docker run -d -p 4545:4444 --name selenium-hub selenium/hub</code></pre><p>
We can explicitly specify the name for container, else Docker will automatically generate a unique name for each container. In the above command, we have given a name for selenium hub using <code>--name</code>. We can use this name to link node containers to the hub container.</p>
<p>To check if the container has started, run <code> docker ps </code> command and see the status of it.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/docker_started_selenium_hub.png" class="img-responsive" alt="Selenium run grid Hub" /></p>
<p>To check the configuration information, run <code> docker logs <containerid></containerid></code></p>
<p>If you see the status as 'Selenium Grid hub is up and running' then its time to start registering the nodes to hub.</p>
<p>We can also now enter the URL in the browser and the see the Grid running up</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/docker_selenium_grid_console.png" class="img-responsive" alt="Selenium run grid Hub" /></p>
<p>To register nodes to the Hub, we need to pull nodes from Docker Hub using below commands :- </p>
<p>To get Chrome node <code>docker pull selenium/node-chrome</code></p>
<p>To get Firefox node <code>docker pull selenium/node-firefox</code></p>
<p>Once the pull complete, we need to link these nodes to the hub container by running below commands :-</p>
<p>Command to link both Chrome and Firefox nodes to selenium-hub</p>
<pre><code>docker run -d --link selenium-hub:hub selenium/node-firefox
docker run -d --link selenium-hub:hub selenium/node-chrome</code></pre><p>
Now again type <code>docker ps -a</code> command in your terminal, to see a list of containers that are currently active. This will bring up total three containers Selenium Hub, Firefox node, and Chrome node.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/docker_selenium_grid_nodes.png" class="img-responsive" alt="Selenium run grid Hub" /></p>
<p>We can also see the nodes registered in Grid Console. Enter Grid IP and observe that Chrome and Firefox nodes are connected to Hub.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/docker_grid_console.png" class="img-responsive" alt="Selenium run grid Hub" /></p>
<p>Done !!! Now your grid configuration is ready. You can execute your selenium automation scripts as you do. </p>
<p>If you want view test execution, we need to pull 'debug' images, which allow us to see the browser executing tests.</p>
<pre><code>docker pull selenium/node-chrome-debug
docker pull selenium/node-firefox-debug</code></pre><p>
By using docker ps –a command, you can see all the Docker containers and their running ports. Now link these nodes to container hub.</p>
<pre><code>docker run –d –link selenium-hub:hub selenium/node-chrome-debug
docker run –d –link selenium-hub:hub selenium/node-firefox-debug</code></pre><h3> View test execution using debug nodes</h3>
<p>Now we can view browsers by using VNC viewer. Enter your hub URL and port number of each browser (debug browser chrome/firefox) and Click connect button.</p>
<p>VNC viewer will ask you for a password to show you the browser. Type the defauolt password as 'secret' and then click 'Ok' button. </p>
<p>How to increase nodes ?</p>
<p>Say, now if you want more nodes (Total 6 nodes - Say 3 Chrome and 3 Firefox), you can create them in the same way as we have done above:</p>
<p>To increase 2 more chrome nodes, run below commands :- </p>
<pre><code>docker run -d --link selenium-hub:hub selenium/node-chrome
docker run -d --link selenium-hub:hub selenium/node-chrome</code></pre><p>
To increase Firefox nodes, run the below command :-</p>
<pre><code>docker run -d --link selenium-hub:hub selenium/node-firefox
docker run -d --link selenium-hub:hub selenium/node-firefox</code></pre><p>
Now check the Grid console, it will have total 3 chrome and 3 Firefox instances running.</p>
<p>We have executed multiple commands to get Selenium Grid Hub and nodes up and running. Now Let us have all together and start Selenium Grid By running a single <code>docker-compose</code> command.</p>
<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><!-- InsideContent --></p><p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9942551602531349" data-ad-slot="3391308424" data-ad-format="auto"></ins></p>
<script>
<!--//--><![CDATA[// ><!--
(adsbygoogle = window.adsbygoogle || []).push({});
//--><!]]>
</script><h3>What is Docker Compose ?</h3>
<p><i>Docker Compose is a tool for defining and running multi-container Docker applications.</i></p>
<p>We will create a <code>docker-compose.yml</code> file and see how the images interact with each other. Docker compose uses ".yml" file to create and start all the services defined. </p>
<p>To install Docker Compose, you’ll need to install Docker first. We assume that you have already installed docker, now please <a href="https://docs.docker.com/compose/install/" target="_blank">install docker compose</a> and proceed.</p>
<p>Below is the command to install docker-compose, check for the latest release and replace version in the command below if necessary.</p>
<pre><code>sudo curl -o /usr/local/bin/docker-compose -L "<a href="https://github.com/docker/compose/releases/download/1.11.2/docker-compose-">https://github.com/docker/compose/releases/download/1.11.2/docker-compose-</a>$(uname -s)-$(uname -m)"</code></pre><p>
Now set the permissions by running below command :-</p>
<pre><code> sudo chmod +x /usr/local/bin/docker-compose</code></pre><p>
Then we'll verify that the installation was successful by checking the docker-compose version:</p>
<pre><code>docker-compose --version</code></pre><p>
If the permissions are not set, you may get error as <code>bash: /usr/local/bin/docker-compose: Permission denied</code></p>
<p>That's all. We are all set to go, to pull and run Selenium Grid Hub and Nodes with a Single command. Docker Compose will download the images, configure, and start them running. </p>
<pre><code>docker-compose up</code></pre><p>
Before running Docker Compose, we will stop running containers (if there are any) and remove by running below commands.</p>
<p>To Stop Container <code>docker stop containerId</code></p>
<p>To Remove Container <code>docker rm containerId</code></p>
<p>To stop all running containers <code>docker stop $(docker ps -q)</code></p>
<p>To remove all containers <code>docker rm $(docker ps -aq)</code></p>
<p>We will create a simple Docker-compose file like below and add this to the repository. Below is the simple Docker-compose.yml file to pull, link and run Selenium Grid Hub and nodes. </p>
<pre><code>hub:
image: selenium/hub
ports:
- "4444:4444"
firefox:
image: selenium/node-firefox
links:
- hub
chrome:
image: selenium/node-chrome
links:
- hub</code></pre><p>
In the above docker compose file, we have defined selenium hub entity, pointed image name and assigned the port. We have defined and linked two nodes firefox-node and chrome-node. Just navigate to the location where docker-compose.yml file is located and run the below command.</p>
<pre><code>docker-compose up -d</code></pre><p>
After running above command, check 'docker ps' or open Grid console to see grid Hub and nodes running.</p>
<p>When there are huge tests that need to run parallel, two nodes may be not enough. Docker-compose has a great feature which allows us to scale number of similar containers with single command.</p>
<h3>Increase Nodes using Docker-compose</h3>
<p>If you want to increase the number of chrome nodes to three, enter command:</p>
<pre><code>docker-compose scale chrome=3</code></pre><p>
Again if you want to increase the number of firefox nodes to 3, enter below command:</p>
<pre><code>docker-compose scale firefox=3</code></pre><p>
To check if all the 6 nodes registered to the Grid Hub, run the below command with selenium-hub container id :-</p>
<pre><code>docker logs &lt;conatinerId&gt;</code></pre><p>
This will show you all the containers that are registered to the Hub. It just took few minutes/commands to have Selenium Grid up and Running successfully.</p>
<h2>Part 1: Step by step video to configure selenium grid using Docker</h2>
<div class="youtube-player" data-id="aXAjL9v_9CM"></div>
<h2>Part 2: Step by step video to Setup Selenium Grid using Docker-Compose</h2>
<div class="youtube-player" data-id="l5KKDTaol0Q"></div>
<p>Hope this helps you to setup Grid on your containers and run selenium tests with simple command.</p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/grid" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Grid</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Configure Selenium Grid using Docker" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/configure-selenium-grid-using-docker" class="rdf-meta element-hidden"></span>Sun, 19 Mar 2017 16:46:01 +0000harrydev234 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/configure-selenium-grid-using-docker#commentsExecute your Automation Tests in the Cloud using Seleniumhttp://www.seleniumeasy.com/selenium-tutorials/execute-selenium-tests-in-the-Cloud
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>In this article, will talk about CrossBrowserTesting which lets us to test website across 1500+ browsers - Android devices, iPhones, iPads, Windows, &amp; OSX. Check list of Operating systems, mobile devices and browsers supported by <a href="https://crossbrowsertesting.com/browsers" target="_blank">CrossBrowsersTesting</a>.</p>
<p>The end users across the globe have their choice of using different browsers to access web applications. So, it is very important to verify applications on various browsers and versions. It is always a good practice to verify how the application behaves on various browsers and Operating System. Maintaining infrastructure which supports different combinations of browsers and Operating systems with different resolutions is very difficult. </p>
<p>CrossBrowserTesting (CBT) is one of the cloud-based platforms for testing both web and mobile applications with real physical devices and simulators. Using CrossBrowserTesting we can run Selenium automation scripts across hundreds of browsers and operating systems and focus ONLY on writing test scripts. </p>
<p>It's very simple to set-up CBT, no additional software required, we can start running tests immediately and share test report snapshots, videos and network traffic information right in one easy report.</p>
<h3>Let's getting started with CrossBrowserTesting and will look at how to get Selenium script running on the CrossBrowserTesting Cloud.</h3>
<p><b>Step 1:-</b> Sign up for CrossBrowserTesting account. You can Start Your <a href="https://crossbrowsertesting.com/freetrial" target="_blank">Free Trial</a> - No Credit Card Required.</p>
<p><b>Step 2:-</b> Get your authkey, which you can find under Account -&gt; Manage Account once you login.</p>
<p><b> Step 3:-</b> To run selenium example test from your machine, first add required dependencies.<br />
You may need to add the below dependencies to your project.<br />
selenium-server-standalone-vXXX.jar<br />
unirest-java-vXXX.jar<br />
json-XXX.jar</p>
<p><b>Step 4:-</b> Define capabilities like Browser, OS, Resolution etc.</p>
<p><b> Step 5:-</b> Copy paste the below code</p>
<p><b>Step 6:-</b> Run the test as Java application</p>
<p>Now we will look into the below example on how we can connect to CrossBrowserTesting and execute basic Selenium script using Java.</p>
<p><b>Below is the basic Selenium code using Java to execute on CBT.</b></p>
<pre><code>package easyCBTExample;
import static org.junit.Assert.*;
import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
public class CBTExampleTest {
static String username = "kdevxxxxxxxju.com"; // Your username
static String authkey = "xx51xx15xx1a9acb"; // Your authkey
public static void main(String[] args) throws Exception {
// Created object of DesiredCapabilities
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability("name", "Selenium Test Example");
caps.setCapability("build", "1.0");
caps.setCapability("browser_api_name", "Edge20");
caps.setCapability("os_api_name", "Win10");
caps.setCapability("screen_resolution", "1024x768");
caps.setCapability("selenium_version", "2.53.1");
RemoteWebDriver driver = new RemoteWebDriver(
new URL("http://" + username + ":" + authkey + "@hub.crossbrowsertesting.com:80/wd/hub"), caps);
System.out.println(driver.getSessionId());
// we wrap the test in a try catch loop so we can log assert failures in our system
try {
// load the page url
System.out.println("Loading Url");
driver.get("<a href="http://crossbrowsertesting.github.io/selenium_example_page.html&quot;">http://crossbrowsertesting.github.io/selenium_example_page.html"</a>);
// maximize the window - DESKTOPS ONLY
System.out.println("Maximizing window");
driver.manage().window().maximize();
// Check the page title (try changing to make the assertion fail!)
assertEquals(driver.getTitle(), "Selenium Test Example Page");
} catch (AssertionError ae) {
// if we have an assertion error, take a snapshot of where the test
// fails
} catch (Exception a) {
// if we have an other exception, take a snapshot of where the test
// fails
} finally {
// and quit the driver
driver.quit();
}
}
}</code></pre><p>
When we run the above test, it will show the test status as running with the capabilities mentioned.</p>
<p><img alt="Status of the test running" class="img-responsive" src="../sites/default/files/pictures/selenium/selenium_test_running.jpg" /></p>
<h3>What have we Done?</h3>
<p>Firstly, we have specified CBT username ( which is the email address with which you signed up for your account) and <code>authkey</code> to interact with CrossBrowserTesting. </p>
<p>To run tests on remote machines i.e on CrossBrowserTesting Cloud, WebDriver has to use the instance of the RemoteWebDriver and DesiredCapabilities in order to specify browser name, version and platform to execute tests.</p>
<p>Generally to run tests on our local machine, we will just specify as <code>WebDriver driver = new FirefoxDriver();<code> to run on Firefox browser.</code></code></p>
<p>To execute tests on remote machine, we need to use <code>remotewebdriver</code>, here we have changed that to run tests on CBT.</p>
<pre><code>RemoteWebDriver driver = new RemoteWebDriver(new URL("http://" + username + ":" + authkey + "@hub.crossbrowsertesting.com:80/wd/hub"), caps);</code></pre><p>
"Not all server implementations will support every WebDriver feature. Therefore, the client and server should use JSON objects with the properties listed below when describing which features a user [requests](JsonWireProtocol#POST_/session.md) that a session support. "</p>
<p><a href="https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/remote/DesiredCapabilities.html" target="_blank">DesiredCapabilities</a> helps us to customize and configure a browser session using key-value pair. When using CBT, we have to specify os_api_name and browser_api_name mandatorily. For example OS can be defined for Windows 10 as 'Win10' and Windows 8.1 as Win8.1 so on. And browser name can be defined as 'FF46' for Firefox Version 46 and 'Chrome53' for chrome version 53. You can use CBT wizard / via an API call to view specific capabilities that you need when building test. </p>
<p>We have to add capabilities 'name' and 'build' to specify test name and build number to make more meaningful. And all remaining capabilities are optional to customize your test more. Below is the screenshot which shows the capabilities added to the test.</p>
<p><img alt="Capabilities added to the test running" class="img-responsive" src="../sites/default/files/pictures/selenium/selenium_test_capabilities.jpg" /></p>
<p>If you want test to run with specific resolution, then you need to add <code>'caps.setCapability("screen_resolution", "1280x768");'</code>. Else tests will be executed on default screen resolution '1024x768'. </p>
<p>If you don't specify 'browser_api_name' / browser_api_name, it will throw an WebdriverExpection as 'Capabilities must specify either a browserName or CrossBrowserTesting's browser_api_name so we know what browser to launch.' or 'os_api_name needs to be a string'</p>
<p>Check list of possible <a href="https://help.crossbrowsertesting.com/selenium-testing/automation-capabilities/" target="_blank">Selenium capabilities</a> that we can use when executing tests across CrossBrowserTesting’s service.</p>
<p>We have wrapped test in a try catch loop, so that we can log assert failures and capture snapshots. In the above test, there is only one assertion to check the page title. </p>
<p>Check Part two on How to capture screenshots and how to run tests parallely using TestNG on CBT Cloud Service.</p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/cloud-execution" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Cloud Execution</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Execute your Automation Tests in the Cloud using Selenium" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/execute-selenium-tests-in-the-Cloud" class="rdf-meta element-hidden"></span>Fri, 23 Dec 2016 16:31:35 +0000harrydev229 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/execute-selenium-tests-in-the-Cloud#commentsCapture Performance Data Using BrowserMob Proxy and Seleniumhttp://www.seleniumeasy.com/selenium-tutorials/browsermob-proxy-selenium-example
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p><a href="http://bmp.lightbody.net/" target="_blank">BrowserMob Proxy</a> is an open source tools which is used to <b>capture performance data</b> for a web applications in an HAR format. It also allows to manipulate browser behavior and traffic, such as simulating network traffic, rewriting HTTP requests and responses etc.</p>
<p>Manually, we can monitor performance of a web application by using browser tools like <b>Firebug</b> or <b>Developers Tools</b> etc. <i>BrowserMob proxy helps us to capture client side performance data for a web application using Selenium WebDriver automated tests</i>. In this example, we will configure BrowserMob proxy for Selenium WebDriver and capture the performance data in HAR format.</p>
<p class="pullquote"> HTTP Archive format or HAR is a JSON-formatted archive file format for logging of a web browser's interaction with a web application.</p>
<p class="credits">— <a href="https://en.wikipedia.org/wiki/.har" target="_blank">Wikipedia</a></p>
<p>In the below example, we will be taking <a href="http://www.seleniumeasy.com/testng-tutorials/testng-introduction">TestNG annotations</a> help to start and stop proxy server before the tests and close after all tests completes execution. BrowserMob Proxy makes it easy to use a proxy in Selenium tests. You can look at the sample snippet provided by <a href="https://github.com/lightbody/browsermob-proxy" target="_blank">BrowserMob GitHub</a>.</p>
<pre><code> // start the proxy
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.start(0);
// get the Selenium proxy object
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
// start the browser up
WebDriver driver = new FirefoxDriver(capabilities);
// enable more detailed HAR capture, if desired (see CaptureType for the complete list)
proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
// create a new HAR with the label "yahoo.com"
proxy.newHar("yahoo.com");
// open yahoo.com
driver.get("<a href="http://yahoo.com&quot;">http://yahoo.com"</a>);
// get the HAR data
Har har = proxy.getHar();</code></pre><h4>Below are the methods that we use to start and stop BrowserMobProxy server. If you want to start server on specific port, we need to pass the port value</h4>
<p><i>proxy.start()</i> - Starts the proxy on port 0.<br /><i>proxy.start(int port)</i> - Starts the proxy on the specified port. Ff the specified proxy has already been started, it throws 'java.lang.IllegalStateException'.<br /><i>proxy.stop()</i> - shutdown the proxy server gracefully </p>
<h4>We can use any of the below methods to collect performance data in an HAR format based on the requirement</h4>
<p><i>Har newHar()</i> - Creates a new HAR file with the default page name.<br /><i>Har newHar(String initialPageRef)</i> - Creates a new HAR file with the specified 'initialPageRef' as the page name and page title.<br /><i>Har newHar(String initialPageRef, String initialPageTitle)</i> - Creates a new HAR file with the specified 'initialPageRef' page name and 'initialPageTitle' page title. </p>
<p>You have to <a href="http://bmp.lightbody.net/" target="_blank">download BrowserMob Proxy</a> and make sure that all the dependencies are imported in to the project along with selenium server. Once you unzip browsermob zip folder, Navigate to the lib directory and add. Latest released version is 2.1.2 (July 23, 2016). For more information on the new release, you can visit the BrowserMob Proxy page on <a href="https://github.com/lightbody/browsermob-proxy" target="_blank">Github</a></p>
<pre><code>package com.easy;
import java.io.File;
import java.io.IOException;
import org.openqa.selenium.By;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.proxy.CaptureType;
public class BrowserMobExample {
String driverPath = "F:/drivers/chromedriver/";
String sFileName = "F:/SeleniumEasy.har";
public WebDriver driver;
public BrowserMobProxy proxy;
@BeforeTest
public void setUp() {
// start the proxy
proxy = new BrowserMobProxyServer();
proxy.start(0);
//get the Selenium proxy object - org.openqa.selenium.Proxy;
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// configure it as a desired capability
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.PROXY, seleniumProxy);
//set chromedriver system property
System.setProperty("webdriver.chrome.driver", driverPath+"chromedriver.exe");
driver = new ChromeDriver(capabilities);
// enable more detailed HAR capture, if desired (see CaptureType for the complete list)
proxy.enableHarCaptureTypes(CaptureType.REQUEST_CONTENT, CaptureType.RESPONSE_CONTENT);
// create a new HAR with the label "seleniumeasy.com"
proxy.newHar("seleniumeasy.com");
// open seleniumeasy.com
driver.get("<a href="http://seleniumeasy.com&quot;">http://seleniumeasy.com"</a>);
}
@Test
public void testCaseOne() {
System.out.println("Navigate to selenium tutorials page");
driver.findElement(By.linkText("Selenium"));
}
@AfterTest
public void tearDown() {
// get the HAR data
Har har = proxy.getHar();
// Write HAR Data in a File
File harFile = new File(sFileName);
try {
har.writeTo(harFile);
} catch (IOException ex) {
System.out.println (ex.toString());
System.out.println("Could not find file " + sFileName);
}
if (driver != null) {
proxy.stop();
driver.quit();
}
}
}</code></pre><p>
If you're using Maven, add below dependency to your pom.xml file along with Selenium and TestNG dependencies. <a href="http://mvnrepository.com/artifact/net.lightbody.bmp/browsermob-proxy" target="_blank">MVNRepository - BrowserMob Proxy Parent Project</a></p>
<pre><code> &lt;dependency&gt;
&lt;groupId&gt;net.lightbody.bmp&lt;/groupId&gt;
&lt;artifactId&gt;browsermob-core&lt;/artifactId&gt;
&lt;version&gt;2.1.2&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre><p>
All the network traffic during this test will be captured and saved to the <b>seleniumeasy.har</b> file (specified location) and can be viewed by a HAR Viewer, some of the har viewer links are provided below. </p>
<p>Below is the HAR file generated :</p>
<p class="border-simple">
<img alt="Selenium webdriver to access Shadow Elements" class="img-responsive" src="../sites/default/files/pictures/selenium/browsermob_selenium_har_file.jpg" /></p>
<p>Har Viewer By <a href="http://www.softwareishard.com/har/viewer/" target="_bank">Software is hard Har Viewer</a><br />
Har Viewer by <a href="https://ericduran.github.io/chromeHAR/" target="_blank">Ericduran.github</a><br />
By Google Chrome Ad on <a href="https://chrome.google.com/webstore/detail/http-archive-viewer/ebbdbdmhegaoooipfnjikefdpeoaidml/related?hl=en" target="_blank">HTTP Archive Viewer</a></p>
<p>Hope this helps you. Let me know if you face any issues configuring BrowserMob Proxy with Selenium.</p>
</div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span rel="schema:url" resource="/selenium-tutorials/browsermob-proxy-selenium-example" class="rdf-meta element-hidden"></span><span property="schema:name" content="Capture Performance Data Using BrowserMob Proxy and Selenium" class="rdf-meta element-hidden"></span>Sun, 06 Nov 2016 14:32:42 +0000harrydev228 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/browsermob-proxy-selenium-example#commentsWorking with Shadow DOM Elements using Webdriverhttp://www.seleniumeasy.com/selenium-tutorials/accessing-shadow-dom-elements-with-webdriver
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>When we try to find Shadow DOM elements using selenium locators, it will throw 'NoSuchElementException'. To access these Shadow DOM elements, we need to use <a href="https://seleniumeasy.com/tags/javascriptexecutor">JavascriptExecutor</a> executeScript() function. If you look at the DOM structure, every element that has ShadowDOM also has a shadowRoot property which describes the underlying elements.</p>
<p>Before looking at the example, first let see about <i>DOM and Shadow Dom.</i><br />
DOM - It is a programming interface that treats an HTML, XHTML, or XML document as a tree structure wherein each node is an object representing a part of the document. </p>
<p><a href="https://www.w3.org/TR/shadow-dom/" target="_blank">Shadow DOM</a> provides encapsulation for the JavaScript, CSS, and templating in a Web Component. Shadow DOM is just normal DOM with two differences, one is 'how it is created/used' and other one is 'how it behaves in relation to the rest of the page'. Shadow DOM separates content from presentation thereby eliminating naming conflicts and improving code expression.</p>
<p>We will look an example using Chrome's download page. If you observe the below image, to get the header text (h1 tag), we need to navigate to 3 nested shadow root elements. </p>
<p class="border-simple">
<img alt="Selenium webdriver to access Shadow Elements" class="img-responsive" src="../sites/default/files/pictures/selenium/shadow_dom_elements_with_selenium.jpg" /></p>
<p>In order to do this, first we will try to get the WebElement of the Shadow-root using below method. The below commend will return a web element after executing executeScript() function.</p>
<pre><code>public WebElement expandRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor)driver)
.executeScript("return arguments[0].shadowRoot", element);
return ele;
}</code></pre><p>
Now using this root <i>WebElement</i>, we will try to find the next root element and proceed until we reach the final Shadow Root element. So here in our example, we will navigate till shadow root 3 to access header tag h1.</p>
<h5>Here is the complete example on accessing shadow DOM Elements(polymer elements) through selenium webdriver javascriptExecutor in Java.</h5>
<pre><code>package com.easy;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class ShadowDOMExample {
WebDriver driver;
String driverPath = "F:/Jars/chromedriver/";
@BeforeTest
public void setUp() {
System.out.println("Opening chrome browser");
System.setProperty("webdriver.chrome.driver", driverPath + "chromedriver.exe");
driver = new ChromeDriver();
}
@Test
public void testGetText_FromShadowDOMElements() {
System.out.println("Open Chrome downloads");
driver.get("chrome://downloads/");
System.out.println("Validate downloads page header text");
WebElement root1 = driver.findElement(By.tagName("downloads-manager"));
//Get shadow root element
WebElement shadowRoot1 = expandRootElement(root1);
WebElement root2 = shadowRoot1.findElement(By.cssSelector("downloads-toolbar"));
WebElement shadowRoot2 = expandRootElement(root2);
WebElement root3 = shadowRoot2.findElement(By.cssSelector("cr-toolbar"));
WebElement shadowRoot3 = expandRootElement(root3);
String actualHeading = shadowRoot3.findElement(By.cssSelector("div[id=leftContent]&gt;h1")).getText();
// Verify header title
Assert.assertEquals("Downloads", actualHeading);
}
//Returns webelement
public WebElement expandRootElement(WebElement element) {
WebElement ele = (WebElement) ((JavascriptExecutor) driver)
.executeScript("return arguments[0].shadowRoot",element);
return ele;
}
@AfterTest
public void tearDown() {
driver.quit();
}
}</code></pre><p>
Chrome Browser has <b>native support</b> for ShadowDom from Chrome Version v49. So chrome browser renders Shadow DOM when the application is built with <a href="https://www.polymer-project.org/1.0/" target="_blank">Polymer </a> webcomponent.</p>
<p>In order to access <i>Shadow DOM elements with selenium</i>, traditional locators will throw 'NoSuchElementException'. We have to use JavascriptExecutor execute() function to work. But which is not the case with Firefox, all selenium locators will work as usual as Shadow DOM is not currently supported by default.</p>
<p><b>Below image shows the browsers which has native support for Shadow DOM and that are in development.</b> </p>
<p class="border-simple">
<img alt="Shadow DOM supported browsers" class="img-responsive" src="../sites/default/files/pictures/selenium/shadow_dom_browser_status.jpg" /></p>
<p>Firefox Shadow DOM is not supported by default (until now with Firefox v52), but that can be enabled. To <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components" target="_blank">Enable Web Components in Firefox</a>, type about:config in the address bar to navigate to config page and dismiss any warning that appears. Then search for the preference called dom.webcomponents.enabled, and set it to true. <b>Be cautious before making any changes to config.</b></p>
<p>You can check the status <a href="https://platform-status.mozilla.org/#shadow-dom" target="_blank">here</a>. Firefox internally uses a <a href="https://en.wikipedia.org/wiki/Polyfill" target="_blank">Polyfill</a> which is a browser fallback, which is made in JavaScript, that allows functionality you expect to work in modern browsers to work in older browsers, e.g., to support canvas (an HTML5 feature) in older browsers. </p>
<p>Let me try to execute below test in Firefox browser (Executed in Firefox v49.0.1) on a website which was developed with Polymer Webcomponent and has Shadow DOM elements.</p>
<p>Application URL : - <a href="https://shop.polymer-project.org/">https://shop.polymer-project.org/</a></p>
<pre><code> public void testClickMenuItem_And_ValidatePageHeader() throws InterruptedException {
System.out.println("Open Online Shop");
driver.get("<a href="https://shop.polymer-project.org/&quot;">https://shop.polymer-project.org/"</a>);
wait = new WebDriverWait(driver, 5);
By byMenu = By.linkText("Ladies Outerwear");
wait.until(ExpectedConditions.visibilityOfElementLocated(byMenu));
driver.findElement(byMenu).click();
//Validate Page title
By byHeading = By.cssSelector("header&gt;h1");
wait.until(ExpectedConditions.presenceOfElementLocated(byHeading));
String getActualHeaderText = driver.findElement(byHeading).getText();
Assert.assertEquals(getActualHeaderText, "Ladies Outerwear");
}</code></pre><p>
The above test will be executed without any issues in <a href="https://seleniumeasy.com/selenium-tutorials/launching-firefox-browser-with-geckodriver-selenium-3">Firefox browser using Geckodriver</a></p>
<p>But if executed in chrome, it throws NoSuchEelementException, as chrome browser has native support of Shadow DOM by default. Try to execute the above test in both Firefox and Chrome browser to see the difference. </p>
</div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span rel="schema:url" resource="/selenium-tutorials/accessing-shadow-dom-elements-with-webdriver" class="rdf-meta element-hidden"></span><span property="schema:name" content="Working with Shadow DOM Elements using Webdriver" class="rdf-meta element-hidden"></span>Tue, 18 Oct 2016 16:57:44 +0000harrydev227 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/accessing-shadow-dom-elements-with-webdriver#commentsSelenium 3 - Launch Edge browser using Microsoft Edge Driverhttp://www.seleniumeasy.com/selenium-tutorials/launching-microsoft-edge-browser-using-selenium-3
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>In the previous article, we have seen <a href="https://www.seleniumeasy.com/selenium-tutorials/launching-firefox-browser-with-geckodriver-selenium-3" target="_blank">launching Firefox browser</a> with Gecko driver using Selenium 3. Now let us try to launch Microsoft Edge browse using Selenium 3.</p>
<p>Before proceeding, to start using Webdriver with Microsoft Edge browser, make sure you have Windows 10 on your machine and download the specified Microsoft WebDriver server version for your build.</p>
<p>You can download latest version of <a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/" target="_blank">Microsoft WebDriver from here</a>. Make sure to check Edge version supported and download.</p>
<p>Once you download the file 'MicrosoftWebDriver.msi', Install it to get 'MicrosoftWebDriver.exe' file. </p>
<p>In order to launch Edge Browser, we need to specify the system property with the path of the MicrosoftWebDriver.exe file.</p>
<pre><code>package com.test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.testng.annotations.Test;
public class ExampleThree {
String driverPath = "&lt;path to Microsoft edge driver&gt;";
public WebDriver driver;
@Test(priority=1)
public void launchBrowser() {
System.out.println("launching Microsoft Edge browser");
System.setProperty("webdriver.edge.driver", driverPath+"MicrosoftWebDriver.exe");
driver = new EdgeDriver();
}
@Test(priority=2)
public void openEdgeBrowser() {
driver.navigate().to("<a href="http://www.google.com&quot;">http://www.google.com"</a>);
}
@Test(priority=3)
public void closeDriver() {
if(driver!=null) {
driver.close();
}
}
}</code></pre></div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/selenium-3" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium 3</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Selenium 3 - Launch Edge browser using Microsoft Edge Driver" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/launching-microsoft-edge-browser-using-selenium-3" class="rdf-meta element-hidden"></span>Mon, 08 Aug 2016 11:21:45 +0000harrydev216 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/launching-microsoft-edge-browser-using-selenium-3#commentsSelenium 3 - Launching firefox browser using Geckodriverhttp://www.seleniumeasy.com/selenium-tutorials/launching-firefox-browser-with-geckodriver-selenium-3
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>The first example that we will look into is launching firefox using the Geckodriver. When using Selenium 3 , you have to download geckodriver. Just like the other drivers available to Selenium, Mozilla has released geckodriver executable that will run alongside the browser. </p>
<p>You can download the latest executable on the <a href="https://github.com/mozilla/geckodriver/releases" target="_blank">GitHub page</a>. Now you need to specify the system property with the path </p>
<pre><code>System.setProperty("webdriver.gecko.driver","path of geckodriver.exe");
WebDriver driver = new FirefoxDriver();</code></pre><p>
<b>Below is the code to set GeckoDriver path on Mac OS X for Selenium WebDriver</b></p>
<pre><code>System.setProperty("webdriver.gecko.driver", "/Users/username/Downloads/geckodriver");
WebDriver driver = new FirefoxDriver();</code></pre><p>
<b>What is GeckoDriver?</b></p>
<p>A Proxy for using W3C WebDriver-compatible clients to interact with Gecko-based browsers. Geckodriver provides HTTP API described by the WebDriver protocol to communicate with Gecko browsers, such as Firefox (Version after 47). </p>
<p>Marionette (the next generation of FirefoxDriver) is turned on by default from Selenium 3. Even if you are working with older versions of Firefox browser, Selenium 3 expects you to set path to the driver executable by the webdriver.gecko.driver. </p>
<p>Click here For more details on <a href="https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/">Marionette</a></p>
<p><b>Note</b>: If you are using Selenium version below 2.xx, you don't need gecko additional driver. You can downloaded selenium-server-standalone-2.53.1.jar from <a href="http://selenium-release.storage.googleapis.com/index.html?path=2.53/" target="_blank">download selenium 2.53.1</a></p>
<p>If you are not doing so, it will throw exception <b><i>"java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.gecko.driver system property;" </i></b></p>
<pre><code>java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.gecko.driver system property; for more information, see <a href="https://github.com/mozilla/geckodriver">https://github.com/mozilla/geckodriver</a>. The latest version can be downloaded from <a href="https://github.com/mozilla/geckodriver/releases&#10;">https://github.com/mozilla/geckodriver/releases
</a> at com.google.common.base.Preconditions.checkState(Preconditions.java:199)
at org.openqa.selenium.remote.service.DriverService.findExecutable(DriverService.java:109)
at org.openqa.selenium.firefox.GeckoDriverService.access$100(GeckoDriverService.java:38)
at org.openqa.selenium.firefox.GeckoDriverService$Builder.findDefaultExecutable(GeckoDriverService.java:91)
at org.openqa.selenium.remote.service.DriverService$Builder.build(DriverService.java:296)
at org.openqa.selenium.firefox.FirefoxDriver.createCommandExecutor(FirefoxDriver.java:245)
at org.openqa.selenium.firefox.FirefoxDriver.&lt;init&gt;(FirefoxDriver.java:220)
at org.openqa.selenium.firefox.FirefoxDriver.&lt;init&gt;(FirefoxDriver.java:215)
at org.openqa.selenium.firefox.FirefoxDriver.&lt;init&gt;(FirefoxDriver.java:211)
at org.openqa.selenium.firefox.FirefoxDriver.&lt;init&gt;(FirefoxDriver.java:124)</code></pre><h5>The other important changes in Selenium 3.x are listed below: </h5>
<p>* Minimum java version is now 8+<br />
* The original RC APIs are only available via the leg-rc package.<br />
* To run exported IDE tests, ensure that the leg-rc package is on the classpath.<br />
* Support for Firefox is via Mozilla's geckodriver.<br />
* Support for Edge is provided by MS:<br />
* Official support for IE requires version 9 or above<br />
* New html-table runner backed by WebDriver.<br />
* Unused command line arguments are now no longer parsed.</p>
<p>Now let us see the example to launch firefox browser with Selenium 3 using gecko driver.</p>
<pre><code>package com.test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;
public class ExampleThree {
String driverPath = "&lt;path to gecko driver executable&gt;";
public WebDriver driver;
@Test
public void launchBrowser() {
System.out.println("launching firefox browser");
System.setProperty("webdriver.gecko.driver", driverPath+"geckodriver.exe");
driver = new FirefoxDriver();
}
@Test
public void openApplication() {
driver.navigate().to("<a href="http://www.google.com&quot;">http://www.google.com"</a>);
}
@Test
public void closeDriver() {
if(driver!=null) {
driver.close();
}
}
}</code></pre><p>
<script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><!-- InsideContent --></p><p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9942551602531349" data-ad-slot="3391308424" data-ad-format="auto"></ins></p>
<script>
<!--//--><![CDATA[// ><!--
(adsbygoogle = window.adsbygoogle || []).push({});
//--><!]]>
</script><p>To run tests on remote machines, WebDriver has to use the instance of the RemoteWebDriver and DesiredCapabilities in order to specify browser name, version and platform to execute tests.</p>
<p>Generally to run tests on our local machine, we will just specify as WebDriver driver = new FirefoxDriver(); to run on Firefox browser.</p>
<p>To execute tests on remote machine, we need to use remotewebdriver, below is the sample code to execute your tests on remote machine with Firefox gecko driver</p>
<pre><code>System.setProperty("webdriver.gecko.driver", driverPath+"geckodriver.exe");
DesiredCapabilities capabilities=DesiredCapabilities.firefox();
capabilities.setCapability("marionette", true);
WebDriver driver = new FirefoxDriver(capabilities);</code></pre><p>
The above code is verified with selenium-server-standalone-3.0.0-beta2 and Firefox 48 version. Please let me know if you have any issues. </p>
<p>In your Maven project, just add / update the following selenium dependency to your pom.xml:</p>
<pre><code> &lt;dependency&gt;
&lt;groupId&gt;org.seleniumhq.selenium&lt;/groupId&gt;
&lt;artifactId&gt;selenium-java&lt;/artifactId&gt;
&lt;version&gt;3.0.0-beta2&lt;/version&gt;
&lt;/dependency&gt; </code></pre><p>
When working with selenium grid and if you want your tests to run on Firefox with Selenium version 3.x.x, then we need to provide path to gecko driver executable. Detailed information on <a href="http://www.seleniumeasy.com/selenium-tutorials/configure-selenium-grid-using-json-config-file">Selenium Nodes configuartion using JSON for Firefox gecko driver</a></p>
<p>The most common issue people are facing with latest versions of Firefox is <code> org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms.</code></p>
<p>Users who are facing the above problem, Please use Marionette (geckodriver). </p>
<p>Please do comment your issue / observation with the versions (Selenium, Firefox and Geckodriver) that you have used. </p>
<h4>UPDATE on geckodriver windows 32bit issues</h4>
<pre><code>Sep 1, 2016 3:07:19 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Attempting bi-dialect session, assuming Postel's Law holds true on the remote end</code></pre><p>
If you are facing an issue like <b>org.openqa.selenium.remote.ProtocolHandshake createSession</b> with geckodriver windows 32bit , Please check for an update of the issue here<a href="https://github.com/mozilla/geckodriver/pull/213" target="_blank"> and check the last comment made by 'Andreas Tolfsen'. Once all the issues fixed in the </a><a href="https://github.com/mozilla/geckodriver/milestone/1" target="_blank">milestone</a> they will soon be releasing Geckodriver v0.11. </p>
<p><b>UPDATE:</b><br />
Now you should be able to download <a href="https://github.com/mozilla/geckodriver/releases" target="_blank">gecko driver version 0.11</a> which will resolve windows32 bit issues.</p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/selenium-3" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium 3</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Selenium 3 - Launching firefox browser using Geckodriver" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/launching-firefox-browser-with-geckodriver-selenium-3" class="rdf-meta element-hidden"></span>Mon, 08 Aug 2016 09:29:52 +0000harrydev215 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/launching-firefox-browser-with-geckodriver-selenium-3#commentsPage Factory Design Pattern (Enhanced POM)http://www.seleniumeasy.com/selenium-tutorials/page-factory-pattern-in-selenium-webdriver
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>Selenium Page Factory Pattern is like an extension to <a href="http://www.seleniumeasy.com/selenium-tutorials/page-object-model-framework-introduction">Page Object Model </a>, but Page Factory is much enhanced model. To start with, we just need to import package ‘org.openqa.selenium.support.PageFactory’</p>
<p class="pullquote-large">"Factory class can be used to make using Page Objects simpler and easier".</p>
<p>We use <a href="https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/PageFactory.html" target="_blank" rel="nofollow">Page Factory pattern</a> to initialize web elements which are defined in Page Objects.</p>
<p>We should initialize page objects using initElements() method from PageFactory Class as below, Once we call initElements() method, all elements will get initialized. PageFactory.initElements() static method takes the driver instance of the given class and the class type, and returns a Page Object with its fields fully initialized. </p>
<pre><code>Home homePage = new HomePage(driver);
PageFactory.initElements(driver, homePage);</code></pre><p>
Or, </p>
<pre><code>// To initialize elements.
HomePage homePage = PageFactory.initElements(driver, HomePage.class);</code></pre><p>
Or, <b>as a constructor for page class as below:</b></p>
<pre><code>public HompePage(WebDriver driver) {
this.driver = driver;
PageFactory.initElements(driver, this);
}</code></pre><p>
We should preferably use a constructor which takes a WebDriver instance as its only argument or falling back on a no-arg constructor. An exception will be thrown if the class cannot be instantiated.</p>
<p>Page Factory will initialize every WebElement variable with a reference to a corresponding element on the actual web page based on “locators” defined. This is done by using <b>@FindBy annotations</b>. </p>
<h4>Annotations?</h4>
<p>In Page Factory, Annotations are used to give descriptive names for WebElements to improve code readability. And annotation <b>@FindBy</b> is used to identify Web Elements in the page.</p>
<p>By default, PageFactory will search for elements on the page with a matching id attribute, If that fails, then it will search by the name attribute. But as we need more control over identifying elements in the HTML page and mapping them to our Page Object fields. One way to do this is to use the @FindBy annotation, as shown in the following code:</p>
<p>The <a href="https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/FindBy.html" target="_blank" rel="nofollow">@FindBy</a> annotation supports all the other locators strategies that we use:<br /><b>id, name, className, css, xpath, tagName, linkText and partialLinkText</b> </p>
<p>We can either use this annotation by specifying both "How" and "using" or by specifying any one of the location strategies (Eg: "id") </p>
<pre><code>@FindBy(how = How.ID, using = "username")
private WebElement userName;</code></pre><p>
We can re-write the above one as below:</p>
<pre><code>@FindBy(id="username")
private WebElement userName;</code></pre><p>
And </p>
<p>To work with class name, we will define as below: </p>
<pre><code>@FindBy(className=".input.username")
private WebElement userName;</code></pre><p>
<b>When we have multiple elements (list of WebElements), we can initialize them using PageFactory as below :</b></p>
<pre><code>@FindBy(tagName = "mylist")
private List&lt;WebElement&gt; links;</code></pre><p>
Every time when a method is called on a WebElement, the driver will first find it on the current page and then simulate the action on the WebElement. There are cases where we will be working with a basic page, and we know that we will find the element on the page every time we look for it, In such cases we can use annotation <b>‘@CacheLookup‘</b> which is another annotation in page factory</p>
<pre><code>@FindBy(name="username")
@CacheLookup
private WebElement userName;</code></pre><h4>What is @CacheLookup annotation in PageFactory?</h4>
<p>We will mark <b><i>annotation @CacheLookup</i></b> to WebElements to indicate that it never changes (that is, that the same instance in the DOM will always be used)<br />
CacheLookup attribute can be used to instruct the InitElements() method to cache the element once its located and so that it will not be searched over and over again – this is useful when the elements that are always going to be there<br />
(For AJAX based applications, it may not work where the DOM changes based on user action on the page). Otherwise every time when we use a Web Element the WebDriver will go and search it again</p>
<p>But whenever we use <a href="https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/CacheLookup.html" target="_blank" rel="nofollow">@CacheLookup</a> annotation, we will be losing one of the page factory benefit as it will find the element once and then keep a reference to it, hence, we are more likely to see <a href="http://www.seleniumeasy.com/selenium-tutorials/staleelementreferenceexception-in-selenium-webdriver">StaleElementExceptions.</a></p>
<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><!-- InsideContent --></p><p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9942551602531349" data-ad-slot="3391308424" data-ad-format="auto"></ins></p>
<script>
<!--//--><![CDATA[// ><!--
(adsbygoogle = window.adsbygoogle || []).push({});
//--><!]]>
</script><h4>AjaxElementLocatorFactory</h4>
<p> <a href="https://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/support/pagefactory/AjaxElementLocatorFactory.html" target="_blank" rel="nofollow">AjaxElementLocatorFactory</a> is a lazy load concept in Page Factory pattern to identify WebElements only when they are used in any operation i.e. a timeOut for a WebElement can be assigned to the Object page class with the help of AjaxElementLocatorFactory.</p>
<p> <b>Example: </b></p>
<pre><code>/***
* Constructor
* @param driver an instance of WebDriver
*/
public int TimeoutValue = 30;
public SearchResultsPage(Webdriver driver) {
PageFactory.initElements(new AjaxElementLocatorFactory(driver, TimeoutValue), this);
}</code></pre><p>
The above code will wait for maximum of 30 seconds until the elements specified by annotations is loaded. If the element is not found in the given time interval, it will throw NoSuchElementException' exception.</p>
<p><b>Conclusion :</b></p>
<p>In fact, we can use the page object pattern without using the Page Factory class. The page object pattern simply abstracts business logic away from the physical structure of the pages. And the Page Factory class gives us the ability to use annotations which automatically find the elements on the page without specifying findElement.</p>
<p>Below is the sample code for Page Object Model in Selenium:</p>
<pre><code>public class BasePage {
private By username = By.id("username");
private By password = By.id("password");
private By loginBtn = By.name("loginbtn");
public void userLogin(String userName, String password) {
driver.findElement(username).sendKeys("testuser");
driver.findElement(password).sendKeys("testpassword");
driver.findElement(loginBtn).click();
}
}</code></pre><p>
And the below is the simple code written using Page Factory in Selenium:</p>
<pre><code>public class BasePage {
@FindBy(id= "username") private WebElement userName;
@FindBy(id= "password") private WebElement password;
@FindBy(id= "login") private WebElement loginBtn;
public void userLogin(String userName, String password) {
userName.sendKeys(userName);
password.sendKeys(password);
loginBtn.click();
}
}</code></pre></div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/frameworks" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Frameworks</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Page Factory Design Pattern (Enhanced POM)" class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/page-factory-pattern-in-selenium-webdriver" class="rdf-meta element-hidden"></span>Fri, 19 Feb 2016 17:28:53 +0000harrydev200 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/page-factory-pattern-in-selenium-webdriver#commentsExecute webdriver tests in Parallel using selenium Grid http://www.seleniumeasy.com/selenium-tutorials/parallel-execution-in-selenium-grid
<div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even" property="schema:articleBody content:encoded"><p>In previous article we have seen <a href="http://www.seleniumeasy.com/selenium-tutorials/how-to-configure-selenium-grid">configuring selenium grid</a> and execute a simple test on firefox browser. In this tutorial we will see 'Parallel execution of tests' using selenium grid and execute tests on firefox and chrome browser. </p>
<p>We will register multiple nodes to the Hub and execute tests in parallel. In the below example we will register a node in the same local machine where hub is running and other node in remote machine.</p>
<p>We will register <b><i>node 1</i></b> in local machine with the below command:<br /><b><br />
java -jar selenium-server-standalone-2.48.2.jar -role node -hub <a href="http://localhost:4444/grid/register">http://localhost:4444/grid/register</a><br /></b></p>
<p>We will register <b><i>node 2</i></b> with the below command in remote machine. In the below command, need to pass a parameter by passing JVM properties using the -D flag along with chrome driver path , so that when ever there is a request to execute in chrome driver, Hub will send the request to this node. And here we have to mention the IP address of the machine where the hub is running as we are starting this node in remote machine.</p>
<p><b><br />
java -jar selenium-server-standalone-2.48.2.jar -role node -hub <a href="http://10.0.0.6:4444/grid/register">http://10.0.0.6:4444/grid/register</a> -Dwebdriver.chrome.driver=.\chromedriver.exe<br /></b></p>
<p>After executing the above command, console should look like below:</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/node_parameter_chromedriver.png" class="img-responsive" alt="grid starting in chrome" /></p>
<p>When a Hub receives request to execute test in Chrome browser and If we don't specify chrome driver path for node, it will throw an exception as "Exception: The path to the chromedriver executable must be set by the webdriver.chrome.driver system property; for more information, see <a href="http://code.google.com/p/selenium/wiki/ChromeDriver">http://code.google.com/p/selenium/wiki/ChromeDriver</a>. The latest version can be downloaded from <a href="http://code.google.com/p/chromedriver/downloads/list">http://code.google.com/p/chromedriver/downloads/list</a>".</p>
<p>Now when these two nodes are registered to the hub, hub console should look like below :</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/multiple_hubs_started.png" class="img-responsive" alt="grid with multiple nodes" /></p>
<p>And the Grid console should look like below which shows configuration details of the nodes with IP address. In the below image below image Node 1 is running in Windows * machine (WIN8_1) and Node 2 is running in Windows7 machine.</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/node_machine_configuration.png" class="img-responsive" alt="grid node machine configuration" /></p>
<h4>Let us now take the example and execute tests in parallel.</h4>
<p> In order to do this, we will create two classes which has multiple @Test methods in it. And a Browser class which invokes the remote webdriver based on the browser parameter that we pass in testng.xml file</p>
<p><b>First create a class as 'Browser.java' </b></p>
<pre><code>package com.test;
import java.net.MalformedURLException;
import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
public class Browser {
public static RemoteWebDriver getDriver(String browser) throws MalformedURLException {
return new RemoteWebDriver(new URL("<a href="http://10.0.0.6:4444/wd/hub&quot;">http://10.0.0.6:4444/wd/hub"</a>), getBrowserCapabilities(browser));
}
private static DesiredCapabilities getBrowserCapabilities(String browserType) {
switch (browserType) {
case "firefox":
System.out.println("Opening firefox driver");
return DesiredCapabilities.firefox();
case "chrome":
System.out.println("Opening chrome driver");
return DesiredCapabilities.chrome();
case "IE":
System.out.println("Opening IE driver");
return DesiredCapabilities.internetExplorer();
default:
System.out.println("browser : " + browserType + " is invalid, Launching Firefox as browser of choice..");
return DesiredCapabilities.firefox();
}
}
}</code></pre><p>
We will call 'getDriver' method which will intern call 'getBrowserCapabilities' based on browser parameter from the below two classes. If we pass 'chrome' as parameter, it is invoke chromedriver</p>
<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script><!-- InsideContent --></p><p><ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-9942551602531349" data-ad-slot="3391308424" data-ad-format="auto"></ins></p>
<script>
<!--//--><![CDATA[// ><!--
(adsbygoogle = window.adsbygoogle || []).push({});
//--><!]]>
</script><h4>Let us create a class as 'ParallelTestA.java' as below: </h4>
<pre><code>package com.test;
import java.net.MalformedURLException;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParallelTestA {
public static RemoteWebDriver driver;
public static String appURL = "<a href="http://www.google.com&quot;;&#10;">http://www.google.com";
</a>
@BeforeClass
@Parameters({ "browser" })
public void setUp(String browser) throws MalformedURLException {
System.out.println("*******************");
driver = Browser.getDriver(browser);
driver.manage().window().maximize();
}
@Test
public void testGooglePageTitleInFirefox() {
driver.navigate().to(appURL);
String strPageTitle = driver.getTitle();
Assert.assertTrue(strPageTitle.equalsIgnoreCase("Google"), "Page title doesn't match");
}
@AfterClass
public void tearDown() {
if(driver!=null) {
System.out.println("Closing browser");
driver.quit();
}
}
}</code></pre><h4>Let us create a class as 'ParallelTestB.java' as below: </h4>
<pre><code>package com.test;
import java.net.MalformedURLException;
import org.openqa.selenium.By;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Parameters;
import org.testng.annotations.Test;
public class ParallelTestB {
public static RemoteWebDriver driver;
public static String appURL = "<a href="http://www.google.com&quot;;&#10;">http://www.google.com";
</a>
@BeforeClass
@Parameters({ "browser" })
public void setUp(String browser) throws MalformedURLException {
System.out.println("*******************");
driver = Browser.getDriver(browser);
driver.manage().window().maximize();
}
@Test
public void testGooglePageTitleInChrome() {
driver.navigate().to("<a href="http://www.google.com&quot;">http://www.google.com"</a>);
String strPageTitle = driver.getTitle();
Assert.assertTrue(strPageTitle.equalsIgnoreCase("Google"), "Page title doesn't match");
}
@Test
public void testSearchGoogle() {
System.out.println("Opening Google..");
driver.navigate().to(appURL);
driver.findElement(By.name("q")).sendKeys("Selenium Easy Grid Tutorials");
driver.findElement(By.name("btnG")).click();
}
@AfterClass
public void tearDown() {
if(driver!=null) {
System.out.println("Closing browser");
driver.quit();
}
}
}</code></pre><p>
<b>Now to execute these tests, we need to create testng.xml file as below and set parallel="tests" with parameter browser for each test</b></p>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE suite SYSTEM "<a href="http://testng.org/testng-1.0.dtd&quot;">http://testng.org/testng-1.0.dtd"</a> &gt;
&lt;suite name="Main Test Suite" parallel="tests" verbose="1"&gt;
&lt;test name="Grid firefox Test"&gt;
&lt;parameter name="browser" value="firefox"/&gt;
&lt;classes&gt;
&lt;class name="com.test.ParallelTestA"/&gt;
&lt;/classes&gt;
&lt;/test&gt;
&lt;test name="Grid chrome Test"&gt;
&lt;parameter name="browser" value="chrome"/&gt;
&lt;classes&gt;
&lt;class name="com.test.ParallelTestB"/&gt;
&lt;/classes&gt;
&lt;/test&gt;
&lt;/suite&gt;</code></pre><p>
Once we execute the above code, hub console will display information such as on 'number of nodes available', on which node it has started executing the tests etc.. as below :</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/Hub_status_test_execution.png" class="img-responsive" alt="grid hub test execution" /></p>
<p>There are many other parameters for browser settings that we can pass when registering node to hub. When ever we use <b>-browser</b> parameter, the default browsers will be ignored and only what we specify in command line will be used.</p>
<p>Example :</p>
<pre><code>-browser browserName=firefox,version=30,maxInstances=5,platform=WIN8_1</code></pre><p>
After executing the above command, if you check the grid console, it will just show the browserName, browser version, Max instances (number of instances of same version of browser you can run over the Remote System) and the platform (OS running on the node) that we have used to register the node. Grid console looks like below :</p>
<p class="border-simple">
<img src="../sites/default/files/pictures/selenium/node_registered_parameters.png" class="img-responsive" alt="grid registered node info" /></p>
<p>If the remote machine has multiple versions of Firefox, We can map the location of each binary to a particular version on the same machine to execute with multiple versions as below:</p>
<pre><code>-browser browserName=firefox,version=40,firefox_binary=c:\Program Files\firefox30\firefox,maxInstances=3,platform=WINDOWS -browser browserName=firefox,version=41,firefox_binary=c:\Program Files\firefox40\firefox,maxInstances=3,platform=WINDOWS</code></pre><p>
We will see more on these parameters in next tutorial. </p>
</div></div></div><div class="field field-name-field-tags field-type-taxonomy-term-reference field-label-above"><div class="field-label">Tags:&nbsp;</div><div class="field-items"><div class="field-item even" rel="dc:subject"><a href="/tags/grid" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Grid</a></div></div></div><div class="field field-name-field-selenium-category field-type-taxonomy-term-reference field-label-above"><div class="field-label">Selenium Tutorials:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/selenium-tutorials" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Selenium Tutorials</a></div></div></div><span property="schema:name" content="Execute webdriver tests in Parallel using selenium Grid " class="rdf-meta element-hidden"></span><span rel="schema:url" resource="/selenium-tutorials/parallel-execution-in-selenium-grid" class="rdf-meta element-hidden"></span>Wed, 27 Jan 2016 18:37:47 +0000harrydev199 at http://www.seleniumeasy.comhttp://www.seleniumeasy.com/selenium-tutorials/parallel-execution-in-selenium-grid#comments