Selenium-Basics

 Agenda

To understand basic concepts in Selenium that helps us to build a test automation framework and in the end we can discuss how framework can be developed as well.

Why Selenium?

  1. open source tool
  2. platform independent
  3. multiple browser support
  4. multiple client languages
  5. community support
Best tool to go for browser based automation.

Selenium architecture

Client(Java/supported languages) <-json over http->Browser drivers <-http->Browsers

Client interacts with browser drivers over json wire protocol, where browser drivers take care of running your code on browsers, and result will be interpreted in the same backward direction.

Invoke Browser

Let's take a look, how we invoke different types of browsers using selenium
package day1;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.Test;

public class InvokeBrowser {
@Test
public void invokeChromeBrowser(){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("https://amazon.in");
System.out.println("Current URL :"+driver.getCurrentUrl());
System.out.println("Get Title :"+driver.getTitle());
// driver.close(); // closes current window
driver.quit(); // closes all associated windows
}

@Test
public void invokeFirefoxBrowser(){
System.setProperty("webdriver.gecko.driver", System.getProperty("user.dir")+"\\src\\geckodriver.exe");
WebDriver driver = new FirefoxDriver();
driver.get("https://amazon.in");
System.out.println("Current URL :"+driver.getCurrentUrl());
System.out.println("Get Title :"+driver.getTitle());
driver.close();
}

@Test
public void invokeEdgeBrowser(){
System.setProperty("webdriver.edge.driver", System.getProperty("user.dir")+"\\src\\msedgedriver.exe");
WebDriver driver = new EdgeDriver();
driver.get("https://amazon.in");
System.out.println("Current URL :"+driver.getCurrentUrl());
System.out.println("Get Title :"+driver.getTitle());
driver.close();
}
}
Note:
In the latest selenium version, you can directly write the code without setting the property, selenium web manager will automatically download the compatible chrome driver with your current chrom browser version and invoke accordingly.

Selenium WebDriver Locators

Locators allow to identify a web element uniquely on a web page. There are different ways of identifying element on a page like
ID
XPATH
CSS SELECTOR
NAME
CLASS NAME
TAGNAME
LINK TEXT
PARTIAL LINK TEXT

Sample outer html
<input type="text" id="twotabsearchtextbox" value="" name="field-keywords" autocomplete="off" placeholder="" class="nav-input nav-progressive-attribute" dir="auto" tabindex="0" aria-label="Search">

Note: Under the class, values separated with space are class names.

Note: Have SelectorsHub plugin installed on your chrome, which helps with element identification and validation

package day2;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.time.Duration;

public class Locators {
WebDriver driver;
@BeforeClass
public void invokeChromeBrowser(){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://amazon.in");
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
}

@Test
public void identifyElementByID() throws InterruptedException {
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("by id");
Thread.sleep(10000L);
driver.findElement(By.id("twotabsearchtextbox")).clear();
}

@Test
public void identifyElementByName() throws InterruptedException {
driver.findElement(By.name("field-keywords")).sendKeys("by name");
Thread.sleep(10000L);
driver.findElement(By.name("field-keywords")).clear();
}

@Test
public void identifyElementByClassName() throws InterruptedException {
/*
* nav-input nav-progressive-attribute --> two class names, try going with one
* else
* compound class names not permitted
*/
driver.findElement(By.className("nav-input")).sendKeys("by class name");
Thread.sleep(10000L);
driver.findElement(By.className("nav-input")).clear();
}

@Test
public void identifyElementByCSSSelector() throws InterruptedException {
driver.findElement(By.cssSelector("input[id='twotabsearchtextbox']")).sendKeys("by css selector");
Thread.sleep(10000L);
driver.findElement(By.cssSelector("input[id='twotabsearchtextbox']")).clear();
}

@Test
public void identifyElementByLinkText(){
driver.findElement(By.linkText("Best Sellers")).click();
}

@Test
public void identifyElementByXpath() throws InterruptedException {
driver.findElement(By.xpath("//input[@id='twotabsearchtextbox']")).sendKeys("by xpath");
Thread.sleep(10000L);
driver.findElement(By.xpath("//*[@id='twotabsearchtextbox']")).clear();
}

@AfterClass
public void closeBrowser(){
driver.quit();
}
}
css selectors examples:
tagname.className --> identifying based on classname
tagname child --> identifying element based on hierarchy
tagname[attribute=value] --> identifying element based on attribute and value
tagname[attribute*=value] --> identifying element based on regular expression 

