testng icon indicating copy to clipboard operation
testng copied to clipboard

TestReport customisation: How to get java method names at runtime for adding them in reports instead of TestNames

Open p00j4 opened this issue 11 years ago • 15 comments

Hi Cedric, Thanks for writing this awesome piece. I have a query.... At run time, how can I get the java method names called under a testMethod
ex. ITestContext/ITestResult exposes the testMethods mentioned in testNg.xml file [ but I want to get java methods which are not annotated and being called from any test annotated method]. Need:

@Test(dataProvider="itenary") public void testBooking(StringArray data){ homePage(data); searchPage(data); bookingPage(data); } Now if a test fails in bookingPage() flow then I want to show the method name bookingPage() in test report but not testBooking() [so that my report becomes more narrowed to understand which function caused the fail in entire booking flow testing] similarly for all other methods [but as per my current understanding I can just show the test method name] What I tried: thought to have different tests for all above 3 methods but since I need same data from dataprovider to be passed in all, so It can't be possible. Can you please suggest, any alternative or a object which exposes methods at run time , so that I can make my reports more relevant.

p00j4 avatar Dec 17 '14 08:12 p00j4

@cedricrefresh : Kindly please suggest a way

p00j4 avatar Jan 07 '15 13:01 p00j4

@nullin @cbeust @VladRassokhin

p00j4 avatar Jan 10 '15 03:01 p00j4

To store data between methods you could use @Factory on class constructor and fields. So could would look like:

class TestClass {
final Object[] args;
@Factory(dataProvider="itenary")
TestClass(Object[] args) {this.args = args}

@Test
void homePage() ...;
@Test(dependsOn="homePage")
searchPage(data) ...;
@Test(dependsOn="searchPage")
bookingPage(data) ... ;
}

But there exists another approaches, e.g. change method name in ITestResult, etc.

VladRassokhin avatar Jan 11 '15 02:01 VladRassokhin

@VladRassokhin : thanks for replying , i'm trying this and will update on the same. however, can you just forward any link which can give little more details on "e.g. change method name in ITestResult,"

p00j4 avatar Jan 11 '15 04:01 p00j4

@VladRassokhin : I tried using Factory but it doesn't serve my purpose, here is my code

public class TestClass {
    final int args;
    @Factory(dataProvider="itenary")
    public TestClass(int args) 
    {
        this.args = args;
    }

    @DataProvider
    static public Object[][] itenary() {
      return new Object[][] {
        new Object[] { 41 },
        new Object[] { 42 },
      };
    }
    @Test(description="homePage /././.",dataProvider="itenary")
    public void homePage(int data){
        System.out.println("in searchPage, data="+data);
    }


    @Test(dependsOnMethods="homePage",dataProvider="itenary")
    public void searchPage(int data){
        System.out.println("in searchPage, data="+data);
    }

    @Test(dependsOnMethods="searchPage",dataProvider="itenary")
    public void bookingPage(int data){
        System.out.println("in bookingPage, data="+data);
    }
}

and the output is-

in homePage, data=41
in homePage, data=42
in homePage, data=41
in homePage, data=42
in searchPage, data=41
in searchPage, data=42
in searchPage, data=41
in searchPage, data=42
in bookingPage, data=41
in bookingPage, data=42
in bookingPage, data=41
in bookingPage, data=42
PASSED: homePage(41)
        homePage /././.
PASSED: homePage(42)
        homePage /././.
PASSED: homePage(41)
        homePage /././.
PASSED: homePage(42)
        homePage /././.
PASSED: searchPage(41)
PASSED: searchPage(42)
PASSED: searchPage(41)
PASSED: searchPage(42)
PASSED: bookingPage(41)
PASSED: bookingPage(42)
PASSED: bookingPage(41)
PASSED: bookingPage(42)

===============================================
    Default test
    Tests run: 12, Failures: 0, Skips: 0
===============================================

rather my desired output is [Since I want all the tests should run for the same data in one cycle]-

in homePage, data=41
in searchPage, data=41
in bookingPage, data=41
in homePage, data=42
in searchPage, data=42
in bookingPage, data=42

Please correct me if I have used Factory in wrong manor, also as per definition, factory is generally used for load testing to load same test multiple times, so I'm wondering how does it can fit my requirement ! image

p00j4 avatar Jan 11 '15 06:01 p00j4

My requirement is , when a test fails, so related enclosing method name should be displayed in test report Ex. when failure occurs in in bookingPage() flow then bookingPage() should be shown in test report but not testBooking() [so that my report becomes more narrowed/specialized to understand which function caused the fail in entire "testBooking" testNg test]

p00j4 avatar Jan 11 '15 06:01 p00j4

@nullin @VladRassokhin @lukasj : anyone felt need of this and tried !

p00j4 avatar Jan 21 '15 04:01 p00j4

@cbeust : i'm naive at this, a little idea will help me achieve the custom requirement and if this feature is straight forward added in lib will definitely make it more usable .

p00j4 avatar Feb 06 '15 10:02 p00j4

Using "ITestResult" also returns "testName" declared in testng xml file but not the java method called from the testMethod where the code had failed.

public void onTestFailure(ITestResult tr) {
    tr.getMethod().getMethodName().toString(); //returns testMethod name but not the method name from where onTestFailure is actuated
    tr.getMethod().getClass().getCanonicalName(); //returns class name
}

p00j4 avatar Apr 27 '15 07:04 p00j4

You can try: tr.getMethod().getConstructorOrMethod().getName()

juherr avatar Apr 27 '15 11:04 juherr

@juherr : this too returns "testBooking" the name of annoted method rather I'm looking for name like "homePage" or "searchPage" etc from wherever the call is transfered to the respective listener method (onTestFailure / onTestSuccess / onTestSkipped) and I'm wondering if its possible with TestNg, since on debugging I have found that "ITestResult" doesn't have the java method name throughout its life cycle [checked in Invoker.java->runTestListeners] [all the names which sound like methodName are actually pointing to @Test method names]

p00j4 avatar Apr 27 '15 12:04 p00j4

@p00j4 Could you create a little and runnable project? That will be easier to understand.

juherr avatar Apr 27 '15 12:04 juherr

@juherr : thanks for taking time out, here is the code- https://github.com/p00j4/customReoprt

test class listener implementation

p00j4 avatar Apr 27 '15 13:04 p00j4

Ok, I understand now. Maybe you could try something with result.getThrowable() but not sure if it is possible.

I never have to use it, but maybe FluentLenium could help you too.

juherr avatar Apr 28 '15 08:04 juherr

@p00j4 you can use this code inside any method- int size = Thread.currentThread().getStackTrace().length; System.out.println("size -"+size); String methodName = Thread.currentThread().getStackTrace()[size-29].getMethodName().toLowerCase(); //there are other 28 methods call so ignore them

This piece of code will always give you the method name which is running currently inside @Test method, like - homePage.

And to get the current method name where exactly test case got failed you can use below code- Thread.currentThread().getStackTrace()[1].getMethodName().toLowerCase();

sanjayselectorshub avatar Nov 02 '15 10:11 sanjayselectorshub