TestNG Groups Attribute: In TestNg grouping, similar methods are an essential feature. But using this feature, a user can be mentioned and assigned multiple methods into a named group. You can also execute those test methods which may belong to a group or multiple groups.
This feature helps us to separate the test methods into different sections or modules. We have done various types of testing on an application, like sanity, integration, regression testing, etc.
By using the grouping feature, we can segregate test methods based on their functionalities or features that the test method verifies. This helps us to execute only a particular set of tests as per the requirement, and because of this TestNG Grouping feature, we can be more productive.
Grouping in TestNG
- “Groups” is another attribute like alwaysRun, ignoreMissingDependencies. You can use these TestNG Groups attributes at the method and class level. Using this attribute, you can specify a method or class for which group or group.
- “Groups” takes values as a string array, meaning you can mention multiple group names simultaneously.
- During execution, by using testng.xml, you can also decide which group should execute by using the include and which groups will not by using exclude tags. If you do not mention any groups, it will run all groups.
TestNG Groups Syntax
We can mention a group name to a method or a class by following the below syntax:
For Single group: groups={“G1”}
For Multiple Group: groups={“G1″,”G2”}
Let us see a simple program:
package com.softwaretestingo.testng.groups; import org.testng.annotations.Test; public class RunAllMethodsWithoutUsingGroupName { // A test method belongs to Group G1 @Test(groups = { "G1" }) public void G1Method1() { System.out.println("G1 Method1"); } // A test method belongs to Group G1 @Test(groups = {"G1"}) public void G1Method2() { System.out.println("G1 Method2"); } // A test method belongs to Group G2 @Test(groups = {"G2"}) public void G2Method1() { System.out.println("G2 Method1"); } // A test method belongs to Group G2 @Test(groups = {"G2"}) public void G2Method2() { System.out.println("G2 Method2"); } // A test method belongs to Group G3 @Test(groups = {"G3"}) public void G3Method1() { System.out.println("G3 Method1"); } // A test method belongs to Group G3 @Test(groups = {"G3"}) public void G3Method2() { System.out.println("G3 Method2"); } }
Create a testng.xml file and run the above test class
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <classes> <class name="com.softwaretestingo.testng.groups.RunAllMethodsWithoutUsingGroupName"/> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
In this xml file, we have not mentioned any group name. It will run all the group’s methods.
Output:
G1 Method1 G1 Method2 G2 Method1 G2 Method2 G3 Method1 G3 Method2 =============================================== Suite Total tests run: 6, Passes: 6, Failures: 0, Skips: 0 ===============================================
But if we want to run some specific group methods, then we can do that by following the below method:
- By setting the attribute “enabled=false” for all the methods of the group that you don’t want to execute.
- By using the include/exclude tag.
Example: From the above TestNG Class, let us try to run only those methods that belong to G1.
You can use the XML file below to run the test methods tagged with the G1 group.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <groups> <run> <include name="G1" /> </run> </groups> <classes> <class name="com.softwaretestingo.testng.groups.RunAllMethodsWithoutUsingGroupName" /> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Output:
G1 Method1 G1 Method2 =============================================== Suite Total tests run: 2, Passes: 2, Failures: 0, Skips: 0 ===============================================
If you want to run the other group, then you need to add another <include> tag inside the <run> tag. Like below:
<run> <include name="G1"/> <include name="G2"/> </run>
Interview Question:
If a method belongs to multiple groups and if you run those groups separately, then how many times that method will be executed?
package com.softwaretestingo.testng.groups; import org.testng.annotations.Test; public class MultipleGroups { // A test method belongs to Group G1 and G2 @Test(groups = { "G1", "G2" }) public void MethodsBelongToG1G2() { System.out.println("MethodsBelongToG1G2"); } // A test method belongs to Group G1, G2 and G3 @Test(groups = { "G1", "G2", "G3" }) public void MethodsBelongToG1G2G3() { System.out.println("MethodsBelongToG1G2G3"); } // A test method belongs to Group G1 @Test(groups = { "G1" }) public void MethodsBelongToG1() { System.out.println("MethodsBelongToG1"); } // A test method belongs to Group G2 @Test(groups = { "G2" }) public void MethodsBelongToG2() { System.out.println("MethodsBelongToG2"); } // A test method belongs to Group G3 @Test(groups = { "G3" }) public void MethodsBelongToG3() { System.out.println("MethodsBelongToG3"); } // A test method belongs to Group G1 and G3 @Test(groups = { "G1", "G3" }) public void MethodsBelongToG1G3() { System.out.println("MethodsBelongToG1G3"); } }
Xml File:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <groups> <run> <include name="G1" /> <include name="G2" /> <include name="G3" /> </run> </groups> <classes> <class name="com.softwaretestingo.testng.groups.MultipleGroups" /> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Output:
MethodsBelongToG1 MethodsBelongToG1G2 MethodsBelongToG1G2G3 MethodsBelongToG1G3 MethodsBelongToG2 MethodsBelongToG3 =============================================== Suite Total tests run: 6, Passes: 6, Failures: 0, Skips: 0 ===============================================
Note: You can see the MethodsBelongToG1G2G3() method is assigned to multiple groups, so we may think that it will execute three times, but it will execute once.
Exclude Tag In Groups
In the same way, you can mention the group name that you don’t want to run by using the <exclude> tag, like below:
<groups> <run> <exclude name="G1"/> </run> </groups>
If we want to run only the first two groups, then we can mention this:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <groups> <run> <include name="G1" /> <include name="G2" /> <exclude name="G3" /> </run> </groups> <classes> <class name="com.softwaretestingo.testng.groups.MultipleGroups" /> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Output:
MethodsBelongToG1 MethodsBelongToG1G2 MethodsBelongToG2 =============================================== Suite Total tests run: 3, Passes: 3, Failures: 0, Skips: 0 ===============================================
How do you use regular expressions with TestNG groups?
We have seen how to make TestNG Groups as per requirement. If you have used somany groups inside your TestNG classes, we suggest using some prefixes or suffixes with the group name.
That will help us to easily use the regular expression by which we can decrease the complexity with the help of regular expression. We can represent more TestNG Group names through a single statement with regular expression.
Let us see how we can do that:
package com.softwaretestingo.testng.groups; import org.testng.annotations.Test; public class GroupWithRegularExpression { /* * Generally smoke tests are subset of regression. Smoke tests are run for high level testing of * basic functionality. SO sometimes you need to run only smoke tests and sometimes regression. * Regression will include more or less everything. */ @Test(groups = { "Regression_Group1", "Smoke_Group1" }) public void Group1Method1() { System.out.println("Group1 Method1"); } @Test(groups = { "Regression_Group1" }) public void Group1Method2() { System.out.println("Group1 Method2"); } @Test(groups = { "Regression_Group2", "Smoke_Group2" }) public void Group2Method1() { System.out.println("Group2 Method2"); } @Test(groups = { "Regression_Group2" }) public void Group2Method2() { System.out.println("Group2 Method2"); } @Test(groups = { "Regression_Group3", "Smoke_Group3" }) public void Group3Method1() { System.out.println("Group3 Method3"); } @Test(groups = { "Regression_Group3" }) public void Group3Method3() { System.out.println("Group3 Method3"); } }
Now, from the above class, if we want to run all the smoke groups, then we have to mention all the smoke groups one by one like below :
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <groups> <run> <include name="Smoke_Group1" /> <include name="Smoke_Group2" /> <include name="Smoke_Group3" /> </run> </groups> <classes> <class name="com.softwaretestingo.testng.groups.GroupWithRegularExpression" /> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
But we can achieve the same TestNG Groups thing by using the regular expression:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <groups> <run> <include name="Smoke.*" /> </run> </groups> <classes> <class name="com.softwaretestingo.testng.groups.GroupWithRegularExpression" /> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
As you can see above, we have used the regular expression to mention all the smoke groups in a single statement. And the output will be
Group1 Method1 Group2 Method2 Group3 Method3 =============================================== Suite Total tests run: 3, Passes: 3, Failures: 0, Skips: 0 ===============================================
Note:
- TestNG uses regular expressions and not wildcards. Be aware of the difference (for example, “anything” is matched by.”*” — dot star — and not “*”).
- You can’t use regex in the class name attribute with TestNG xml. Regex can be used to include exclude tags and package tags.
- Regex is case-sensitive, meaning “Smoke” and “smoke” differ.
@BeforeGroups & @AfterGroups Annotations
Above, we discussed using group attributes with the @Test Annotation. But We have two annotations related to Groups: @BeforeGroups And @AfterGroups.
With a simple program, let’s try to understand how these annotations work with groups in TestNG.
package com.softwaretestingo.testng.groups; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; public class GroupAnnotationUses { @BeforeGroups("Test1") public void login() { System.out.println("Login Sucessfully"); } @AfterGroups("Test2") public void logout() { System.out.println("Logout Sucessfully"); } @Test(groups={"Test1"}) public void FundTransfer() { System.out.println("Fund Transfer"); } @Test(groups={"Test1","Test2"}) public void search() { System.out.println("Search Sucessfully"); } @Test(groups={"Test2"}) public void bill() { System.out.println("Bill Generated"); } }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd"> <suite name="Suite"> <test thread-count="5" name="Test"> <classes> <class name="com.softwaretestingo.testng.groups.GroupAnnotationUses"/> </classes> </test> <!-- Test --> </suite> <!-- Suite -->
Output:
Login Sucessfully Fund Transfer Bill Generated Search Sucessfully Logout Sucessfully =============================================== Suite Total tests run: 3, Passes: 3, Failures: 0, Skips: 0 ===============================================
TestNG dependsOnGroups Example
We have already seen dependsOnMethods. Similarly, we have another attribute called dependsOnGroups. Here, the dependent test will run after the dependent groups are executed.
package com.softwaretestingo.testng.groups; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; public class DependsOnGroups { @BeforeGroups("smoke") public void setUp() { System.out.println("Browser Launched"); } @AfterGroups("smoke") public void tearDown() { System.out.println("Browser Closed"); } @Test(groups = "smoke") public void HomePage() { System.out.println("Home Page Launched"); } @Test(dependsOnGroups = {"smoke"}) public void verifyTest() { System.out.println("Smoke Test Completed"); } }
Here, if we run the above testing Class, then the output will be
Browser Launched Home Page Launched Browser Closed Smoke Test Completed
If you notice, after the successful execution of the Smoke group, the dependsOnGroups test method was executed. But if the smoke group got any exception for any reason, then the dependsOnGroups test method will not execute.
To understand the execution behavior, let us take an example where we will intentionally raise an exception in the test method.
package com.softwaretestingo.testng.groups; import org.testng.annotations.AfterGroups; import org.testng.annotations.BeforeGroups; import org.testng.annotations.Test; public class DependsOnGroups { @BeforeGroups("smoke") public void setUp() { System.out.println("Browser Launched"); } @AfterGroups("smoke") public void tearDown() { System.out.println("Browser Closed"); } @Test(groups = "smoke") public void HomePage() { System.out.println("Home Page Launched"); throw new RuntimeException(); } @Test(dependsOnGroups = {"smoke"}) public void verifyTest() { System.out.println("Smoke Test Completed"); } }
Here, we have intentionally raised RuntimeException in the HomePage method; that’s why the verifyTest method will be skipped.
Browser Launched Home Page Launched Browser Closed FAILED: com.softwaretestingo.testng.groups.DependsOnGroups.HomePage SKIPPED: com.softwaretestingo.testng.groups.DependsOnGroups.verifyTest =============================================== Default test Tests run: 2, Failures: 1, Skips: 1 =============================================== =============================================== Default suite Total tests run: 2, Passes: 0, Failures: 1, Skips: 1 ===============================================