xpath examples:
//tagname[@attribute='value'] --> identifying element based on attribute and value
//*[@attribute='value'] --> identifying element based on attribute and value
//tagname/child --> identifying element based on hierarchy
//tagname/child[7] --> identifying element based on indexing
//tagname[contains(@id,'value')] --> identifying element based on regular expression
//tagname[text()='value'] --> identifying element based on text
//tagname[@id='value']/parent::tag --> navigating from child to parent

Browser Navigations

driver.get("https://amazon.in");
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));

driver.navigate().to("https://google.com");
driver.navigate().back();
driver.navigate().forward();
driver.navigate().refresh();

Handling Drop down

We use select class
@Test
public void testDropdown(){
WebElement searchDropDown = driver.findElement(By.xpath("//*[@id='searchDropdownBox']"));
Select staticDropdown = new Select(searchDropDown);
System.out.println("default selected option : "+staticDropdown.getFirstSelectedOption().getText());
staticDropdown.selectByIndex(5);
System.out.println("selected option : "+staticDropdown.getFirstSelectedOption().getText());
staticDropdown.selectByValue("search-alias=stripbooks");
System.out.println("selected option : "+staticDropdown.getFirstSelectedOption().getText());
staticDropdown.selectByVisibleText("Furniture");
System.out.println("selected option : "+staticDropdown.getFirstSelectedOption().getText());
}
handling dynamic drop down
@Test
public void handlingDynamicDropdown() throws InterruptedException {
driver.findElement(By.xpath("//input[@id='twotabsearchtextbox']")).sendKeys("la");
Thread.sleep(10000L);
List<WebElement> elements = driver.findElements(By.cssSelector("div.autocomplete-results-container"));
for(WebElement element: elements){
System.out.println(element.getText().trim());
}
}

Handling alert

we need switch driver to alert to handle pop up
@Test
public void handleAlert() throws InterruptedException {
driver.findElement(By.id("alertbtn")).click();
Thread.sleep(5000L);
System.out.println(driver.switchTo().alert().getText());
driver.switchTo().alert().accept();
Thread.sleep(5000L);
}

@Test
public void handleOkAndCancelAlerts() throws InterruptedException {
driver.findElement(By.id("confirmbtn")).click();
Thread.sleep(5000L);
System.out.println(driver.switchTo().alert().getText());
driver.switchTo().alert().dismiss();
Thread.sleep(5000L);
driver.findElement(By.id("confirmbtn")).click();
Thread.sleep(5000L);
driver.switchTo().alert().accept();
Thread.sleep(5000L);
}

synchronization

Implicit wait

driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));

Explicit wait

@Test
public void explicitWaits() throws InterruptedException {
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("macbook");
driver.findElement(By.id("twotabsearchtextbox")).sendKeys(Keys.ENTER);

By locator = By.xpath("//*[@data-index=3]");
WebDriverWait webDriverWait = new WebDriverWait(driver, Duration.ofSeconds(5));
webDriverWait.until(ExpectedConditions.visibilityOfElementLocated(locator));

driver.findElement(locator).click();
Thread.sleep(5000L);
}

Fluent wait

@Test
public void fluentWait() throws InterruptedException {
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("macbook");
driver.findElement(By.id("twotabsearchtextbox")).sendKeys(Keys.ENTER);

Wait<WebDriver> wait = new FluentWait<>(driver).withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofSeconds(30)).ignoring(NoSuchElementException.class);
WebElement element = wait.until(new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
if(driver.findElement(By.xpath("//*[@data-index=3]")).isDisplayed())
return driver.findElement(By.xpath("//*[@data-index=3]"));
else
return null;
}
});

driver.findElement(By.xpath("//*[@data-index=3]")).click();
Thread.sleep(5000L);
}

Actions

used to do mouse hover operations
@Test
public void testMouseHover() throws InterruptedException {
Actions actions = new Actions(driver);
WebElement element= driver.findElement(By.xpath("//*[text()='Hello, Sign in']"));
actions.moveToElement(element).build().perform();
Thread.sleep(5000L);
}
for composite actions
@Test
public void testCompositeActions() throws InterruptedException {
Actions actions = new Actions(driver);
WebElement element= driver.findElement(By.id("twotabsearchtextbox"));
actions.moveToElement(element).click().keyDown(Keys.SHIFT).sendKeys("macbook").doubleClick().build().perform();
Thread.sleep(5000L);
}
for right clicks
@Test
public void testRightClick() throws InterruptedException {
Actions actions = new Actions(driver);
WebElement element= driver.findElement(By.xpath("//*[text()='Hello, Sign in']"));
actions.moveToElement(element).contextClick().build().perform();
Thread.sleep(5000L);
}

