Search code examples
annotationsautomated-teststestnglistenertestng-dataprovider

how to pass data to onTestSuccess method in Listener class of TESTNG for each iteration from @Test method used dataprovider


, i have a @Test method with dataprovider , i have a Listener.class , my target is that when my @Test method is success, the status of case in testrail is setted as "Passed" automatically in onTestSuccess Method of Listener class , this process is ok, but when i use dataprovider for @Test Method, this causes the problem

i want that same method must be worked (let say) three times because of dataprovider and different case id data must be sent to onTestSuccess method for each iteration from @Test method

My Listener.class

package com.myproject.test.listeners;
import java.lang.reflect.Method;
import org.testng.IClass;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ISuite;
import org.testng.ISuiteListener;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;

public class Listener implements ITestListener, ISuiteListener, IInvokedMethodListener {
    ...
    public void onTestStart(ITestResult result) {
    }
    public void onTestSuccess(ITestResult result) {
        try {
            Program pr = new Program();
            System.out.println("onTestSuccess Method for :" + result.getName());
            String TestID = null;
            String TestRunID = null;
            for (Method testMethod : result.getTestClass().getRealClass().getMethods()) {
                if (testMethod.getName().equals(result.getName()) && testMethod.isAnnotationPresent(UseAsTestRailId.class)) {


                    UseAsTestRailId useAsTestName = testMethod.getAnnotation(UseAsTestRailId.class);
                    TestID = Integer.toString(useAsTestName.testRailCaseId());
                    TestRunID = Integer.toString(useAsTestName.testRailRunId());
                    System.out.println("Case ID---> " + TestID + " Run ID--> " + TestRunID);
                    // 1 = Passed
                    pr.enterTestResult(TestRunID, TestID, 1);
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }
    }

...
}

My test class (SettingsTests.java) including my @Test method (checkCurrentPasswordFormatIsValidatedTest)

@Listeners(com.test.listeners.Listener.class)
//listener annotation row is written in BaseTest class 
public class SettingsTests extends BaseTest {


...


    /**
     * Test Case - C5001275 - Check that "Please enter at least 8 characters."
     * message is displayed when entered value into "Current Password" field in
     * wrong format This case will run two times!
     * 
     * @param currentPasswordValue
     */
    @Test(dataProvider = "currentPasswordTestWithWrongValue")
    @UseAsTestRailId(testRailCaseId = 5001275,testRailRunId = 56662) 
    // aim is that to send different case id for each iteration,now even if method works twice , only one testRailCaseId is sent
    public void checkCurrentPasswordFormatIsValidatedTest(String currentPasswordValue) {
        logger.trace("STARTING TEST: checkCurrentPasswordFormatisValidatedTest");

        logger.trace("Test Step : Enter current password in wrong format");
        settingsPageObject.enterCurrentPassword(currentPasswordValue);

        logger.trace("Test Step : Click on the button 'UPDATE' ");
        settingsPageObject.clickOnUpdateButton();

        logger.trace("Expected Result: The message 'Please enter at least 8 characters.' is displayed on screen.");
        Assert.assertEquals(settingsPageObject.getCurrentPasswordWrongText(), "Please enter at least 8 characters.");
    }



    @DataProvider(name = "currentPasswordTestWithWrongValue")
    public static Object[][] validateTestWithCurrentPasswordInWrongFormat() {

        return new Object[][] { { RandomStringUtils.randomAlphabetic(7) }, { RandomStringUtils.randomAlphabetic(1) } };
    }


...

}

My annotation class (UseAsTestRailId.java)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UseAsTestRailId
{
    int testRailCaseId() default 0;
    int testRailRunId() default 0;
    String[] tags() default "";
}

Some @Test methods to set two case status, some @Test methods to set three case status in testRail,so the more dataprovider data set needed the more case id needed , it must be dynamical


Solution

  • You can use the setattribute value in the testresult object to set custom value. Get the currentresult from Reporter : Reporter.getCurrentTestresult and then setAttribute ("TC_id",sasdf) and use that in your ontestsuccess using the getAttribute ("TC_id") on result object.