Many organizations aim to execute automation tests across various browsers, such as Chrome, Firefox, Edge, and others, to ensure a consistent user experience. Serenity offers the capability to run tests on different browsers, supporting this need.
We can set up multiple driver configurations using the environments section, as demonstrated below.
Handling token expiration and automatically refreshing tokens in REST Assured involves a few steps to ensure your tests can obtain a fresh token when the current one expires.
Add the below-mentioned dependencies to the Maven project.
Obtain Initial Access Token:– Implement a method to obtain the initial access token from the authentication server.
Store Token and Expiration Time:- Use a structure to store the access token and its expiration time.
Check Token Validity:– Before making an API request, check if the token is still valid. If it’s expired or about to expire, refresh it.
Refresh the Token:- Implement a method to refresh the token.
Update Token Storage:– Store the new token and update the expiration time after refreshing.
import io.restassured.RestAssured;
import io.restassured.response.Response;
import java.time.Instant;
public class TokenGeneration {
private static String accessToken;
private static Instant tokenExpiryTime;
Response response;
int expiresIn;
// Method to obtain initial token
public static String getAccessToken() {
if (accessToken == null || isTokenExpired()) {
refreshAccessToken();
}
return accessToken;
}
// Method to check if the token is expired
private static boolean isTokenExpired() {
return tokenExpiryTime == null || Instant.now().isAfter(tokenExpiryTime);
}
// Method to refresh token
private static void refreshAccessToken() {
response = RestAssured.given()
.contentType("application/x-www-form-urlencoded")
.formParam("grant_type", "client_credentials")
.formParam("client_id", "your-client-id")
.formParam("client_secret", "your-client-secret")
.post("https://your-auth-server.com/oauth/token");
accessToken = response.jsonPath().getString("access_token");
expiresIn = response.jsonPath().getInt("expires_in");
tokenExpiryTime = Instant.now().plusSeconds(expiresIn);
System.out.println("Access Token: " + accessToken);
System.out.println("Token Expiry Time: " + tokenExpiryTime);
}
}
Instant.now – The now() method of Instant returns the current time from the system clock. If the current time is “2023-10-01T12:00:00Z”, “Instant.now()“ would represent this moment in time.
isAfter(tokenExpiryTime) – checks if the current time is after the token’s expiration time.
plusSeconds(expiresIn)– This method adds a specified number of seconds to the Instant object. If expiresIn is “3600“ seconds (which is equivalent to 1 hour), it adds an hour to the current Instant.
Token Expiry Buffer:– Consider implementing a buffer time before the actual expiry to refresh the token. This prevents the edge cases where the token might expire during an API call.
Are you familiar with Rest API and want to test your understanding? This post contains 25 useful TestNG multiple-choice questions (quiz) to self-test your knowledge of TestNG .
1) 1) A testing framework for java inspired by JUnit
2) 2) Cédric Beust
3) 2) After
4) 2) Next Generation
5) 4) All of the above
TestNG offers extensive control over the execution of test cases, including setting dependencies, priorities, and parallel execution.
Prior to running test case X, run multiple test cases as a pre-request – TestNG allows us to set dependencies between test methods using dependsOnMethods or dependsOnGroups, so you can ensure that certain test cases run before others.
TestNG provides powerful features such as annotations, test grouping, sequencing, and parameterization, which resolve the limitations found in earlier frameworks like JUnit.
6) 4) None of the above
7) 4) All of the above
8) 2) Independently of
This means that each test case can be executed on its own without depending on the execution or results of other test cases. However, TestNG also allows us to create dependencies between test cases using the dependsOnMethods or dependsOnGroups attributes if needed.
9) 1) Java
10) 4) All of the above
11) 3) XML
In TestNG, an XML file (commonly named as testng.xml) is used to define and configure test suites, test groups, and the sequence of test execution.
12) 2) Testng.xml
Sample testng.xml
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" >
<suite name="SampleSuite">
<test name="SampleTest">
<classes>
<class name="com.example.MyTestClass" />
</classes>
</test>
</suite>
13) 4) All of the above
14) 3) Both A and B
15) 4) All of the above
16) 1) BeforeSuite
17) 3) Before each and every test method in the class i.e., the method with @BeforeMethod annotation will execute for every test method in the class
18) 2) Once before the execution of test methods in the class begins
19) 1) AfterSuite
@AfterSuite: This method is executed after all the test methods in an entire suite have been completed.
20) 2) Annotation
21) 3) BeforeTest
@BeforeTest: This method is executed before any test methods in the <test> tag in the testng.xml file, which can include multiple classes and folders.
22) 2) AfterTest
@AfterTest: This method is executed after all the test methods in the <test> tag in the testng.xml file have been run, which can include multiple classes.
23) 2) BeforeClass
@BeforeClass: This method is invoked before the first test method in the current class is executed.
24) 3) AfterClass
The annotations have different scopes:
@AfterClass:This method is invoked after all the test methods in the current class have been executed.
@AfterMethod: Runs after each individual test method.
@AfterSuite: Runs once after all the tests in the entire suite have finished.
@AfterTest: Runs after all test methods in the <test> tag of the testng.xml file.
25) 1) BeforeMethod
Each of these annotations is executed before a test method, but at different levels:
@BeforeMethod: Runs before each individual test method in the current class.
@BeforeTest: Runs before any test methods in the <test> tag in the testng.xml file.
@BeforeClass: Runs before the first test method in the current class.
@BeforeSuite: Runs once before all tests in the entire suite defined in the testng.xml file.
Are you familiar with TestNG and want to test your understanding? This post contains 25 useful TestNG multiple-choice questions (quiz) to self-test your knowledge.
In this tutorial, we will discuss the ToolTip and how to automate the ToolTip in Selenium.
What is ToolTip?
A ToolTip is a small, informational popup that appears when a user hovers over an element such as a button, image, or link. It provides additional context or information about the element. Tooltips are often implemented using the titleattribute in HTML or through JavaScript and CSS for custom tooltips.
Tool Tips are implemented in different ways–
The basic implementation is based on HTML’s “title”attribute. getAttribute(title) gets the value of the tooltip.
Another tool tip implementation is using Action Class.
This tutorial explains the steps to automate the Custome ToolTip where no title attribute is present.
Let’s understand how one can automate the process of verifying tooltip in Selenium.
To test tooltips in Selenium, you generally follow these steps:
1. Locate the Element with Tooltip: Identify the element that contains the tooltip. 2. Hover Over the Element: Use Actions class to simulate mouse hover event. 3. Capture the Tooltip Text: Retrieve the text from the tooltip element. 4. Validate the Text: Assert that the tooltip text matches the expected value.
Implementation Steps
Locate the Tooltip Element
Identify the element that contains the tooltip. Here, the element has been found using By.id().
Identify the element that contains the tooltip using Actionsclass to hover over the element.
Actions actions = new Actions(driver);
actions.moveToElement(elementWithTooltip).perform();
Retrieve Tooltip Text
Capturing the tooltip text typically found in the titleattribute. But in this case, there is no title in page source, so I have created an xpath using contains(text()) to find the tooltip text.
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
WebElement tooltip = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'You hovered over the Button')]")));
Validate the Text
Comparing the captured text with the expected tooltip text.
if (expectedTooltipText.equals(actualTooltipText)) {
System.out.println("Tooltip text is correct!");
} else {
System.out.println("Tooltip text is incorrect!");
}
The complete program is shown below:
package com.example;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.time.Duration;
public class TooltipTest_Demo {
static WebDriver driver;
static String expectedTooltipText = "You hovered over the Button";
static String actualTooltipText;
public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
driver = new ChromeDriver(options);
driver.manage().window().maximize();
driver.get("https://demoqa.com/tool-tips");
// Locate the element with the tooltip
WebElement elementWithTooltip = driver.findElement(By.id("toolTipButton"));
// Perform hover action using Actions class
Actions actions = new Actions(driver);
actions.moveToElement(elementWithTooltip).perform();
// Wait for the tooltip to be visible
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
WebElement tooltip = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'You hovered over the Button')]")));
// Check the tooltip text
actualTooltipText = tooltip.getText();
System.out.println("Actual Tooltip Text: " + actualTooltipText);
if (expectedTooltipText.equals(actualTooltipText)) {
System.out.println("Tooltip text is correct!");
} else {
System.out.println("Tooltip text is incorrect!");
}
driver.quit();
}
}
The output of the above program is
We are using WebDriverWaitto wait for the hover text to appear.
Summary
Custom ToolTip can be automated using Action class.
moveToElement(element) of Actions class is used to mouse hover an element.
Build() method of Actions class builds the sequence of user actions into an Action object.
Perform() of Action class executes all the sequence of user actions at once.
Fluent waits provide more flexibility, allowing us to specify polling intervals and ignore specific exceptions during the wait time. Fluent Wait not only lets you specify the maximum amount of time to wait for a condition but also allows you to define the frequency with which the condition is checked and to ignore specific exceptions during the wait time.
Key Features of Fluent Wait:
Timeout: The maximum amount of time to wait for the condition.
Polling Frequency: How often the condition should be checked.
Ignoring Exceptions: The ability to ignore specific types of exceptions while waiting.
Below is an example that shows that loading of element take sometime. So to wait for the element, we can use the Fluent Wait.
Step 1
Step 2
Step 3
Below is the example of Fluent wait.
import net.serenitybdd.annotations.DefaultUrl;
import net.serenitybdd.annotations.Managed;
import net.serenitybdd.core.annotations.findby.FindBy;
import net.serenitybdd.core.pages.PageObject;
import net.serenitybdd.core.pages.WebElementFacade;
import net.serenitybdd.junit.runners.SerenityRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.ElementNotInteractableException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.FluentWait;
import java.time.Duration;
import java.util.function.Function;
@RunWith(SerenityRunner.class)
@DefaultUrl("http://the-internet.herokuapp.com/dynamic_loading/1")
public class FluentWait_Demo extends PageObject {
@Managed
WebDriver driver;
@FindBy(xpath = "//*[@id='start']/button")
WebElementFacade startButton;
@FindBy(xpath = "//*[@id='finish']/h4")
WebElementFacade pageText;
@Test
public void fluentWaitDemo() throws InterruptedException {
open();
startButton.click();
waitForElementWithFluentWait(pageText);
}
public void waitForElementWithFluentWait(WebElement pageText) {
FluentWait wait = new FluentWait<>(getDriver())
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(ElementNotInteractableException.class);
wait.until((Function<WebDriver, Boolean>)
driver -> pageText.isDisplayed());
System.out.println("Text :" + pageText.getText());
System.out.println("Fluent Time defined for the test (in seconds) :" + getWaitForTimeout().toSeconds());
}
}
Explanation:
withTimeout(Duration.ofSeconds(10)): Specifies the maximum time to wait for the condition to be met, which is 30 seconds in this case.
pollingEvery(Duration.ofSeconds(2)): Specifies the interval at which the check should be performed, here it is every 5 seconds.
ignoring(ElementNotInteractableException.class): Instructs the wait to ignore ElementNotInteractableException that might occur during the polling period.
The output of the above program is
Fluent Wait supports various conditions similar to explicit waits, such as:
visibilityOfElementLocated
presenceOfElementLocated
elementToBeClickable
textToBePresentInElementLocated
alertIsPresent
elementToBeSelected
frameToBeAvailableAndSwitchToIt
Custom conditions
We can use Lambda expression to simplify the condition:
public void waitForElementWithFluentWait(WebElement pageText) {
FluentWait wait = new FluentWait<>(getDriver())
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(ElementNotInteractableException.class);
wait.until(driver -> pageText.isDisplayed());
System.out.println("Text :" + pageText.getText());
System.out.println("Fluent Time defined for the test (in seconds) :" + getWaitForTimeout().toSeconds());
}
We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
Step 6 – Create a Row. A spreadsheet consists of rows and cells. It has a grid layout.
XSSFRow row = sheet.createRow(rownum++);
Step 7 – Import XSSFRow from package
import org.apache.poi.xssf.usermodel.XSSFRow;
Step 8 – Create cells in a row. A row is a collection of cells. When you enter data in the sheet, it is always stored in the cell.
XSSFCell cell = row.createCell(cellnum++);
Step 9 – Import XSSFCell from package.
XSSFCell cell = row.createCell(cellnum++);
Step 10 – Iterate over Data and Write to the sheet
int rownum = 0;
for (Object[] employeeDetails : data) {
// Create Row
XSSFRow row = sheet.createRow(rownum++);
int cellnum = 0;
for (Object obj : employeeDetails) {
// Create cell
XSSFCell cell = row.createCell(cellnum++);
// Set value to cell
if (obj instanceof String)
cell.setCellValue((String) obj);
else if (obj instanceof Double)
cell.setCellValue((Double) obj);
else if (obj instanceof Integer)
cell.setCellValue((Integer) obj);
}
}
Step 11 – Open a FileOutputStream to a new file named “EmployeeDetails.xlsx”. Write data to an OutputStream. Use the below code to write output stream.
FileOutputStream out = new FileOutputStream(new File("EmployeeDetails.xlsx"));
workbook.write(out);
Step 12 – Close the output stream.
out.close();
Below is the sample code for writing the data in an excel in Java.
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadWriteExcelFile {
public static void main(String[] args) throws IOException {
// create blank workbook
XSSFWorkbook workbook = new XSSFWorkbook();
// Create a blank sheet
XSSFSheet sheet = workbook.createSheet("Write_TestData");
ArrayList<Object[]> data = new ArrayList<Object[]>();
data.add(new String[] { "Name", "Id", "Salary" });
data.add(new Object[] { "Jim", "001A", 10000 });
data.add(new Object[] { "Jack", "1001B", 40000 });
data.add(new Object[] { "Tim", "2001C", 20000 });
data.add(new Object[] { "Gina", "1004S", 30000 });
// Iterate over data and write to sheet
int rownum = 0;
for (Object[] employeeDetails : data) {
// Create Row
XSSFRow row = sheet.createRow(rownum++);
int cellnum = 0;
for (Object obj : employeeDetails) {
// Create cell
XSSFCell cell = row.createCell(cellnum++);
// Set value to cell
if (obj instanceof String)
cell.setCellValue((String) obj);
else if (obj instanceof Double)
cell.setCellValue((Double) obj);
else if (obj instanceof Integer)
cell.setCellValue((Integer) obj);
}
}
try {
// Write the workbook in file system
FileOutputStream out = new FileOutputStream(new File("EmployeeDetails.xlsx"));
workbook.write(out);
out.close();
System.out.println("EmployeeDetails.xlsx has been created successfully");
} catch (Exception e) {
e.printStackTrace();
} finally {
workbook.close();
}
}
}
The output of the above program is
Summary:
Create a WorkBook and Sheet
Prepare the data. Use ArrayList to store the rows of data.
Write Data to the Excel by iterating over each row and cell
Save the Workbook
Handle the exceptions appropriately
That’s it! We have written data in Excel.
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!! Cheers!!
In the previous tutorial, I have explained How to update data in existing excel in Java. In this Java Excel tutorial, I will explain how to create an Excel with formula in a Java program. Excel is very excellent in calculating formulas. The Apache POI library provides excellent support for working with formulas in Excel.
I’m using Apache POI to write data to the excel file. To download and install Apache POI, refer here.
If you are using maven, then you need to add below dependency in pom.xml.
Step 9 – Write the workbook to a File and close the workbook
try {
// Write the workbook in file system
FileOutputStream out = new FileOutputStream(new File("Salary_Slip.xlsx"));
workbook.write(out);
out.close();
System.out.println("Excel written successfully.");
} catch (IOException e) {
e.printStackTrace();
}
In the above line, note that you should make sure that the cell at position (1, 5) does exist, otherwise you get a NullPointerException.
Let us see a program where I have created a cell which contains the formula.
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class FormulaExcelDemo {
public static void main(String[] args) {
// Create object of XSSFWorkbook class
XSSFWorkbook workbook = new XSSFWorkbook();
// Create object of XSSFSheet class
XSSFSheet sheet = workbook.createSheet("Calculate Salary");
// Create Header row using XSSFRow class
XSSFRow header = sheet.createRow(0);
header.createCell(0).setCellValue("Employee_Name");
header.createCell(1).setCellValue("Base_Salary");
header.createCell(2).setCellValue("Variable_Pay");
header.createCell(3).setCellValue("Other_Benefits");
header.createCell(4).setCellValue("Total Salary");
header.createCell(5).setCellValue("Base_Variable Salary");
XSSFRow dataRow = sheet.createRow(1);
dataRow.createCell(0).setCellValue("George");
dataRow.createCell(1).setCellValue(5000);
dataRow.createCell(2).setCellValue(650);
dataRow.createCell(3).setCellValue(1200);
// Set formula
dataRow.createCell(4).setCellFormula("B2+C2+D2");
dataRow.createCell(5).setCellFormula("SUM(B2:C2)");
try {
// Write the workbook in file system
FileOutputStream out = new FileOutputStream(new File("Salary_Slip.xlsx"));
workbook.write(out);
out.close();
System.out.println("Excel written successfully.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
The output of the above program is
Updated Excel
That’s it! Well Done! Cheers!!
Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!
In this tutorial I will explain the steps to delete a directory in Java.
The delete() method of the File class deletes the files and empty directory represented by the current File object. If a directory is not empty or has files, then it can’t be deleted directly. First, empty the directory, then delete the folder.
Suppose there exists a directory with path Desktop\Test. The next image displays the files and directories present inside Test folder. The Test directory has folders Demo_1, Demo_2, and Demo_3.
The next java programs illustrate how to delete a directory. This example uses a recursive method to delete the directory and all its contents, including subdirectories.
package org.example;
import java.io.File;
public class DeleteDirectoryDemo {
public static void main(String[] args) {
String directoryPath = "C:\\Users\\Vibha\\Desktop\\Test";
//Create a file object for the directory
File directory = new File(directoryPath);
if(directory.exists()&& directory.isDirectory()) {
boolean successful = deleteDirectory(directory);
if (successful) {
System.out.println("Directory deleted :" + directoryPath);
} else {
System.out.println("Failed to delete Directory :" + directoryPath);
}
} else {
System.out.println("Directory does not exists :" + directoryPath);
}
}
private static boolean deleteDirectory(File directory) {
File[] allContents = directory.listFiles();
if (allContents != null) {
for (File file : allContents) {
deleteDirectory(file);
System.out.println("File deleted :" + file);
}
}
return directory.delete();
}
}
Explanation
Step 1 – Check if the directory exists.
if(directory.exists()&& directory.isDirectory())
Step 2 – List files in the directory.
File[] allContents = directory.listFiles();
Step 3 – Delete files and subdirectories recursively
In this tutorial, we will discuss how to validate the HTTP response status code, status like, header, body and Content Type using REST Assured. Every HTTP Response received from a server in response to an HTTP request sent by the client has a status code.
Verifying HTTP Response Status Code with Rest Assured
A response code indicating the status of the request (e.g., 200 OK, 404 Not Found). The status code that the server returns tells us whether the request was successful or not. If the request was successful, the server sends the status code in the range of 200-299. If the request was not successful, then the status code other than the range is returned.
The getStatusCode() method returns an integer and then we can verify its value.
Below is an example.
@Test
public void verifyStatusCode() {
String BaseURL = "https://dummy.restapiexample.com/api";
// GIVEN
Response response = given()
// WHEN
.when()
.get("https://reqres.in/api/users/2")
// THEN
.then()
.extract().response();
int actualStatusCode = response.getStatusCode();
System.out.println("Status Code : " + actualStatusCode);
Assert.assertEquals(200, actualStatusCode);
}
The output of the above program is
Verifying HTTP Response Status Line with Rest Assured
The getStatusLine() method returns a string and then we can verify its value.
@Test
public void verifyStatusLine() {
// GIVEN
Response response = given()
// WHEN
.when()
.get("https://reqres.in/api/users/2")
// THEN
.then()
.extract().response();
String actualStatusLine = response.getStatusLine();
System.out.println("Status Line : " + actualStatusLine);
Assert.assertEquals("HTTP/1.1 200 OK", actualStatusLine);
}
The output of the above program is
Verifying HTTP Response Body with Rest Assured
In the below example, we are obtaining the body content of the HTTP response using the getBody().