Window Handles

@Test
public void testSwitch() throws InterruptedException {
driver.findElement(By.id("twotabsearchtextbox")).sendKeys("macbook");
driver.findElement(By.id("twotabsearchtextbox")).sendKeys(Keys.ENTER);
Thread.sleep(5000L);
driver.findElement(By.xpath("//*[@data-index=3]")).click();
Thread.sleep(5000L);
Set<String> windowHandles = driver.getWindowHandles();
Iterator<String> iterator = windowHandles.iterator();
String parent = iterator.next();
String child = iterator.next();
driver.switchTo().window(child);
Thread.sleep(5000L);
}

Handling Frames

@Test
public void testFrames() throws InterruptedException {
WebElement frame = driver.findElement(By.xpath("//*[@id=\"content\"]/iframe"));
driver.switchTo().frame(frame);

WebElement src = driver.findElement(By.id("draggable"));
WebElement dest = driver.findElement(By.id("droppable"));

Actions actions = new Actions(driver);
actions.dragAndDrop(src,dest).build().perform();
Thread.sleep(5000L);

driver.switchTo().defaultContent(); // comes back to the main window
}

Open Links in Multiple tabs

By holding control key and clicking, links will open in separate tabs, this action can be performed in selenium like below

String click = Keys.chord(Keys.CONTROL, Keys.ENTER);
driver.findElement(By.xpath("")).sendKeys(click);

Scrolling

@Test
public void testScrolling() throws InterruptedException {
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
javascriptExecutor.executeScript("window.scrollBy(0,500)");
Thread.sleep(5000L);
javascriptExecutor.executeScript("document.querySelector(\".tableFixHead\").scrollTop=5000");
Thread.sleep(5000L);
// to scroll till end of page
javascriptExecutor.executeScript("window.scrollTo(0, document.body.scrollHeight)");
}

WebTable

without streams:
@Test
public void testDataRetrieval(){
List<WebElement> elements = driver.findElements(By.xpath("//*[@id='product']/tbody/tr"));
for(WebElement element: elements){
List<WebElement> data = element.findElements(By.tagName("td"));
for(WebElement value: data){
System.out.print(value.getText().trim()+" -- ");
}
System.out.println();
}
}
with streams
@Test
public void testDataRetrievalUsingStreams(){
List<WebElement> elements = driver.findElements(By.xpath("//*[@id='product']/tbody/tr"));
for(WebElement element: elements) {
List<WebElement> data = element.findElements(By.tagName("td"));
data.stream().map(s->s.getText().trim()).forEach(s-> System.out.print(s+"--"));
System.out.println();
}
}

Handling Certs

WebDriver driver;
@BeforeClass
public void invokeChromeBrowser(){
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setAcceptInsecureCerts(true);
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
driver = new ChromeDriver(chromeOptions);
}

@Test
public void testForCerts() throws InterruptedException {
driver.get("https://expired.badssl.com/");
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
Thread.sleep(5000L);
System.out.println(driver.getTitle());
}
refer to their official website for more configurations - ChromeDriver - WebDriver for Chrome - Capabilities & ChromeOptions (chromium.org)

Broken Links

@Test
public void validateBrokenLinks() throws IOException {
String url = "https://google.com/";
HttpURLConnection httpURLConnection = (HttpURLConnection)new URL(url).openConnection();
httpURLConnection.setRequestMethod("HEAD");
httpURLConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
System.out.println("response code is "+responseCode);
}

Soft Asserts

With Assert, it fails test immediately, but with Soft, it will continue execution and fails at the end
@Test
public void softAssert(){
SoftAssert softAssert = new SoftAssert();
softAssert.assertTrue(false);
softAssert.assertTrue(false);
softAssert.assertTrue(false);
softAssert.assertAll();
}

Relative Locators

