by admin | Aug 11, 2021 | Automation Testing, Blog, Latest Post |
Nowadays, data transfer from a client to a server or vice versa has become more concerning and significant. From the very beginning, using XML (Extensible Markup Language) has been one of the best ways for transferring data. Be it a configuration file or a mapping document, XML has made life easier for us by making quick data interchange possible by giving a clear structure to the data and helping the dynamic configuration & loading of variables. Then came JSON (JavaScript Object Notation), a competitive alternative and even possible replacement to XML. As a leading Test Automation Company, we make sure to always use the best tools in our projects. So in this blog, we will be listing the top 5 JSON Libraries every tester must know about and back it up with the need. But let’s take a look at a few basics before heading to the list.
What is JSON?
JSON is a data format that is both easy to read and write for us humans and easy to understand for the machines. It is mainly used to transmit data from a server to a web or mobile application. JSON is a much simpler and lightweight alternative to XML as it requires less coding and is smaller in size. This makes JSON faster when it comes to processing and transmitting data. Although it is written in JavaScript, JSON is language-independent.
Why is JSON so popular?
What makes JSON so popular is that it is text-based and has easy to parse data formatting that requires no additional code for parsing. Thus it helps in delivering faster data interchange and excellent web service results. The JSON library is open source and what makes it even better is that it is supported in all browsers. If we take a look at the other advantages of JSON, it has very precise syntax, the creation & manipulation of JSON are easy, and it uses the map data structure instead of XML’s tree data structure. We have added a sample syntax of JSON below:
{
“Id”: “101”,
“name: “Elvis”,
“Age”: 26,
“isAlive”: true,
“department”: “Computer Science”,
}
JSON Syntax Rules:
The syntax rules are very similar to the syntax rules of JavaScript, and they are as follows,
1. It should start and end with curly brackets.
2. Both keys and values must be indicated as strings.
3. Data are separated by commas.
Example:
4. Square brackets hold the arrays.
1. Jackson JSON Library
Jackson Library is an open-source library that is used by the Java community mostly because of its clean and compact JSON results that creates a very simple reading structure. In this library, dependencies are not required as it is independent. Mapping creation is also not required as it provides the default mapping for most of the objects which can be serialized. Though the system holds a large object or graph, it consumes a lesser amount of space to process and fetches the result.
Three steps to process the JSON by Jackson API
1. Streaming API
It enables us to read and write JSON content as discrete events. The implication here is that the JSON Parser reads the data and the JSON Generator writes the data. It can very easily be added to the maven repository by adding its dependency to the pom.xml file
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.1</version>
</dependency>
2. Tree Model
It converts the JSON content into a tree node, and the ObjectMapper helps in building a tree of JsonNode nodes. The tree model approach can be considered equivalent to the DOM parser that is used for XML. It is the most flexible approach as well. So similar to the Streaming API, the tree model can also be added to the maven repository by adding its dependency to the pom.xml file
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
3. Data Binding
Data binding lets us convert JSON to and from Plain Old Java Object (POJO) with the use of annotations. Here, the ObjectMapper reads and writes both types of data bindings (Simple Data Binding and Full Data Binding). We can add it to the maven repository by simply adding its dependency to the pom.xml file
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.3</version>
</dependency>
2. GSON Library
GSON is also an open-source library that was developed by Google. This library is special among the other JSON Libraries as it is capable of converting a JSON String into a Java Object and a Java Object into an equivalent JSON representation without calling the Java annotations in your classes.
Features of GSON
1. Open Source library
2. Cross-platform
3. Mapping is not necessary
4. Quite fast and holds low memory space
5. No Dependencies
6. Clean and compact JSON results.
Also, in GSON, we have the same three steps to process the JSON, and they are
1. Streaming API
2. Tree model
3. Data Binding
Adding it to the maven repository also has the same procedure as we have to just add it to its dependency in the pom.xml file
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
3. JSON-simple Library
It is a simple JSON library that is used for encoding and decoding the JSON text. It uses Map and List internally for JSON processing. We can use this JSON-simple to parse JSON data as well as write JSON to a file.
Features of JSON-simple
1. Lightweight API, which works quite well with simple JSON requirements.
2. No dependencies
3. Easy to use by reusing Map and List
4. High in performance
5. Heap-based parser
If you want to use a lightweight JSON library that both reads & writes JSON and also supports streams, you probably should choose this JSON-simple library.
The same process of adding its dependency to the pom.xml life can be carried out to add it to the maven repository.
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
4. Flexjson
It is also another JSON library that is used to serialize and deserialize Java objects into and from JSON. What’s special about Flexjson is its control over serialization that allows both deep and shallow copies of objects.
Normally, to send an object-oriented model or graph, other libraries create a lot of boilerplate to translate it into a JSON object. Flexjson tries to resolve this issue by providing a higher-level API like DSL.
If you know for a fact that you will be using a small amount of data in your application that will only need a small amount of space to store and read the object into JSON format, you should consider using Flexjson.
As usual, we can add it to the maven repository by adding its dependency to the pom.xml file.
<dependency>
<groupId>net.sf.flexjson</groupId>
<artifactId>flexjson</artifactId>
<version>2.0</version>
</dependency>
5. JSON-lib
JSON-lib is a java library for transforming beans, maps, collections, java arrays, and XML to JSON and back again to beans and DynaBeans. Beans are classes that encapsulate many objects into a single object (the bean), and DynaBeans, a Java object that supports properties whose names, data types, and values can be dynamically modified.
If you are about to use a large amount of data to store or read to/from JSON, then you should consider using JSON-lib or Jackson.
You can add the below dependency file to the pom.xml file to add it to the maven repository.
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
</dependency>
Conclusion:
We hope you are now clear which of these 5 JSON libraries would be apt for your use based on the points that we have discussed. As providing the best automation testing services is always a priority for us, we always explore all the viable options to streamline our process and enhance efficiency. With these libraries, you can parse the JSON String and generate Java objects or create a JSON String from your Java Objects. If you are having web services or any applications that result in a JSON response, then these libraries are very important for you.
Ultimately, if you want to handle large data with a good response speed, you can go with Jackson. But if all you need is a simple response, GSON is better, and if you are looking for any third-party dependencies, then you can go with JSON-simple or Flexjson.
by Anika Chakraborty | Jul 26, 2021 | Automation Testing, Blog, Latest Post |
Reducing the complexity of any process is always the key to better performance, similarly parsing the XML data to obtain a readable format of that XML file that we humans can understand is also a very important process. A simple equivalent to this parsing process would be the process of language translation. Let’s take the example of two national leaders discussing an important meeting. They could either choose to use a common language like English or talk in the languages they are comfortable with and use translators to solve the purpose. Likewise, the XML will be in a format that is easily understood by a computer, but once the information has been parsed, we will be able to read data from XML and understand it with ease.
As one of the leading QA companies in the market, we use different parsers based on our needs and so let’s explore which parser would be the perfect match for your need by understanding how they work. But before we explore how we can read data from XML, let us get introduced to XML first as there might be a few readers who may not know much about XML.
An Introduction to the XML:
XML stands for Extensible mark-up Language, and it’s primarily used to describe and organize information in ways that are easily understandable by both humans and computers. It is a subset of the Standard Generalized Mark-up Language (SGML) that is used to create structured documents. In XML, all blocks are considered as an “Element”. The tags are not pre-defined, and they are called “Self-descriptive” tags as it enables us to create our own customized tags. It also supports node-to-node interaction to fill the readability gap between Humans and Machines.
XML is designed to store and transfer data between different operating systems without us having to face any data loss. XML is not dependant on any platform or language. One can say that XML is similar to HTML as it neither acts as the frontend nor as the backend. For example, we would have used HTML to create the backend code, and that code would be passed to the frontend where it is rendered as a webpage.
Prerequisite:
There are a few basic prerequisites that should be ready in order to read data from XML, and we have listed them below,
1. Install any IDE(Eclipse/Intellij )
2. Make sure if Java is installed
3. Create a Java project in IDE
4. Create an XML file by using .xml extension
XML file creation:
So the first three steps are pretty straightforward, and you may not need any help to get it done. So let’s directly jump to the fourth and final prerequisite step, where we have to create an XML file manually in our Java project.
Navigate to the File tab in your IDE
– Create a new file
– Save it as “filename.xml”
The XML file will display under your Java project. In the same way, we can create the XML file in our local machine by using the .xml file extension. Later, we can use this XML file path in our program for parsing the XML. Let’s see the technologies for parsing the XML.
XML Parse:
XML parsing is nothing but the process of converting the XML data into a human-readable format. The XML parsing can be done by making use of different XML Parsers. But what do these parsers do? Well, parsers make use of the XSL Transformation (XSLT) processor to transform the XML data to a readable format and paves the way for using XML in our programs. The most commonly used parsers are DOM, SAX, StAX, Xpath, and JDOM. So let’s take a look at each parses one-by-one..
Using DOM Parser to Read data from XML:
DOM stands for Document Object Model. DOM is a parser that is both easy to learn and use. It acts as an interface to access and modify the node in XML. DOM works by building the entire XML file into memory and moving it node by node in a sequential order to parse the XML. DOM can be used to identify both the content and structure of the document. But the setback that comes with DOM is that it is slow and consumes a large amount of memory because of the way it works. So DOM will be an optimal choice if you are looking to parse a smaller file and not a very large XML file as everything in DOM is a node in the XML file. Let’s see how to parse the below XML by using the DOM parser.
Here is the XML File that we need to parse:
<?xml version = "1.0"?>
<Mail>
<email Subject="Codoid Client Meeting Remainder">
<from>Priya</from>
<empid>COD11</empid>
<Designation>Software Tester</Designation>
<to>Karthick</to>
<body>We have meeting at tomorrow 8 AM. Please be available
</body>
</email>
<email Subject="Reg:Codoid Client Meeting Remainder ">
<from>Kartick</from>
<empid>COD123</empid>
<Designation>Juniour Software Tester</Designation>
<to>Priya</to>
<body>Thanks for reminding me about the meeting. Will join on time</body>
</email>
</Mail>
DOM Parser:
package com.company;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;
public class DOMParser {
public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
try {
File file = new File("E:\\Examp\\src\\com\\company\\xmldata.xml");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
Document doc = builder.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element:: " + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("email");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("Email Subject : "
+ eElement.getAttribute("Subject"));
System.out.println("From Name : "
+ eElement
.getElementsByTagName("from")
.item(0)
.getTextContent());
System.out.println("Designation : "
+ eElement
.getElementsByTagName("Designation")
.item(0)
.getTextContent());
System.out.println("Employee Id : "
+ eElement
.getElementsByTagName("empid")
.item(0)
.getTextContent());
System.out.println("To Name : "
+ eElement
.getElementsByTagName("to")
.item(0)
.getTextContent());
System.out.println("Email Body : "
+ eElement
.getElementsByTagName("body")
.item(0)
.getTextContent());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
We have created a DocumentBuilderFactory API to produce the object trees from XML, after which we’ve also created a document interface to access the XML document data. As stated earlier, the node is the base datatype for DOM here. From the code, we can see that the getDocumentElement() method will return the root of the element, and the getElementsByTagName() method will return the value of that particular tag.
Using the SAX Parser to Read data from XML:
The SAX parser is a simple event-based API that parses the XML document line-by-line using the Handler class. Everything in XML is considered to be “Tokens” in SAX. Unlike the DOM parser that we saw earlier, SAX does not load the entire XML file into memory. It also doesn’t create any object representation of the XML document. Instead, it triggers events when it encounters the opening tag, closing tag, and character data in an XML file. It reads the XML from top to bottom and identifies the tokens and call-back methods in the handler that are invoked. Due to the top to bottom approach, tokens are parsed in the same order as they appear in the document. Due to the change in the way SAX works, it is faster and uses less memory in comparison to the DOM parser.
SAX Parser:
try{
File file = new File("E:\\Examp\\src\\com\\company\\xmldata.xml");
SAXParserFactory saxParserFactory= SAXParserFactory.newInstance();
SAXParser saxParser= saxParserFactory.newSAXParser();
SaxHandler sax= new SaxHandler();
saxParser.parse(file,sax);
}
catch (Exception e){
e.printStackTrace();
}
}
}
In the above code, we have created an XML file and given its path in the code. The SAXParserFactory used in the code creates the new instance for that file. After that, we can create the object for the Handler class using which we parse the XML data. So we have called the handler class method by using the object. Now, let’s see how the Handler class and its method are created.
class SaxHandler extends DefaultHandler{
boolean from=false;
boolean to=false;
boolean Designation= false;
boolean empid= false;
boolean body=false;
StringBuilder data=null;
@Override
public void startElement(String uri, String localName,
String qName, Attributes attributes){
if(qName.equalsIgnoreCase("email")){
String Subject= attributes.getValue("Subject");
System.out.println("Subject:: "+Subject);
}
else if(qName.equalsIgnoreCase("from")){
from=true;
}
else if(qName.equalsIgnoreCase("Designation")){
Designation=true;
}
else if(qName.equalsIgnoreCase("empid")){
empid=true;
}
else if(qName.equalsIgnoreCase("to")){
to=true;
}
else if(qName.equalsIgnoreCase("body")) {
body = true;
}
data=new StringBuilder();
}
@Override
public void endElement(String uri, String localName, String qName){
if(qName.equalsIgnoreCase("email")){
System.out.println("End Element:: "+qName);
}
}
@Override
public void characters(char ch[], int start, int length){
// data.append(new String(ch,start,length));
if(from){
System.out.println("FromName:: "+new String(ch,start,length));
from=false;
}
else if(Designation){
System.out.println("Designation:: "+new String(ch,start,length));
Designation=false;
}
else if(empid){
System.out.println("empid:: "+new String(ch,start,length));
empid=false;
}
else if(to){
System.out.println("to:: "+new String(ch,start,length));
to=false;
}
else if(body){
System.out.println("body:: "+new String(ch,start,length));
body=false;
}
}
}
Our ultimate goal is to read data from XML using the SAX parser. So in the above example, we have created our own SAX Parser class and also extended the DefaultHandler class which has various parsing methods. The 3 most prevalent methods of the DefaultHandler class are:
1. startElement() – It receives the notification of the start of an element. It has 3 parameters which we have explained by providing the data that has to be used.
startElement(String uri, String localName,String qName, Attributes attributes)
uri – The Namespace URI, or the empty string if the element has no Namespace URI.
localName – The local name (without prefix) or the empty string if Namespace processing is not being performed.
qName – The qualified name (with prefix) or the empty string if qualified names are not available.
attributes – The attributes attached to the element. If there are no attributes, it shall be an empty attributes object.
The startElement() is used to identify the first element of the XML as it creates an object every time a start element is found in the XML file.
2. endElement() – So we have already seen about startElement(), and just as the name suggests, endElement() receives the notification of the end of an element.
endElement (String uri, String localName, String qName)
uri – The Namespace URI, or the empty string if the element has no Namespace URI
localName – The local name (without prefix) or the empty string if Namespace processing is not being performed.
qName – The qualified name (with prefix) or the empty string if qualified names are not available.
The endElement() is used to check the end element of the XML file.
3.characters() – Receives the notification of character data inside an element.
characters (char ch[], int start, int length)
ch – The characters.
start – The start position in the character array.
length – The number of characters that have to be used from the character array.
characters() is used to identify the character data inside an element. It divides the data into multiple character chunks. Whenever a character is found in an XML document, the char() will be executed. That’s why we append() the string to keep this data.
Using the JDOM Parser to Read data from XML:
So the JDOM parser is a combination of the DOM and SAX parsers that we have already seen. It’s an open-source Java-based library API. The JDOM parser can be as fast as the SAX, and it also doesn’t require much memory to parse the XML file. In JDOM, we even can switch the two parsers easily like DOM to SAX, or vice versa. So the main advantage is that it returns the tree structure of all elements in XML without impacting the memory of the application.
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JDOMParser {
public static void main(String[] args) throws JDOMException, IOException {
try{
File file = new File("E:\\Examp\\src\\com\\company\\xmldata.xml");
SAXBuilder saxBuilder = new SAXBuilder();
Document doc= saxBuilder.build(file);
System.out.println("Root element :" + doc.getRootElement().getName());
Element ele= doc.getRootElement();
List<Element> elementList = ele.getChildren("email");
for(Element emailelement: elementList){
System.out.println("Current element:: "+emailelement.getName());
Attribute attribute= emailelement.getAttribute("Subject");
System.out.println("Subject:: "+attribute.getValue());
System.out.println("From:: "+emailelement.getChild("from").getText());
System.out.println("Designation:: "+emailelement.getChild("Designation").getText());
System.out.println("Empid:: "+emailelement.getChild("empid").getText());
System.out.println("To:: "+emailelement.getChild("to").getText());
System.out.println("Body:: "+emailelement.getChild("body").getText());
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
We have used the SAXBuilder class to transform the XML to a JDOM document. The getRootElement() is used to find the starting element of the XML and store all the elements from the XML to a list based on the starting element and iterate that element list. At the very end, we have used the getText() method to get the value of each attribute.
Using the StAX Parser to Read data from XML:
The StAX Parser is similar to the SAX Parser with just one difference. That major difference is that it employs 2 APIs (Cursor based API and Iterator-based API) to parse the XML. The StAX parser is also known as the PULL API, and it gets the name from the fact that we can use it to access the information from the XML whenever needed. The other standout aspect of the StAX parser is that it can read and also write the XML. Every element in the XML is considered as “Events”, and below is the code that we require for parsing the XML file using the StAX Parser.
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLEventReader eventReader =
factory.createXMLEventReader(new FileReader("E:\\Examp\\src\\com\\company\\xmldata.xml "));
while(eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
switch(event.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
StartElement startElement = event.asStartElement();
String qName = startElement.getName().getLocalPart();
if (qName.equalsIgnoreCase("email")) {
System.out.println("Start Element : email");
Iterator<Attribute> attributes = startElement.getAttributes();
String rollNo = attributes.next().getValue();
System.out.println("Subject " + Subject);
} else if (qName.equalsIgnoreCase("from")) {
EmailFrom = true;
} else if (qName.equalsIgnoreCase("empid")) {
Empid = true;
} else if (qName.equalsIgnoreCase("Designation")) {
Desination = true;
}
else if (qName.equalsIgnoreCase("to")) {
EmailTo = true;
}
else if (qName.equalsIgnoreCase("body")) {
EmailBody = true;
}
break;
case XMLStreamConstants.CHARACTERS:
Characters characters = event.asCharacters();
if(EmailFrom) {
System.out.println("From: " + characters.getData());
EmailFrom = false;
}
if(Empid) {
System.out.println("EmpId: " + characters.getData());
Empid = false;
}
if(Desination) {
System.out.println("Designation: " + characters.getData());
Desination = false;
}
if(EmailTo) {
System.out.println("to: " + characters.getData());
EmailTo = false;
}
if(EmailBody) {
System.out.println("EmailBody: " + characters.getData());
EmailBody = false;
}
break;
case XMLStreamConstants.END_ELEMENT:
EndElement endElement = event.asEndElement();
if(endElement.getName().getLocalPart().equalsIgnoreCase("email")) {
System.out.println("End Element : email");
System.out.println();
}
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}}
In StAX, we have used the XMLEventReader interface that provides the peek at the next event and also returns the configuration information.
The StartElement interface give access to the start elements in XML and the asStartElement() method returns the startElement event. It is important to note that the exception will be shown if the start element event doesn’t occur.
All character events are reported using the Characters interface. If you are wondering what would get reported as character events? The answer is that all the text and whitespaces events are reported as characters events.
The asCharacters() method returns the Characters from XML, and we will be able to get the data from XML as characters using the getData() method. Though it iterates each and every data from the XML and gives it in the form of a tree structure, it doesn’t return the start and end element events.
The EndElement class is used to point and return the end of the elements in an XML doc.
Using the Xpath Parser to Read data from XML:
The Xpath parser is a query language that is used to find the node from an XML file and parse the XML based on the query string. Now let’s take a look at an example code for better understanding.
File inputFile = new File("E:\\Examp\\src\\com\\company\\xmldata.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
// DocumentBuilder dBuilder;
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
String expression = "/Mail/Email";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
Node nNode = nodeList.item(i);
System.out.println("\nCurrent Element :" + nNode.getNodeName());
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("From : " + eElement.getElementsByTagName("from").item(0).getTextContent());
System.out.println("EmpId : " + eElement.getElementsByTagName("empid").item(0).getTextContent());
System.out.println("Designation : " + eElement.getElementsByTagName("Designation").item(0).getTextContent());
System.out.println("TO : " + eElement.getElementsByTagName("to").item(0).getTextContent());
System.out.println("Body : " + eElement.getElementsByTagName("body").item(0).getTextContent());
}
In the above code, we used the XPath Factory for creating a new instance for the XPath. Then we have taken the XPath for the XML data and stored it as a String datatype. This String expression is called as “XPath Expression”.
Next, we have compiled the list of the XPath Expression by using the xPath.compile() method and iterated the list of nodes from the compiled expression using the evaluate() method.
We have used the getNodeName() method to get the starting element of the XML.
So once the XML document has been read, we would reuse the document and the XPath object in all the methods.
Conclusion
We hope you have found the parser that fits your requirement and in-process also enjoyed reading this article. So to sum things up, we have seen how each parser works to understand the pros and cons of each type. Choosing the apt parser might seem like a very small aspect when compared to the entire scale of the project. But as one of the best software testing service providers, we believe in attaining maximum efficiency in each process, be it small or big.
by admin | Jul 19, 2021 | Automation Testing, Blog, Latest Post |
If you are going to test an application using Selenium WebDriver, you most definitely will face scenarios where you will be needed to trigger keyboard and mouse interactions. This is where our Action Class Guide comes into the picture. Basically, Action Class is a built-in feature provided by Selenium for simulating various events and acts of a keyboard and mouse. With the help of Action classes, you will be able to trigger mouse events like Double Click, Right Click, and many more events. The same goes for keyboards as well, you can trigger the functions of CTRL key, CTRL + different keys, and other such combinations. As one of the best QA companies, we have been able to use Action Class to its zenith by using it in various combinations as per the project needs. But before exploring such Action class implementations, let’s take a look at some basics.
Action Class Guide for MouseActions
So we wanted to start our Action Class Guide by listing some of the most frequently used mouse events available in the Action class.
click() – Clicks on the particular WebElement (Normal Left Click)
contextClick() – Right clicks on the particular WebElement
doubleClick() – Performs a double click on the WebElement
dragAndDrop (WebElement source, WebElement target) – Clicks and holds the web element to drag it to the targeted web element where it is released.
dragAndDropBy(WebElement source, int xOffset, int yOffset) – Clicks and Drag the element to the given location using offset values
moveToElement(WebElement) – Moves the mouse to the web element and holds it on the location (In simple words, the mouse hovers over an element)
moveByOffset(int xOffSet, int yOffSet) – Moves the mouse from the current position to the given left (xOffset value) and down (yOffset Value).
clickAndHold(WebElement element) – Clicks and holds an element without release.
release() – Releases a held mouse click.
Action Class Guide Keyboard Actions
Same as above, we have listed some frequently used keyboard events available in the Action class,
keyDown(WebElement, java.lang.CharSequence key) – To press the key without releasing it on the WebElement
keyUp(WebElement, java.lang.CharSequence key) – To release the key stroke on the webElement
sendkeys(value) – To enter values on WebElements like textboxes
So by including these methods, you can smoothly run your script and execute the code without any issues….
Absolutely not, we’re just kidding. We still have to gather all the action methods and execute them under the Action class.
build() – It is a method where all the actions are chained together for the action which is going to be performed.
So the above method can be used to make the actions that are to be executed ready.
perform() – It is a method used to compile and also execute the action class.
A perform method can be called alone without a build method to execute the action class methods if only one action is performed.
Action Class Guide for Performing actions
Now that we have gone through the basics, let’s find out how to implement the Action Classes in Code.
Step1:
Import the Interaction package that contains the Action Class. You can use the below line for importing,
“importorg.openqa.selenium.interactions.Actions; ”
Step2:
Create the object of the Action Class and use the Web Driver reference as the argument
Actions action = new Actions (driver)
Step3:
Once the above two steps have been completed, you can start writing your script using the Action classes and the different methods available.
Let’s proceed further and take a look at the implementation and uses of the actions available for both the mouse & keyboard.
1. SendKeys(WebElement element, value)
As stated above, this action class is mainly used to send a char sequence into the textbox. But it is also worth noting that we can use it to send the keystrokes of different key combinations likeCTRL+T, Enter, and so on.
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import java.util.concurrent.TimeUnit;
public class SendKeys {
public static void main(String[] args) {
WebDriver driver; System.setProperty("webdriver.chrome.driver","D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.flipkart.com/");
driver.manage().window().maximize();
Actions action = new Actions(driver);
WebElement eleSearchBox = driver.findElement(By.cssSelector("input[placeholder='Search for products, brands and more']"));
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
action.sendKeys(eleSearchBox, "Iphone").build().perform();
action.sendKeys(Keys.ENTER).build().perform();
driver.close();
}
}
By using the SendKeys method, an element is searched by the keystroke instead of clicking on the Search Button. (i.e.) We can clearly see in the code that the “Keys.Enter” is inside the Keys class that has various keystrokes available for the keys.
2. MoveToElement(WebElement element)
You might be in a position to test if an element changes color, shows some additional information, or performs the intended action when the mouse hovers over it. So let’s take a look at the code and find out how you can make it happen.
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.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import java.util.concurrent.TimeUnit;
public class MouseHover {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.leafground.com/");
driver.manage().window().maximize();
Actions action = new Actions(driver);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,170)", "");
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//img[@alt='mouseover']"))).click();
WebElement eleTabCourses = driver.findElement(By.xpath("//a[normalize-space()='TestLeaf Courses']"));
action.moveToElement(eleTabCourses).build().perform();
driver.close();
}
}
We have written the above code in a way that the code first waits for the image to become clickable. Once it loads, the image gets clicked, and the mouse hovers over the element for a second.
3. DragAndDrop(source, target)
So there are basically two types of drag and drop that we will be seeing in this Action Class Guide. This is the type of action class using which we can assign a target area where the element can be dragged and dropped. Now let’s see the code to execute the DragAndDrop action,
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.interactions.Actions;
import java.util.concurrent.TimeUnit;
public class DragAndDrop {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.leafground.com/");
driver.manage().window().maximize();
Actions action = new Actions(driver);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.findElement(By.xpath("//h5[normalize-space()='Droppable']")).click();
WebElement eleSource = driver.findElement(By.xpath("//div[@id='draggable']"));
WebElement eleTarget = driver.findElement(By.xpath("//div[@id='droppable']"));
action.dragAndDrop(eleSource,eleTarget).build().perform(););
driver.close();
}
}
For dragging an element to the dropped place, first, the locators are captured for the source and target. Following this, they are passed inside the action method using dragAndDrop.
4. DragAndDropBy(WebElement source,int xOffset, int yOffSet )
So we have already seen how to drag a drop an element within a targeted area, but what if we would like to drag and drop an element by a defined value? Let’s take a look at the code and find out how.
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.interactions.Actions;
import java.util.concurrent.TimeUnit;
public class DragAndDropOffset {
public static void main(String[] args) throws InterruptedException {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.leafground.com/");
driver.manage().window().maximize();
Actions action = new Actions(driver);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
driver.findElement(By.xpath("//img[@alt='Draggable']")).click();
WebElement eleDrag= driver.findElement(By.xpath("//div[@id='draggable']"));
action.dragAndDropBy(eleDrag,200,130).build().perform();
Thread.sleep(2000);
driver.close();
}
}
In the above code, we have used the DragAndDropBy method in a way that it clicks and moves the element to the offset position as specified and releases it once the target location is reached.
5. Click(WebElement element)
There is no way to test anything without being able to use the left click button. So let’s find out the code to execute this very basic and necessary functionality.
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.interactions.Actions;
public class LeftClick {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.com/");
driver.manage().window().maximize();
Actions actions = new Actions(driver);
WebElement eleInput = driver.findElement(By.name("q"));
actions.sendKeys(eleInput, "www.codoid.com").build().perform();
WebElement BtnSearch = driver.findElement(By.xpath("//div[@class='FPdoLc lJ9FBc']//input[@name='btnK']"));
actions.click(BtnSearch).build().perform();
driver.close();
}
}
6. ContextClick(WebElement element)
Though the right-click is not used as commonly as the left click, it is still a very basic functionality every tester must know. So let’s take a look at the code to find out how to implement it.
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.interactions.Actions;
import java.util.concurrent.TimeUnit;
public class RightClick {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://demo.guru99.com/test/simple_context_menu.html");
driver.manage().window().maximize();
Actions action = new Actions(driver);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement eleRightClick = driver.findElement(By.xpath("//span[@class='context-menu-one btn btn-neutral']"));
action.contextClick(eleRightClick).perform();
driver.close();
}
}
It is worth mentioning here that we have not used ‘build’ anywhere in the above code. Instead, we have used ‘perform’ to execute the functionality.
7. DoubleClick(WebElement element)
Just like the previous functionalities we have seen in the Action Class Guide, double-click is another basic functionality that is vital to any form of testing. So let’s jump straight to the code.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
import java.util.concurrent.TimeUnit;
public class DoubleClick {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://demo.guru99.com/test/simple_context_menu.html");
driver.manage().window().maximize();
Actions action = new Actions(driver);
driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
WebElement eleDoubleClick = driver.findElement(By.xpath("//button[normalize-space()='Double-Click Me To See Alert']"));
action.doubleClick(eleDoubleClick).perform();
driver.quit();
}
8. KeyDown(WebElement element, Modifier Key) & KeyUp (WebElement element, Modifier Key)
CTRL, SHIFT, and ALT are few examples of modifier keys that we all use on a day-to-day basis. For example, we hold down Shift if we want to type something in caps. So when we use the KeyDown action class, it holds a particular key down until we release it using the KeyUp action class. With that said, let’s see an example code in which we have used these functionalities,
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
public class KeyDownAndKeyUp {
public static void main(String[] args) {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.com/");
driver.manage().window().maximize();
Actions actions = new Actions(driver);
WebElement eleInput = driver.findElement(By.name("q"));
actions.click(eleInput).build().perform();
actions.keyDown(eleInput, Keys.SHIFT);
actions.sendKeys("eiffel tower");
actions.keyUp(eleInput,Keys.SHIFT);
actions.sendKeys(Keys.ENTER);
actions.build().perform();
driver.close();
}
}
So if you have taken a look at the code, it is evident that once we have used the KeyDown method, the Shift key was pressed down. So the text ‘eiffel tower’ that was fed in the next line would have gotten capitalized. Now that the KeyDown has solved its purpose in this scenario, we have used to KeyUp method to release it.
9. MoveByOffset(int xOffSet, int yOffSet)
As seen above, ByOffset(int x, int y) is used when we need to click on any particular location. We can do this by assigning locations for the x and y axes. Now let’s explore the code that we have used for execution.
import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;
public class MoveByOffSet {
public static void main(String[] args) throws InterruptedException {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.com/");
driver.manage().window().maximize();
Actions actions = new Actions(driver);
WebElement eleInput = driver.findElement(By.name("q"));
actions.sendKeys(eleInput, "Eiffel").build().perform();
actions.sendKeys(Keys.ENTER).build().perform();
Thread.sleep(2000);
actions.moveByOffset(650, 300).contextClick().build().perform();
driver.close();
}
}
10. ClickAndHold(WebElement element)
The action method that we will be seeing now in our Action Class Guide can be used when an element has to be clicked and held for a certain period of time.
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.interactions.Actions;
public class ClickAndHold {
public static void main(String[] args) throws InterruptedException {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.google.com/");
driver.manage().window().maximize();
Actions actions = new Actions(driver);
WebElement eleInput = driver.findElement(By.name("q"));
actions.sendKeys(eleInput, "Flower").build().perform();
actions.moveByOffset(500,300).click().build().perform();
Thread.sleep(2000);
WebElement BtnSearch = driver.findElement(By.xpath("//div[@class='FPdoLc lJ9FBc']//input[@name='btnK']"));
actions.clickAndHold(BtnSearch).build().perform();
driver.close();
}
}
In the above code, we have first opened Google and then searched using ‘Flower’ as the input and then performed a left-click action at the defined location. After which, we have performed a click and hold action on the search button.
Note:
In addition to that, if we need the click to be released, we can use the release method to release the clicked element before using ‘build’.
actions.clickAndHold(BtnSearch).release().build().perform();
Uploading a File Using SendKeys Method:
We know that the SendKeys action method can be used to send a character sequence. But one interesting way to use it would be to upload a normal document. If you’re wondering how that is possible, let’s take a look at the code,
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
public class FileUpload {
public static void main(String[] args) throws InterruptedException {
WebDriver driver;
System.setProperty("webdriver.chrome.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\chromedriver.exe");
driver = new ChromeDriver();
driver.get("http://www.leafground.com/");
driver.manage().window().maximize();
driver.findElement(By.xpath(" //img[@alt='contextClick']")).click();
WebElement eleSendFile = driver.findElement(By.cssSelector("input[name='filename']"));
eleSendFile.sendKeys("C:\\Users\\OneDrive\\Desktop\\Sample.txt");
Thread.sleep(2000);
driver.close();
}
}
In the above code, we have used the SendKeys action method to enter the file’s address path to locate the object that has to be uploaded. The document which we have used here is an input type document as this type of document is only ideal for sending the document using SendKeys.
Note:
Just in case you are not using Google Chrome and would like to execute these action class methods in Mozilla Firefox, all you have to do is just add the driver and set the system property for the gecko driver and initialize the driver object for it using the below line.
System.setProperty("webdriver.gecko.driver", "D:\\ActionClass\\src\\test\\java\\Drivers\\geckodriver.exe");
driver = new FirefoxDriver();
Conclusion:
We hope you have enjoyed reading our introductory action class guide that has covered the basic action class methods starting from a basic ‘Click’ to uploading a file using ‘SendKeys’. Action class helps one to perform all the basic actions on a webapp.Release() method, which can be used to release any element that was clicked or held. ‘Perform’ can be used alone, but if there are more composite actions, build and perform should be used together. As a leading test automation company, we are well aware of how resourceful action classes can be when used effectively. Once you have understood the basics, you would be able to perform so many more actions by using combinations of the action methods established in this blog.
by admin | Jun 21, 2021 | Automation Testing, Blog |
One of the big trends that rose in popularity in 2020 is test automation and it’s still one of the hottest trends today. This has been the answer that made many believe in the potential of CI/CD and quick QA processes. But even with its perks, many teams are still struggling to achieve its benefits because of the issues they encounter when implementing and working with test automation.
The biggest misconception of test automation is that you’re pretty much set once you have onboard this process. Truthfully, the reality is far from that. Thorough and careful planning is needed, that’s why partnering up with a reliable automation testing company can do loads to help you reach your ideal business workflow.
With that being said, it’s best to solve these problems while the iron is still hot. In this article, we’ll give you a rundown of the most common automation problems even the most seasoned QA teams still experience, so you won’t have to go through it yourself. Let’s take a look!
Problem #1: Having Unrealistic Expectations for Automated Testing
Test automation really transforms how a business operates — it saves so much time, effort, resources, and money. But with that being said, many QA teams think that once test automation is integrated into the system, things will improve rather quickly and efficiently. The truth is — not quite.
QA teams have unrealistic expectations about automation testing, making them mess up the whole testing process. The truth is, manual testing still matters in some areas for research, and having a clear testing strategy is still vital.
Problem #2: Introducing the Wrong Tools
QA teams’ mistake that causes problems in their automation processes is that they aren’t using the right tools. Without the right tools, test automation won’t work effectively, and with the plethora of software and tools in the market, it’s quite easy to feel overwhelmed.
The best way to deal with this is by working with an automation testing company that could help you choose the best tools that would help you reach your goals. Together, you can set requirements, such as your budget and what kind of support your team needs, then look for a tool that fits just that.
Problem #3: Choosing Wrong Tests to Automate
When you integrate test automation in your business operations, it could be the shiny new toy your QA team may have, preventing you from choosing the right tests to focus on. With that, you risk missing out on important scenarios and gaps in software quality.
With that being said, choose tests that are worth automating. As you integrate test automation in your workflow, assess which cases need this type of approach and be more beneficial for the team. Besides that, it helps look for potential weak spots in your system to avoid any mishaps during the testing.
Problem #4: Lack of Training for Testing
Among all the QA team problems, this is by far the trickiest. Without proper training, all your strategies and automation testing efforts may go to waste. With poor training, your team won’t develop an effective and consistent system that could help create a powerful testing approach.
So before implementing automation, it’s best to train your team correctly and work with an automation testing provider, like Codoid, who could help your team throughout this significant change. With clarity, your team will develop enough technical skills to support your automated tests.
The Bottom Line: You Need to Do the Work to Make Test Automation Do Its Job
Many business leaders reap the benefits of test automation, but we can all agree that reaching this isn’t a walk in the park. The unrealistic expectations that people have over the whole process cause teams to underestimate the importance of a solid strategy, creating gaps in product quality.
With that being said, it’s best to work with automation testing companies, so you know exactly what you’re dealing with and how to maximize the potential of this incredible tool.
Work With Codoid
Seeing as test automation can be quite challenging to deal with, it’s best to work with industry leaders in QA, such as Codoid.
Here at Codoid, we are passionate about guiding and leading the Quality Assurance community in creating better strategies that would help develop and expand their companies. We offer various testing services, such as automation, mobile, performance, gaming, analytics testing, and more.
We also speak at software testing groups, software quality assurance events, and automation testing conferences. If you’re looking for automation testing companies that would help develop your QA team, speak to us today — we’re happy to help!
by admin | Jun 21, 2021 | Automation Testing, Blog, Latest Post |
TestNG is not the only option available in the market. But most of the automation testers prefer TestNG over other options like JUnit because TestNG allows parallel execution of test cases that saves loads of time possible with the help of the ‘parallel’ keyword in the XML file, TestNG’s seamless integration with tools like Jenkins, Maven, etc., and grouping of test cases also becomes easy with the use TestNG. These features have been instrumental in us providing the best software testing services to our clients. So in this TestNG tutorial, we will be focusing on how to make use of all these advantages and also explore all the advantages that TestNG brings to the table.
TestNG is an open-source testing framework where NG stands for Next Generation. It provides many features to execute the test methods by using various annotations like @Test @BeforeTest, @BeforeClass, etc. TestNG allows its users to generate robust test results that include the number of test cases that have Run, Passed, Failed, and Skipped. It can also be used to implement the logging feature using TestNG Listeners. On the whole, TestNG can also be used across various testing types like Unit, Regression, Functional, and API Testing. But before we get started with the TestNG Tutorial, let’s see how to set it up.
Installation and Setup of TestNG in IntelliJ:
IntelliJ requires a JAR file to add dependencies for TestNG script development and for running the test suites. So if it is a Maven Project, we would have to download the TestNG Jar File. Since we will be running tests on Java, we need to download an external TestNG Jar File onto our system by using the provided link.
Direct download link: TestNG/7.4.0/testng-7.4.0.jar
Reference: org.testng/TestNG
Please refer to the below image and instructions for a step-by-step guide,
i. Open IntelliJ,
ii. Create a new JAVA Project,
iii. Navigate to ‘File’ >> ‘Project Structure’ in IntelliJ,
iv. Click on ‘Libraries’ from Project Setting,
v. Add it to your ‘TestNG’ jar file, and then click on the ‘Apply and OK’ button.
If we want to work on a maven project, we have to mention the dependency in the POM.xml file
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
TestNG Annotations:
TestNG annotations that are used to execute the test scripts can be defined by ‘@Test’ annotations. Before we head over to other aspects of the TestNG Tutorial, let’s take a look at the various annotations that are available in TestNG along with a short description of them.
Types of TestNG Annotations:
@Test Annotations:
We use this annotation to mark a method as a test method. The methods marked with @Test annotation are automatically invoked by the TestNG engine in default order (i.e.) alphabetically.
Syntax:
@Test
public void TestMethod1() {
System.out.println("\n Test-Method-001");
}
So in this part of the TestNG Tutorial, we will be focusing on the most important attributes of @Test annotations, starting with the description
1. ‘Description’ attribute of @Test Annotation:
The ‘Description’ keyword is used to provide a description of the test case. It can also be termed as a one-line summary, and it has been illustrated in the below example that describes the action of the user in a single line.
@Test(description = "User visits Codoid Home page")
public void launchCodoidURL(){
System.out.println("\n >>> User visits Codoid Home page...");
}
2. Test Methods with Priority:
As mentioned earlier, we are aware that the methods will execute multiple test annotations alphabetically by default. But what if there is a need to run the methods or the test annotations based on defined priorities? Here is where the ‘Priority’ attribute comes into play, as it can be used to assign priorities to each test method. The highest priority would be given when a test method is marked with 1 and the priority decreases inversely as the number increases.
We have mentioned syntax below to denote how the priority attribute would function.
Syntax:
@Test(priority = 1)
public void Test1() {
System.out.println("\n Test-1");
}
@Test(priority = 2)
public void Test2() {
System.out.println("\n Test-2");
}
3. Test Methods with Priority & without priority:
So in the above-mentioned syntax code, we saw 2 sets of programs that had defined priorities. But what if there is a need to define priorities only for a certain number of methods? It is very easy to accomplish as you can simply leave the methods that don’t need defined priorities and mark the other methods alone in the order that you wish. It is worth noting that the methods that had no defined priority will be run first on an alphabetical basis and then followed by the defined order.
Syntax:
@Test(priority = 1) //with Priority
public void Test1() {
System.out.println("\n Test-1");
}
@Test //without priority
public void TestMethod1() {
System.out.println("\n Test-Method-001");
}
@Test //without priority
public void TestMethod2() {
System.out.println("\n Test-Method-001");
}
@Test(priority = 2) //with Priority
public void Test2() {
System.out.println("\n Test-2");
}
Code Explanation:
– Non-Prioritized methods ‘TestMethod1() and TestMethod2()’ have been executed in alphabetical order. (Line No: 60 and 65)
– Prioritized methods ‘Test1() and Test2()’ have been executed based on the priority level. (Line No: 55 and 69)
4. Depends On Methods in TestNG:
In our test scripts, we might have some methods that depend on the execution of another method before it is executed. For example, if a user wishes to send an email using the email application, then the user has to be logged in to the application first. So there will be no point in trying to send the mail if the sign-in is incomplete. So we can make use of this attribute that will help methods from getting executed if their dependent method doesn’t get a ‘Pass’. The same scenario is shown below as an example.
Syntax:
@Test
public void UserLoginIntoEmailApplication(){
System.out.println("\n >> User Login :: ");
}
@Test(dependsOnMethods = "UserLoginIntoEmailApplication")
public void UserSendAnNewEmail(){
System.out.println(">> User send an eMail");
}
Sometimes, there might be scenarios where a test case depends on more than one test method. So we can pass the parameters in annotations as shown below.
Syntax for dependsOnMethods: (Multiple Dependent Test methods)
@Test(dependsOnMethods = { "UserLoginIntoEmailApplication", "UserSendAnNewEmail" })
public void SignOut() {
System.out.println(">>> Sign Out");
}
5. TestNG Groups:
The grouping concept is one of the best features of TestNG and one of the important parts of this TestNG Tutorial. So using this concept we can create a group of test methods based on modules/test cases. For example, the client requirement might demand you to execute a large number of smoke or regression tests. So you can simply pass the parameter in group attributes as shown below.
Syntax:
@Test(groups = { "Regression" })
public void userLogin() {
....
}
@Test(groups = { "Regression" })
public void userSendEmail() {
....
}
So the groups are specified in the ‘.xml’ file and can either be used with the “groups” tag name or under the ‘test’ tag.
Syntax:
<groups>
<run>
<include name = "Regression"></include>
</run>
</groups>
DataProvider in TestNG:
In this method, a user will be able to pass the test data in test methods and also iterate the test methods using different data from the @DataProvider annotation, and it will return the 2D array objects.
Let’s see a simple example for this annotation,
Code:
@DataProvider(name = "data-provider")
public Object[][] dataProviderMethod() {
return new Object[][]{{"Codoid-001"}, {"Codoid-002"}};
}
@Test(dataProvider = "data-provider")
public void testDataProviderConcept(String strData) {
System.out.println("\n >> Data: " + strData);
}
Code Explanation:
We have maintained the array object and Test methods in the same class. In this method, the “testDataProviderConcept(String strData)” will iterate based on the array size. It will also retrieve the values “Codoid-001 and Codoid-002” from the ‘dataProviderMethod()’ with the help of the @DataProvider annotation.
Multiple Parameters in TestNG DataProvider:
It is even possible to pass multiple data through a single parameter. In this test method, we will be able to retrieve the data using multiple arguments as shown in the example,
For example,
@DataProvider(name = "data-provider")
public Object[][] dataProviderMethod(){
return new Object[][] {{123,456 ,789}, {001, 002, 003}};
}
@Test(dataProvider = "data-provider")
public void testMethod(int value1, int value2, int value3) {
System.out.println("\n >> value1: "+value1+"; Value2: "+value2+"; Value3: "+value3);
}
DataProvider In TestNG Using Inheritance concept:
If you are looking for a way to maintain the code based on the project structure, then the DataProvider methods can maintain one class and the test methods can maintain another class. Let’s take a look at the example to find out how.
For example, we can access the dataprovider class using another attribute like “dataProviderClass”
Syntax :
@Test(dataProvider = “data-provider”, dataProviderClass = DP.class)
Note:
i. dataProviderClass // attribute Name
ii. DP.class // class Name; To inherit the other class.
Code:
//Class-1
@Test(dataProvider = "data-provider", dataProviderClass = DataProviderUtil.class)
public void testDataProviderConcept(String strData) {
System.out.println("\n >> Data: " + strData);
}
//Class-2 "Class Name: DataProviderUtil"
@DataProvider(name = "data-provider")
public Object[][] dataProviderMethod() {
return new Object[][]{{"Codoid-001"}, {"Codoid-002"}};
TestNG Tutorial for using Excel Workbook as a Data Provider:
Now that we have seen how to pass the parameter with single or multiple data through an array object, but what if there is a need that demands a large number of data be used? Adding everything to the code will not be an optimal choice at all. We have a solution to overcome this in our TestNG Tutorial and so let’s focus on how we can retrieve data from an Excel workbook. Knowing this will come in very handy while executing Functional tests, and when there is a need to create a large amount of test data for performing Load tests.
We are going to implement the Excel workbook in the TestNG-DataProvider annotation to fetch the data from the excel sheet and search the products in Amazon. In the example, we have listed a few mobile phones like iPhone 12, Pixel 4a, and so on in the excel sheet.
The below-mentioned Excel util class is used to retrieve the data from the Excel sheet.
ExcelUtil.JAVA
Code:
/*Description: We can retrieve the data from the Excel workbook
* parameter-1: Excel workbook directory path,
* parameter-2: Sheet name*/
public static Iterator<Object[]> getTestData(String strWorkbookPath, String strWorksheetName) {
List<Object[]> data = new ArrayList<Object[]>();
int inRowCounter = 0;
try {
FileInputStream file = new FileInputStream(new File(strWorkbookPath));
//Get the workbook instance for the xlsx file.
HSSFWorkbook workbook = new HSSFWorkbook(file);
//Get the first sheet from the workbook
HSSFSheet sheet = workbook.getSheet(strWorksheetName);
//Get an iterator to all the rows in the current sheet
Iterator<Row> rowIterator = sheet.rowIterator();
Row firstRow = rowIterator.next();
Map<String, String> columnNamesMap = getColumnNames(firstRow);
while (rowIterator.hasNext()) {
Iterator<Cell> cellIterator = rowIterator.next().cellIterator();
Map<String, String> rowMap = new LinkedHashMap();
for (Entry entry : columnNamesMap.entrySet()) {
String strColumnName = entry.getKey().toString();
String strValue = cellIterator.next().toString();
rowMap.put(strColumnName, strValue);
}
}
file.close();
} catch (Exception e) {
e.printStackTrace();
}
return data.iterator();
}
private static Map<String, String> getColumnNames(Row row) {
Map<String, String> columnNamesMap = new LinkedHashMap();
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext()) {
String strColumnName = cells.next().toString();
columnNamesMap.put(strColumnName, strColumnName);
}
return columnNamesMap;
}
DataProvider.Class
@DataProvider(name = "AmazonProduct", parallel = false)
public static Iterator<Object[]> getDeviceName() {
String strWorkBookPath = new StringBuilder().append(System.getProperty("user.dir")).append(File.separator)
.append("resources\\testdata").append(File.separator).append("testdata").append(".xlsx").toString();
Iterator<Object[]> testData = ExcelUtil.getTestData(strWorkBookPath, "Mobiles");
return testData;
}
TestScripts.java
@Test(dataProvider = "AmazonProduct", dataProviderClass = DataProviderUtil.staticProviderClass.class)
public void searchAmazonProducts(Map<String, String> dataMap) {
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get("https://www.amazon.in/");
wait = new WebDriverWait(driver, 25);
WebElement txtSearchEngine = wait.until(ExpectedConditions.visibilityOfElementLocated(
By.cssSelector("#twotabsearchtextbox")));
System.out.println("\n Devices : " + dataMap.get("Devices"));
txtSearchEngine.sendKeys(dataMap.get("Devices"));
txtSearchEngine.submit();
driver.quit();
}
Please refer to the below image,
Parameterization in TestNG:
When there is a need to perform tests by using different test data, or when you are looking to test by logging in with a different user that has distinct usernames and passwords then Parameterization will come in handy as the “@Parameters” annotation in TestNG allows argument values to pass to Test methods via the testng.xml file. (Parameter values are declared in testng.xml) We have explained the different user scenarios using an example.
Syntax:
@Parameters({ “param-name” })
Let’s write a simple program for the @Parameters annotation,
Code:
@Test
@Parameters({"Username"})
public void TestMethod1(String strUsername) {
//We can retrieve the data using this argument. (It’ll retrieve from testng.xml file)
System.out.println("\n Username : " + strUsername);
}
TestNG Tutorial for Parallel Execution:
Saving time during the testing process is always a priority, and one of the best possible ways to do it would be by executing tests in parallel rather than sequential execution. So as promised at the beginning of this TestNG Tutorial, let’s see how we can have test suites executed in parallel on different browsers, and how it can be even defined in the Testing.xml file.
TestNG provides different levels of execution that we can achieve by using the Testing.xml file. The attributes that we can use to achieve them are,
i. Methods,
ii. Classes, and
iii. Tests.
i. parallel=”methods”:
We had already seen about methods that are dependent on other methods for their execution, so accordingly if you are looking to execute many independent methods in parallel, then this attribute can be used. Using this attribute, all test methods will run on a separate thread. In the below example, we have executed two test methods in two threads.
Note: Thread count is the specified number of browser instances that should be assigned for this test execution.
Syntax:
<suite name="Test-method Suite" parallel="methods" thread-count="2" >
Code :
TestParallelForMethodsExecution.java
public class TestParallelForMethodsExecution {
@Test
public void visitCodoidPage() {
String baseUrl = "https://codoid.com/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 25);
String testTitle = "QA Testing Company - Software Testing Services";
boolean isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
WebElement elmntAboutUsTab = driver.findElement(By.xpath("//ul[@id='top-menu']/li/a[text()='About Us']"));
elmntAboutUsTab.click();
driver.close();
}
@Test
public void visitAmazonPage() {
String baseUrl = "https://www.amazon.in/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
WebDriverWait wait = new WebDriverWait(driver, 25);
String testTitle = "Online Shopping site in India";
boolean isVerified;
isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
driver.close();
}
}
TestNG.xml
<suite thread-count="2" name="Parallel-Test-Suite" parallel="methods">
<test name="To Run TestNG :: Parallel methods concept">
<classes>
<class name="scripts.TestParallelForMethodsExecution"/>
</classes>
</test>
</suite>
ii. parallel=”tests”:
But the problem is that the above type will not work if we have a lot of test methods that are dependent on each other like how we saw earlier with the email example. So this attribute can be used to overcome this issue by adding all the dependent tests to a suite file (Testing.xml) and executing it separately in a thread as each tag will be considered a test suite and it’ll be executed in a separate thread.
Syntax:
<suite name="Test-Suite" parallel="tests" thread-count="2">
Code
MultipleSession1.java
public class MultipleSession1 {
public static WebDriver driver = null;
public static WebDriverWait wait = null;
@Test
public void visitAmazonPage() {
String baseUrl = "https://www.amazon.in/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
wait = new WebDriverWait(driver, 25);
String testTitle = "Online Shopping site in India";
boolean isVerified;
isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
}
@BeforeMethod
public void beforeMethod() {
System.out.println("\n Starting Test On Chrome Browser");
}
@AfterTest
public void terminateBrowser() {
driver.close();
}
}
MultipleSession2.java
public class MultipleSession2 {
public static WebDriver driver = null;
public static WebDriverWait wait = null;
@Test
public void visitCodoidAboutUsPage() {
String baseUrl = "https://codoid.com/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
wait = new WebDriverWait(driver, 25);
String testTitle = "QA Testing Company - Software Testing Services";
boolean isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
WebElement elmntAboutUsTab = driver.findElement(By.xpath("//ul[@id='top-menu']/li/a[text()='About Us']"));
elmntAboutUsTab.click();
}
@BeforeMethod
public void beforeMethod() {
System.out.println("\n Starting Test On Chrome Browser");
}
@AfterTest
public void terminateBrowser() {
driver.close();
}
}
TestNG.xml
<suite thread-count="2" name="Parallel-Test-Suite" parallel="tests">
<test name="To Run TestNG :: Parallel Tests concept - 1">
<classes>
<class name="scripts.MultipleSession1"/>
</classes>
</test>
<test name="To Run TestNG :: Parallel Tests concept - 2">
<classes>
<class name="scripts.MultipleSession2"/>
</classes>
</test>
</suite>
iii. parallel=”classes”:
This type has similar usage scope as the previous one with one major difference. Using this attribute, we can execute tests under each class in an individual thread, and the same has been explained in the below example.
Syntax:
<suite thread-count=”2” name =”Parallel-Test-Suite” parallel=”classes”>
Code:
Test1.java
public class Test1 {
public static WebDriver driver = null;
public static WebDriverWait wait = null;
@Test
public void Test1() {
String baseUrl = "https://codoid.com/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
wait = new WebDriverWait(driver, 25);
}
@Test
public void Test2() {
String testTitle = "QA Testing Company - Software Testing Services";
boolean isVerified;
isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
}
@Test
public void Test3() throws InterruptedException {
WebElement elmntAboutUsTab = driver.findElement(By.xpath("//ul[@id='top-menu']/li/a[text()='About Us']"));
elmntAboutUsTab.click();
}
@AfterTest
public void terminateBrowser() {
driver.close();
}
}
Test2.java
public class Test2 {
public static WebDriver driver = null;
public static WebDriverWait wait = null;
@Test(priority = 1)
public void launchAmazonURL() {
String baseUrl = "https://www.amazon.in/";
System.setProperty("webdriver.chrome.driver", "./resources/drivers/chromedriver.exe");
driver = new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
wait = new WebDriverWait(driver, 25);
}
@Test(priority = 2)
public void verifyAmazonTitle() {
String testTitle = "Online Shopping site in India";
boolean isVerified;
isVerified = wait.until(ExpectedConditions.titleContains(testTitle));
Assert.assertTrue(isVerified);
}
@Test(priority = 3)
public void navigatesToAboutUsPage() throws InterruptedException {
WebElement elmntAmazonPayTab = driver.findElement(By.xpath("//a[text()='Amazon Pay']"));
elmntAmazonPayTab.click();
}
@BeforeMethod
public void beforeMethod() {
System.out.println("\n Starting Test On Chrome Browser");
}
@AfterTest
public void terminateBrowser() {
driver.close();
}
}
TestNG.xml
<suite thread-count="2" name="Parallel-Test-Suite" parallel="classes">
<test name="Using Classes attributes for parallel execution.">
<classes>
<class name="scripts.Test1"/>
<class name="scripts.Test2"/>
</classes>
</test>
</suite>
In the above 3 points, it can be seen that we have defined the keywords for parallel (classes, tests, and methods) attributes on the Testing.xml file. Now, we’re going to explain the sample scripts for classes and methods.
Conclusion:
As promised at the beginning of this TestNG tutorial, we have explored all the plus points of TestNG. So we hope this information would be useful and that you have enjoyed reading this blog. As one of the leading automation testing companies, we have always found TestNG beneficial in crucial circumstances, and hope it will come in handy for you as well.
by admin | Jun 4, 2021 | Automation Testing, Blog |
In the world of software development, no product could ever face success without undergoing thorough and rigorous testing. Test automation is essential as it ensures that the end product delivered is stable and works according to the required specifications. However, QA teams and automation testing companies are not immune to making mistakes. In fact, any mistakes they made could potentially cost time, money, and trust that could easily derail the product’s success. Here are four common test automation mistakes your team should avoid at all times.
Not Identifying What Should and Shouldn’t Be Automated
For a tester, understanding what areas to automate and how it will help the organization is the basic rule of thumb for test automation success. It’s why you do the things you do.
However, there are times when you might be tempted to jump in and start hunting for tools to do the job. Don’t be too hasty about it, and make sure to clearly identify first which tasks to automate and which ones to execute manually. This will effectively be your guiding principle throughout the testing process. Failure to do so is a recipe for disaster.
Automating the Wrong Things
In a way, this is the result of mistake number one. Because you failed to identify what areas to automate, you risk making mistakes and automating the wrong things. Many teams try to automate tasks that aren’t actually good candidates for automation. One big miscalculation in this area is trying to translate your existing testing activities one-to-one into automation. Doing this is a huge waste of time and effort, leaving you to focus on things that don’t need to be automated at all. Keep your priorities straight, and don’t forget why you’re doing the testing in the first place.
Picking the Wrong Tools
There are many different problems you want to solve with automation, and one tool can’t solve all of them. That’s why picking the right tools is essential. The thing is, a lot of QA managers and automation testing companies are always looking for that one tool that could solve everything for them. The truth is, it just doesn’t exist.
The key is finding out what problem you want to solve with a tool, rather than buying a tool and then finding a problem for it. It’s best to design specific problems you need to solve before shopping around for a tool.
Failure to Coordinate with Fellow Testers
There are many people involved in a testing team. All these people are equipped with a different skill set that can prove invaluable to you. While they have their own specializations, that doesn’t mean you don’t discuss the progress of your tasks with them. Coordination is key to accelerating product delivery. Without coordination, you risk committing more mistakes and taking more time to fix those mistakes. If everyone is on the same page, they can respond better if something doesn’t go according to plan.
Conclusion
When handling an automation testing project, you need to be mindful of every little detail, including avoiding any pitfalls such as the ones mentioned above. While it is good to learn from your mistakes, it is always better to be preventive, especially if we’re talking about developing software.
If you’re in need of a QA company with a seamless track record, Codoid is your best choice. Every new software product deserves high-quality automation testing, and our team happens to be fully equipped to do just that. When it comes to QA automation services, there’s no better choice than Codoid. Partner with us today!