1

I am running a test suite with the test methods belonging to a certain groups.

Below is the Selenium code:

public class BaseClass
{

    @BeforeMethod(onlyForGroups = {"P1"})
    public void bmeth1()
    {
        System.out.println("Before Method1 called");
    }

    @BeforeMethod(onlyForGroups = {"P2"})
    public void bmeth2()
    {
        System.out.println("Before Method2 called");
    }

    @BeforeMethod(onlyForGroups = {"P3"})
    public void bmeth3()
    {
        System.out.println("Before Method3 called");
    }

    @AfterMethod(onlyForGroups = {"P1"})
    public void ameth1()
    {
        System.out.println("After Method1 called");
    }

    @AfterMethod(onlyForGroups = {"P2"})
    public void ameth2()
    {
        System.out.println("After Method2 called");
    }

    @AfterMethod(onlyForGroups = {"P3"})
    public void ameth3()
    {
        System.out.println("After Method3 called");
    }

}

public class TC_003 extends BaseClass
{

    @Test(groups = {"P1"})
    public void tCase6()
    {
        System.out.println("Inside testcase 6");
    }

    @Test(groups = {"P2"})
    public void tCase7()
    {
        System.out.println("Inside testcase 7");
    }

    @Test(groups = {"P3"})
    public void tCase8()
    {
        System.out.println("Inside testcase 8");
    }

}

Below is the testng.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite" verbose="10">
<test name="Test1">
    <groups>
        <run>
            <include name=".*"/>
        </run>
    </groups>
    <classes>
        <class name="testing.TC_003"/>
    </classes>
</test>
</suite>

Actual Output:

Inside testcase 6
Inside testcase 7
Inside testcase 8

Expected Output:

Before Method1 called
Inside testcase 6
After Method1 called
Before Method2 called
Inside testcase 7
After Method2 called
Before Method3 called
Inside testcase 8
After Method3 called

The test methods are executed, but the @BeforeMethod/@AfterMethod did not execute. This issue occurs only if we include certain groups in testng.xml file. But if we exclude certain groups or do not use groups tag in testng.xml file, then they are executed.

As suggested here, the current workaround is to use alwaysRun=true flag along with onlyForGroups flag. But if we apply this workaround, and if there is any SkipException in the preceding/parent config methods, then it is forced to execute the @BeforeMethod/@AfterMethod methods, even when the test method is going to be skipped. There is a similar issue logged here, when the preceding/parent config methods has failed.

64
  • your code works as it is are ou using 7.3.0 lates testng ?
    – PDHide
    Commented Feb 17, 2021 at 0:39
  • 1
    i have added information on how to mix the two also
    – PDHide
    Commented Feb 22, 2021 at 17:19
  • 1
    Please read the updated answer groups defines the group a method belongs to , so if you specify that in testng.xml then only those groups get executed
    – PDHide
    Commented Feb 22, 2021 at 17:39
  • 1
    so if your before and after is in that group or doesn't has alwaysrun enabled , it won't get invoked
    – PDHide
    Commented Feb 22, 2021 at 17:40
  • 1
    yes thats correct :) groups and always run is just for invoking , only gtoup is to create relation ship
    – PDHide
    Commented Feb 22, 2021 at 18:18

1 Answer 1

1

Its an interesting observation if you change onlyforgroups to groups then everything works:

but when there are multiple groups included in your testng.xml then all before and after method in mentioned group get executed before every test method . so in order to avoid this you have to mix groups and onlygroups together

Explanation:

If you don't specify group in testng xml then all methods get invoked. but if you mention group then only methods in that particular group get executed.

this is because if you read the definition of groups:

https://testng.org/doc/documentation-main.html

groups The list of groups this class/method belongs to.

so if you don't mention the group or always run true then the method is not invoked so you won't get the before and after method invoked as they are not in any group

Work around:

you can mix the two as :

package driversetup;

import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;



public class TestBaseClass  {
    

    @BeforeMethod(onlyForGroups = {"P1"},groups = {"P1"})
    public void bmeth1()
    {
        System.out.println("Before Method1 called");
    }

    @BeforeMethod(onlyForGroups = {"P2"},groups = {"P2"})
    public void bmeth2()
    {
        System.out.println("Before Method2 called");
    }

    @BeforeMethod(onlyForGroups = {"P3"},groups = {"P3"})
    public void bmeth3()
    {
        System.out.println("Before Method3 called");
    }

    @AfterMethod(onlyForGroups = {"P1"},groups = {"P1"})
    public void ameth1()
    {
        System.out.println("After Method1 called");
    }

    @AfterMethod(onlyForGroups = {"P2"},groups = {"P2"})
    public void ameth2()
    {
        System.out.println("After Method2 called");
    }

    @AfterMethod(onlyForGroups = {"P3"},groups = {"P3"})
    public void ameth3()
    {
        System.out.println("After Method3 called");
    }
    

}

or enable always run true

package driversetup;

import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;



public class TestBaseClass {
    

    @BeforeMethod(onlyForGroups = {"P1"},alwaysRun = true)
    public void bmeth1()
    {
        System.out.println("Before Method1 called");
    }

    @BeforeMethod(onlyForGroups = {"P2"},alwaysRun = true)
    public void bmeth2()
    {
        System.out.println("Before Method2 called");
    }

    @BeforeMethod(onlyForGroups = {"P3"},alwaysRun = true)
    public void bmeth3()
    {
        System.out.println("Before Method3 called");
    }

    @AfterMethod(onlyForGroups = {"P1"},alwaysRun = true)
    public void ameth1()
    {
        System.out.println("After Method1 called");
    }

    @AfterMethod(onlyForGroups = {"P2"},alwaysRun = true)
    public void ameth2()
    {
        System.out.println("After Method2 called");
    }

    @AfterMethod(onlyForGroups = {"P3"},alwaysRun = true)
    public void ameth3()
    {
        System.out.println("After Method3 called");
    }
    

}

this ensures that the before and after method gets invoked, but get executed only for correct @test methods

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.