helps with identifying elements above, below, left, right of a webelement.
@Test
public void testRelativeLocators(){
driver.findElement(By.xpath("//*[@id='nav-link-accountList-nav-line-1']")).click();
WebElement emailField = driver.findElement(By.xpath("//input[@id='ap_email']"));
String label = driver.findElement(with(By.tagName("label")).above(emailField)).getText().trim();
System.out.println("Printing label"+label);
}

Multiple windows

In selenium 4, there is a provision for switching to new window
@Test
public void testMultipleWindows(){
driver.switchTo().newWindow(WindowType.WINDOW);
driver.switchTo().newWindow(WindowType.TAB);
// you perform opertations on those tabs or windows by switching
}

Web element screenshot

WebElement emailField = driver.findElement(By.xpath("//input[@id='ap_email']"));
emailField.sendKeys("hello");
File file = emailField.getScreenshotAs(OutputType.FILE);// logic for screenshot

Get web element dimensions

int height = emailField.getRect().getHeight();
int width = emailField.getRect().getWidth();
System.out.println("Height and width are : "+height+"-"+width);

Selenium Grid

  1. It's a smart proxy server, that helps to runs tests parallelly
  2. Selenium Code --> HUB --> nodes
  3. code interacts with hub, and hub takes care executing scripts on nodes
  4. Hub is a union of following components
    1. Router --> incoming request from selenium
    2. Distributor --> decides on which node it has to execute
    3. Session Map --> stores session ID and node address
    4. New Session Queue --> All the session will be queued here
    5. Event bus --> all communications happens over event bus.
  5. download selenium grid jar - Downloads | Selenium
  6. Note:place jar and drivers in same folder, from there start the hub
  7. start hub --> java -jar selenium-server-4.1.3.jar hub
  8. check status of grid here - http://localhost:4444/ui/index.html#/
  9. start node --> java -jar selenium-server-4.1.3.jar node --detect-drivers true
  10. grid console will be showing this node (4 chrome, 4 safari, 4 IE etc)
  11. you can start another node in physical machine by running above command with additional parameters java -jar selenium-server-4.1.3.jar node --detect-drivers true --publish-events tcp://<ip address of hub>:4442 --subscribe-events tcp://<ip address of hub>:4443
    1. Note: we are simply pinging publishing and subscribing ports of hub to register node
  12. check status of grid, where you will see another node
  13. code to run tests via grid
package grid.day15;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.annotations.Test;

import java.net.MalformedURLException;
import java.net.URL;

public class GridTest {
@Test
public void testChrome() throws MalformedURLException, InterruptedException {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setBrowserName("chrome");
WebDriver driver = new RemoteWebDriver(new URL("http://192.168.29.186:4444"), desiredCapabilities);

driver.get("https://google.com");
driver.findElement(By.name("q")).sendKeys("selenium");
driver.findElement(By.name("q")).sendKeys(Keys.ENTER);
Thread.sleep(5000L);
driver.quit();
}
}
Note: Grid and node should be up and running

Selenium Chrome Dev Tools integration

  1. Chrome dev tools is built into google chrome browser, which can be used for deeper analysis.
  2. CDP(chrome dev tools protocol) is exposed, so that we can access dev tools programatically.
  3. Selenium4 created a wrapper around it and can be used in our tests. Some of the cool features that we can leverage are
    1. mock network requests and responses
    2. injecting session cookies or bypassing login etc
    3. mobile views
    4. sites performance
    5. geolocations of the user
    6. blocking network requests
    7. java script debugging
  4. For reference - Chrome DevTools Protocol

For device emulation:

Note: we are enabling mobile view
@Test
public void testChromeViaWrapper() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Emulation.setDeviceMetricsOverride(600, 1000, 70, true,
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(),
Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty()));
driver.get("https://google.com");
Thread.sleep(5000L);
driver.quit();
}
we can invoke cdp commands directly as well, without selenium wrapper. Make sure to create a hash map.
@Test
public void testChromeViaCDP() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
Map deviceMetrics = new HashMap();
deviceMetrics.put("width", 600);
deviceMetrics.put("height", 1000);
deviceMetrics.put("deviceScaleFactor", 50);
deviceMetrics.put("mobile", true);
driver.executeCdpCommand("Emulation.setDeviceMetricsOverride", deviceMetrics);
driver.get("https://google.com");
driver.findElement(By.name("q")).sendKeys("Selenium");
driver.findElement(By.name("q")).sendKeys(Keys.ENTER);
Thread.sleep(5000L);
driver.quit();
}

