Understanding TestNG Groups: A Comprehensive Guide

What are TestNG Groups?

TestNG Groups provide a way to categorize test methods. This is particularly useful when you have various test cases spread across different classes, and you want to selectively run specific sets of tests. Not only can you declare methods within a specified group, but you can also nest groups within other groups, providing a high degree of flexibility.

Advantages

  • Flexibility

  • Selective Execution

  • Organized Test Structure

How to Use TestNG Groups

1. Basic Grouping Example:

Let's consider a scenario where we have three classes - Personal_loan.java, Home_loan.java, and Car_loan.java. Each class contains multiple test methods, and we want to group them based on a common characteristic, such as SmokeTest.

// Personal_loan.java
@Test(groups= {"SmokeTest"})
public void WebLoginPersonalLoan() {
    System.out.println("Web Login Personal Loan");
}

// Home_loan.java
@Test(groups= {"SmokeTest"})
public void MobileLoginHomeLoan() {
    System.out.println("Mobile Login Home Loan");
}

// Car_loan.java
@Test(groups= {"SmokeTest"})
public void APILoginCarLoan() {
    System.out.println("API Login Car Loan");
}

In the above example, we've tagged specific test methods with the group SmokeTest.

2. Running Tests with TestNG XML:

To execute specific groups, we use the testng.xml file. Here's an example:

<!-- testng.xml -->
<suite name="test_suite">
    <groups>
        <run>
            <include name="SmokeTest"/>
        </run>
    </groups>
    <test name="Smoke Tests">
        <classes>
            <class name="com.javatpoint.Personal_loan"/>
            <class name="com.javatpoint.Home_loan"/>
            <class name="com.javatpoint.Car_loan"/>
        </classes>
    </test>
</suite>

In this XML configuration, we include the SmokeTest group to run only the relevant test methods.

3. Multiple Groups and Exclusion:

You can assign multiple groups to a test method and even exclude specific groups. Here's an example:

// Groups.java

@Test(groups= {"Group A"})
public void testcase1() {
    System.out.println("Test case belonging to Group A");
}

@Test(groups= {"Group A", "Group B"})
public void testcase2() {
    System.out.println("Test case belonging to both Group A and Group B");
}

@Test(groups= {"Group B"})
public void testcase3() {
    System.out.println("Test case belonging to Group B");
}
<!-- testng.xml -->
<test name="Group A">
    <groups>
        <run>
            <include name="Group A"/>
        </run>
    </groups>
    <classes>
        <class name="com.javatpoint.Groups"/>
    </classes>
</test>

<test name="Group B">
    <groups>
        <run>
            <include name="Group B"/>
        </run>
    </groups>
    <classes>
        <class name="com.javatpoint.Groups"/>
    </classes>
</test>

In this example, testcase1 is in Group A, testcase2 is in both Group A and Group B, and testcase3 is in Group B. The XML configuration allows us to selectively run tests belonging to these groups.

4. Including/Excluding Groups:

You can explicitly include or exclude groups using the <include> and <exclude> tags in the testng.xml file:

// Groups.java

@Test(groups= {"Include Group"})
public void test_case1() {
    System.out.println("This is test case 1");
}

@Test(groups= {"Include Group"})
public void test_case2() {
    System.out.println("This is test case 2");
}

@Test(groups= {"Exclude Group"})
public void test_case3() {
    System.out.println("This is test case 3");
}
<!-- testng.xml -->
<test name="Include and Exclude Group">
    <groups>
        <run>
            <include name="Include Group"/>
            <exclude name="Exclude Group"/>
        </run>
    </groups>
    <classes>
        <class name="com.javatpoint.Groups"/>
    </classes>
</test>

In this example, test_case1 and test_case2 are included, while test_case3 is excluded.

5. Using Regular Expressions:

TestNG allows the use of regular expressions to include or exclude groups:

// Regular_Expression.java

@Test(groups= {"Include test case1"})
public void test_case1() {
    System.out.println("This is test case 1");
}

@Test(groups= {"Include test case2"})
public void test_case2() {
    System.out.println("This is test case 2");
}

@Test(groups= {"Exclude test case3"})
public void test_case3() {
    System.out.println("This is test case 3");
}
<!-- testng.xml -->
<test name="Including test cases">
    <groups>
        <run>
            <include name="Include.*"/>
        </run>
    </groups>
    <classes>
        <class name="com.javatpoint.Regular_Expression"/>
    </classes>
</test>

In this example, the regular expression Include.* includes groups starting with "Include."

6. Groups in Groups:

You can create meta-groups by defining groups within other groups. Let's consider an example:

// Groups_in_Groups.java

@Test(groups= {"Smoke"})
public void test1() {
    System.out.println("test1");
}

@Test(groups= {"Regression"})
public void test2() {
    System.out.println("test2");
}

@Test
public void test3() {
    System.out.println("test3");
}
<!-- testng.xml -->
<test name="Groups in Groups">
    <groups>
        <define name="Group 1">
            <include name="Smoke"/>
            <include name="Regression"/>
        </define>
        <run>
            <include name="Group 1"/>
        </run>
    </groups>
    <classes>
        <class name="com.javatpoint.Groups_in_Groups"/>
    </classes>
</test>

Let's dive into a more detailed explanation and an example:

Example Scenario:

Consider a scenario where you have different types of tests for a web application: Smoke Tests, Regression Tests, and End-to-End Tests. Additionally, each of these test types may consist of more specific groups. For example, Smoke Tests might include sub-groups like Login and Homepage, while Regression Tests might include sub-groups like Database and API.

Implementation in TestNG

Let's create a set of test methods in a Java class (Groups_in_Groups.java) that simulates this scenario:

// Groups_in_Groups.java
import org.testng.annotations.Test;

public class Groups_in_Groups {

    @Test(groups = {"Smoke", "Login"})
    public void test1() {
        System.out.println("Smoke Test: Login");
    }

    @Test(groups = {"Smoke", "Homepage"})
    public void test2() {
        System.out.println("Smoke Test: Homepage");
    }

    @Test(groups = {"Regression", "Database"})
    public void test3() {
        System.out.println("Regression Test: Database");
    }

    @Test(groups = {"Regression", "API"})
    public void test4() {
        System.out.println("Regression Test: API");
    }

    @Test(groups = {"End-to-End"})
    public void test5() {
        System.out.println("End-to-End Test");
    }
}

In this example:

  • test1 and test2 are part of the Smoke group and further categorized into Login and Homepage sub-groups.

  • test3 and test4 are part of the Regression group and further categorized into Database and API sub-groups.

  • test5 is a standalone test in the End-to-End group.

Using Meta-Groups in TestNG XML

Now, let's create a testng.xml file that defines meta-groups:

<!-- testng.xml -->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="test_suite">
    <test name="Web Application Tests">
        <groups>
            <define name="Smoke">
                <include name="Login"/>
                <include name="Homepage"/>
            </define>
            <define name="Regression">
                <include name="Database"/>
                <include name="API"/>
            </define>
        </groups>
        <run>
            <include name="Smoke"/>
            <include name="Regression"/>
        </run>
        <classes>
            <class name="com.javatpoint.Groups_in_Groups"/>
        </classes>
    </test>
</suite>

In this testng.xml file:

  • We define two meta-groups: Smoke and Regression.

  • Each meta-group includes specific sub-groups (e.g., Login, Homepage, Database, API).

  • The <run> section specifies which meta-groups to include in the test run (Smoke and Regression).