Introduction
In the previous post, we have seen how maximum beginners and experienced Selenium professionals apply inheritance with TestNG annotations while setup test scripts and end up with encountering NullPointerException. We have solved NullPointerException by converting instance variables to Static variables.
We can solve the above problem using a Singleton design pattern as well. Let’s learn about it.
Dependency version details
TestNG version used as below:-
org.testng testng 7.1.0 test
Singleton Class
Let’s think of a scenario. A money bank may have many branches and many registered customers can withdraw or deposit or access there account at any time any place. Bank has a centralized common server where details of each customer are stored. If a new branch is opened it will also access data from the same server. If a brach is closed then also server will have customer’s data. In short, there is a common place where the state of data is stored.
We can consider an example of money withdrawal from ATM. If a customer tries to withdraw money simultaneously from two places, surely it will fail in one place because they also have a common place where data is kept updated. We can call that common place as a Singleton class.
When we develop a class in such a way that it can have the only instance at any time, is called a Singleton class. If a class is not instantiated then instantiate it and if the class is already instantiated return the same instantiated instance of the class. If we allow only one instance of any class that means we will have a shared object (somewhat how does a class variable or static variable works). This will solve our problem explained in the previous post. Variables initialized in TestNG annotated method will be stored in a common object for usage wherever we want.
Singleton class to store shared variables
package SecondTestNullPointerExceptionWithSingleton; public class SharedVariables { // Private instance of class private static final SharedVariables instance = new SharedVariables(); // Private constructor to control object creation of class private SharedVariables() { } // Return unidealized instance of class public static SharedVariables getInstance() { return instance; } // A private variable with getter and setter methods private String someVariable; public String getSomeVariable() { return someVariable; } public void setSomeVariable(String someVariable) { this.someVariable = someVariable; } }
Setup class with TestNG annotation
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.BeforeSuite; public class Setup { // Get same instance of SharedVariables always SharedVariables sharedVariables = SharedVariables.getInstance(); @BeforeSuite public void setupVariable() { System.out.println("Executing setupVariable..."); sharedVariables.setSomeVariable("someValue"); } }
FirstTestNG class
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.Test; public class FirstTestNGClass extends Setup{ @Test public void firstMethodOfFirstTestNGClass() { System.out.println("Executing firstMethodOfFirstTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); } @Test public void secondMethodOfFirstTestNGClass() { System.out.println("Executing secondMethodOfFirstTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); } }
SecondTestNG class
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.Test; public class SecondTestNGClass extends Setup{ @Test public void firstMethodOfSecondTestNGClass() { System.out.println("Executing firstMethodOfSecondTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); } @Test public void secondMethodOfSecondTestNGClass() { System.out.println("Executing secondMethodOfSecondTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); } }
SecondTestNullPointerExceptionWithSingleton.xml
Output
[RemoteTestNG] detected TestNG version 7.0.1 Executing setupVariable... Executing firstMethodOfFirstTestNGClass... Value of someVariable is : someValue Executing secondMethodOfFirstTestNGClass... Value of someVariable is : someValue Executing firstMethodOfSecondTestNGClass... Value of someVariable is : someValue Executing secondMethodOfSecondTestNGClass... Value of someVariable is : someValue =============================================== Suite Total tests run: 4, Passes: 4, Failures: 0, Skips: 0 ===============================================
You may ask in the above Singleton class creating variables in advance will be difficult and how can we save random variables. We can make out singleton class more advance with Map where will give user flexibility to save any data. This implementation even helps in sharing context among tests.
Singleton class with Map
package SecondTestNullPointerExceptionWithSingleton; import java.util.HashMap; public class SharedVariablesMap { // Private instance of class private static final SharedVariablesMap instance = new SharedVariablesMap(); private static HashMapdataStore = new HashMap<>(); // Private constructor to control object creation of class private SharedVariablesMap() { } // Return unidealized instance of class public static SharedVariablesMap getInstance() { return instance; } public void store(String key, String value) { dataStore.put(key, value); } public Object get(String key) { return dataStore.get(key); } }
Setup class
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.BeforeSuite; public class Setup { // Get same instance of SharedVariables always SharedVariables sharedVariables = SharedVariables.getInstance(); SharedVariablesMap sharedVariablesMap = SharedVariablesMap.getInstance(); @BeforeSuite public void setupVariable() { System.out.println("Executing setupVariable..."); sharedVariables.setSomeVariable("someValue"); sharedVariablesMap.store("Name", "Amod"); } }
FirstTestNG class
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.Test; public class FirstTestNGClass extends Setup{ @Test public void firstMethodOfFirstTestNGClass() { System.out.println("Executing firstMethodOfFirstTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); System.out.println("Value of name is :"+ sharedVariablesMap.get("Name")); } @Test public void secondMethodOfFirstTestNGClass() { System.out.println("Executing secondMethodOfFirstTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); System.out.println("Value of name is :"+ sharedVariablesMap.get("Name")); } }
SecondTestNG class
package SecondTestNullPointerExceptionWithSingleton; import org.testng.annotations.Test; public class SecondTestNGClass extends Setup{ @Test public void firstMethodOfSecondTestNGClass() { System.out.println("Executing firstMethodOfSecondTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); System.out.println("Value of name is :"+ sharedVariablesMap.get("Name")); } @Test public void secondMethodOfSecondTestNGClass() { System.out.println("Executing secondMethodOfSecondTestNGClass..."); System.out.println("Value of someVariable is : "+ sharedVariables.getSomeVariable()); System.out.println("Value of name is :"+ sharedVariablesMap.get("Name")); } }
There is no change in TestNG xml.
Output
[RemoteTestNG] detected TestNG version 7.0.1 Executing setupVariable... Executing firstMethodOfFirstTestNGClass... Value of someVariable is : someValue Value of name is :Amod Executing secondMethodOfFirstTestNGClass... Value of someVariable is : someValue Value of name is :Amod Executing firstMethodOfSecondTestNGClass... Value of someVariable is : someValue Value of name is :Amod Executing secondMethodOfSecondTestNGClass... Value of someVariable is : someValue Value of name is :Amod =============================================== Suite Total tests run: 4, Passes: 4, Failures: 0, Skips: 0 ===============================================
You can download/clone the above sample project from here.
If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning
Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.
Many other topics you can navigate through the menu.
Thanks. This is cool. I’ll think of usage when adapting to selenium tests suites.