0

Background

I have the following situation:

  • My test-classes implement org.testng.ITest
  • They all have a Helper containing info on the current test environment (e.g. device-under-test)

For example:

com.company.appundertest.Helper h;

public class TestClass implements org.testng.ITest {
    private String testName;

    //Helper is initialized externally in Factory + DataProvider 
    //and passed to Constructor.
    public TestClass(com.company.appundertest.Helper hh) {

    this.h = hh;

    //constructor sets the test-name dynamically
    //to distinguish multiple parallel test runs.
    this.testName = "some dynamic test name";
    }

    @Override
    public String getTestName() {
        return this.testName;
    }

    @Test
    public void failingTest() {
        //test that fails...
    }
}
  • These test-classes are executed in parallel using Factory and parallel data-provider.
  • Upon Test Failure, I need to access variables within the Helper instance of the failing test-class. These will be used to identify the environment at the point of failure (e.g. take screenshot on failing device).

This problem essentially boils down to:

How would I access fields within the TestNG test-class?

References

Community
  • 1
  • 1
Vish
  • 2,144
  • 5
  • 25
  • 48

2 Answers2

1

Here's an example method. You can insert this in a Test Listener class (which extends TestListenerAdapter)

public class CustomTestNGListener extends TestListenerAdapter{

//accepts test class as parameter.
//use ITestResult#getInstance()

private void getCurrentTestHelper(Object testClass) {
        Class<?> c = testClass.getClass();
        try {
            //get the field "h" declared in the test-class.
            //getDeclaredField() works for protected members.
            Field hField = c.getDeclaredField("h");

            //get the name and class of the field h.
            //(this is just for fun)
            String name = hField.getName();
            Object thisHelperInstance = hField.get(testClass);
            System.out.print(name + ":" + thisHelperInstance.toString() + "\n");

            //get fields inside this Helper as follows:
            Field innerField = thisHelperInstance.getClass().getDeclaredField("someInnerField");

            //get the value of the field corresponding to the above Helper instance.
            System.out.println(innerField.get(thisHelperInstance).toString());

        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

}
}

Call this as follows:

@Override
public void onTestFailure(ITestResult tr) {
        getCurrentTestHelper(tr.getInstance());
}
Vish
  • 2,144
  • 5
  • 25
  • 48
0

The @Vish 's solution is good, but you can avoid reflection with:

interface TestWithHelper {
   Helper getHelper();
}

where your TestClass will implement it. Then:

private void getCurrentTestHelper(Object testClass) {
  if (testClass instanceof TestWithHelper) {
    Helper helper = ((TestWithHelper) testClass).getHelper();
    ...
  }
}
juherr
  • 5,640
  • 1
  • 21
  • 63