Localization

Based on latitude and longitude, languages changes on the website, we can validate them as well.
@Test
public void testLocalization() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
Map<String, Object> coordinates = new HashMap<>();
coordinates.put("latitude", 39);
coordinates.put("longitude", 116);
coordinates.put("accuracy", 100);
driver.executeCdpCommand("Emulation.setGeolocationOverride", coordinates);
driver.get("https://google.com");
driver.findElement(By.name("q")).sendKeys("netflix");
driver.findElement(By.name("q")).sendKeys(Keys.ENTER);
Thread.sleep(10000L);
driver.quit();
}

Extract network responses

@Test
public void networkTracking() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir")+"\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(), Optional.empty(),
Optional.empty()));

devTools.addListener(Network.requestWillBeSent(), requestWillBeSent -> {
Request request = requestWillBeSent.getRequest();
System.out.println("Requests : "+request.getUrl());
});

devTools.addListener(Network.responseReceived(), responseReceived -> {
Response response = responseReceived.getResponse();
System.out.println("Response : "+response.getUrl());
System.out.println("Response : "+response.getStatus());
if(response.getStatus().toString().startsWith("4")){
System.out.println("Response : "+response.getUrl());
}
});

driver.get("https://amazon.in");
Thread.sleep(10000L);
driver.quit();
}

Mock Network Request

Mock the endpoint with required endpoint
Example: 
getMoviesListEnglish, which can be mocked with getMovielsListHindi.

package selenium4.cdp.day19;

import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v99.fetch.Fetch;
import org.testng.annotations.Test;

import java.util.Optional;

public class NetworkMocking {
@Test
public void testNetworkMocking() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Fetch.enable(Optional.empty(), Optional.empty()));
devTools.addListener(Fetch.requestPaused(), requestPaused -> {
if (requestPaused.getRequest().getUrl().contains("shetty")) {
String mockedURL = requestPaused.getRequest().getUrl().replace("=shetty", "Badguy");
System.out.println(mockedURL);
devTools.send(Fetch.continueRequest(requestPaused.getRequestId(), Optional.of(mockedURL),
Optional.of(requestPaused.getRequest().getMethod()), Optional.empty(),
Optional.empty(), Optional.empty()));
} else {
devTools.send(Fetch.continueRequest(requestPaused.getRequestId(), Optional.of(requestPaused.getRequest().getUrl()),
Optional.of(requestPaused.getRequest().getMethod()), Optional.empty(),
Optional.empty(), Optional.empty()));
}
});
driver.get("https://rahulshettyacademy.com/angularAppdemo");
driver.findElement(By.xpath("//button[@routerlink='/library']")).click();
Thread.sleep(10000L);
driver.quit();
}
}

Network Failures

@Test
public void testNetworkErrors() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
Optional<List<RequestPattern>> requestPatterns = Optional.of(Arrays.asList(new RequestPattern(Optional.of("*GetBook*"), Optional.empty(), Optional.empty())));
devTools.send(Fetch.enable(requestPatterns, Optional.empty()));
devTools.addListener(Fetch.requestPaused(), requestPaused -> {
devTools.send(Fetch.failRequest(requestPaused.getRequestId(), ErrorReason.FAILED));
});
driver.get("https://rahulshettyacademy.com/angularAppdemo");
driver.findElement(By.xpath("//button[@routerlink='/library']")).click();
Thread.sleep(10000L);
driver.quit();
}

Block unwanted request call

@Test
public void testBlockNetworkCalls() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
devTools.send(Network.setBlockedURLs(ImmutableList.of("*jpg", "*css")));

driver.get("https://amazon.in");
Thread.sleep(10000L);
driver.quit();
}

Emulate network speed

@Test
public void testNetworkSpeed(){
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
DevTools devTools = driver.getDevTools();
devTools.createSession();
devTools.send(Network.enable(Optional.empty(), Optional.empty(), Optional.empty()));
devTools.send(Network.emulateNetworkConditions(false, 3000, 20000, 100000,
Optional.of(ConnectionType.ETHERNET)));
}

Basic Authentication

sometimes you come across browsers, that needs authentication. (usually happens in your work environment when connected on vpn etc.)

public class BasicAuthentication {
@Test
public void testBasicAuthentication() throws InterruptedException {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
ChromeDriver driver = new ChromeDriver();
Predicate<URI> predicate = uri -> uri.getHost().contains("httpbin.org");

((HasAuthentication)driver).register(predicate, UsernameAndPassword.of("foo", "bar"));
driver.get("http://httpbin.org/basic-auth/foo/bar");
Thread.sleep(10000L);
driver.quit();
}
}

Window authentication pop ups

We can pass username and password in the url itself
like below where admin and admin is the username and password
driver.get("http://admin:admin@the-internet.herokuapp.com");

To get Browser logs

LogEntries logEntries = driver.manage().logs().get(LogType.BROWSER);
List<LogEntry> all = logEntries.getAll();
for(LogEntry entry:all)
System.out.println(entry.getMessage())

File Upload using AutoIT

  1. download autoit from AutoIt Downloads - AutoIt (autoitscript.com)
  2. open editor from - C:\Program Files (x86)\AutoIt3\SciTE
  3. write scirpt, compile to create .exe
  4. now execute this exe from java using Runtime.getRuntime().exec("path of exe")

validate download files

  1. use File.exists to validate whether file is downloaded or not

Framework concepts

  1. Use pico container for dependency injection
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>7.2.3</version>
<scope>test</scope>
</dependency>
  1. Create TestContextSetup class where required objects will be initialized.
package utils;

import pageObjects.PageObjectManager;

public class TestContextSetup {
private final PageObjectManager pageObjectManager;
private final TestBase testBase;
private final GenericUtils genericUtils;

public TestContextSetup() {
this.testBase = new TestBase();
this.pageObjectManager = new PageObjectManager(testBase.webDriverManager());
this.genericUtils = new GenericUtils(testBase.webDriverManager());
}

public PageObjectManager getPageObjectManager() {
return pageObjectManager;
}

public TestBase getTestBase() {
return testBase;
}

public GenericUtils getGenericUtils() {
return genericUtils;
}
}
  1. Let's have a TestBase class where driver is initialized
package utils;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import java.io.FileInputStream;
import java.io.IOException;
import java.time.Duration;
import java.util.Properties;

public class TestBase {
public WebDriver driver;
public WebDriver webDriverManager(){

FileInputStream fileInputStream;
Properties properties = null;

try {
fileInputStream = new FileInputStream(System.getProperty("user.dir") +
"\\src\\test\\resources\\global.properties");
properties = new Properties();
properties.load(fileInputStream);
} catch (IOException e) {
e.printStackTrace();
}

if(driver == null) {
assert properties != null;
if(properties.getProperty("browser").equalsIgnoreCase("chrome")) {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\chromedriver.exe");
driver = new ChromeDriver();
driver.get(properties.getProperty("url"));
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
}
}
return driver;
}
}
  1. Generic utils where common functionalities will be written
package utils;

import org.openqa.selenium.WebDriver;

import java.util.Iterator;
import java.util.Set;

public class GenericUtils {

private final WebDriver driver;

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

public void switchWindow(){
Set<String> windowHandles = driver.getWindowHandles();
Iterator<String> iterator = windowHandles.iterator();
String parentWindow = iterator.next();
String childWindow = iterator.next();
driver.switchTo().window(childWindow);
}
}
  1. Creating a PageOjbectManager which helps us to initialize page objects
package pageObjects;

import org.openqa.selenium.WebDriver;

public class PageObjectManager {

private final WebDriver driver;

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

public HomePage getHomePage() {
return new HomePage(driver);
}

public ProductDetailsPage getProductDetailsPage() {
return new ProductDetailsPage(driver);
}
}
  1. Implemented Page object for HomePage
public class HomePage {

private final WebDriver driver;

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

private final By searchBox = By.xpath("//*[@id=\"twotabsearchtextbox\"]");
private final By firstProductLink = By.xpath("//*[@data-index=3]");

public void searchProduct(String productName){
driver.findElement(searchBox).sendKeys(productName);
driver.findElement(searchBox).sendKeys(Keys.ENTER);
}

public void clickOnFirstProduct(){
driver.findElement(firstProductLink).click();
}

}
  1. TestNG runner file
package runners;

import io.cucumber.testng.AbstractTestNGCucumberTests;
import io.cucumber.testng.CucumberOptions;
import org.testng.annotations.DataProvider;

@CucumberOptions(
features = "src/test/java/features",
glue = "stepDefinitions",
monochrome = true,
tags = "@Functional",
plugin = {
"html:target/cucumber.html", "json:target/cucumber.json",
"com.aventstack.extentreports.cucumber.adapter.ExtentCucumberAdapter:",
"rerun:target/failed_scenarios.txt"
}
)
public class TestNGRunner extends AbstractTestNGCucumberTests {
@DataProvider(parallel = true)
@Override
public Object[][] scenarios() {
return super.scenarios();
}
}
  1. For extent reporting, we should configure extent.properties and have the dependencies
<!-- https://mvnrepository.com/artifact/com.aventstack/extentreports -->
<dependency>
<groupId>com.aventstack</groupId>
<artifactId>extentreports</artifactId>
<version>5.0.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/tech.grasshopper/extentreports-cucumber7-adapter -->
<dependency>
<groupId>tech.grasshopper</groupId>
<artifactId>extentreports-cucumber7-adapter</artifactId>
<version>1.3.0</version>
</dependency>
  1. extent.properties
extent.reporter.spark.start=true
extent.reporter.spark.out=test-output/SparkReport/Spark.html
screenshot.dir=test-output/screenshots/
screenshot.rel.path=../screenshots/
  1. Sample feature file
Feature: Product Search
@Functional
Scenario Outline: Get Product Price
Given user lands on home page
When user search for <value>
Then open first one from the product list and get the price
Examples:
|value|
|macbook|
|dell |
|asus |

  1. Step definitions
package stepDefinitions;

import io.cucumber.java.en.Given;
import io.cucumber.java.en.When;
import pageObjects.HomePage;
import utils.TestContextSetup;

public class HomePageStepDefinition {

private final TestContextSetup testContextSetup;

public HomePageStepDefinition(TestContextSetup testContextSetup){
this.testContextSetup = testContextSetup;
}

@Given("user lands on home page")
public void user_lands_on_home_page() {
testContextSetup.getTestBase().webDriverManager();
testContextSetup.getPageObjectManager().getHomePage();
}

@When("^user search for (.+)$")
public void user_search_for(String value) {
HomePage homePage = testContextSetup.getPageObjectManager().getHomePage();
homePage.searchProduct(value);
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
homePage.clickOnFirstProduct();
}
}
  1. How hooks are managed
package stepDefinitions;

import io.cucumber.java.After;
import io.cucumber.java.AfterStep;
import io.cucumber.java.Scenario;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import utils.TestContextSetup;

import java.io.File;
import java.io.IOException;

public class Hooks {
private final TestContextSetup testContextSetup;

public Hooks(TestContextSetup testContextSetup) {
this.testContextSetup = testContextSetup;
}

@After
public void closeBrowser(){
testContextSetup.getTestBase().webDriverManager().quit();
}

@AfterStep
public void takeScreenshot(Scenario scenario) throws IOException {
if(scenario.isFailed()){
File file = ((TakesScreenshot)testContextSetup.getTestBase().webDriverManager()).getScreenshotAs(OutputType.FILE);
byte[] content = FileUtils.readFileToByteArray(file);
scenario.attach(content, "image/png", "image");
}
}
}
  1. global.properties
browser=chrome
url=https://www.amazon.in/

Apache Log4j

  1. It's a logging framework.
  2. download maven dependency from official website - Log4j – Maven, Ivy, Gradle, and SBT Artifacts (apache.org)
  3. make sure you have dependencies added for core and api.
private static final Logger logger = LogManager.getLogger(HomePageStepDefinition.class.getName());
  1. followed by you can use logger.info() or logger.error() or logger.debug() depending on your need.
  2. Make sure to create config file and name it as log4j2.xml
  3. Note: Place it in src/test/resources folder
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Appender tag helps to record logs in console or any other file
Logger tag help with control of logs like error, trace etc

Resources:

  1. For more details Please refer to my github project - itsvinayr/SeleniumBasics: Project designed to cover all selenium concepts with examples (github.com)
  2. For more details on the framework, please refer to my github project - itsvinayr/SeleniumBDDFramework: E2E framework developed with Selenium and Cucumber to automation functional test cases. (github.com)
  3. To understand concepts related to Cucumber - Please refer to my blog - Cucumber - BDD Framework (vinayraghumanda.blogspot.com)
  4. Official site for selenium - Downloads | Selenium

Comments

Popular posts from this blog

TestNg - Test Automation Framework

React Js and Redux

Appium 7 - Android Test Automation