-1

I have @test methods in a class1 and @before method in super class. I wanted to get the class variable declared in class1 to be accessed in @before method.

3 Answers3

0

No. That is against the rules of inheritance. The super class is the parent class, and the class1 mentioned in your question is the child class.

The child class can access the attributes of the parent class , but vica - versa is not true. Here is a similar question with more explanation.

Mahima
  • 178
  • 8
0

The term "class variable" is used to denote static variables. I assume that you intended to discuss the use of "instance variables". If an instance variable is to be used in a parent class, then ideally it should be an instance variable of the parent class.

If you actually want to use a "class variable" (or static variable) of a child class in parent class then it is possible (if it has the relevant access modifier)

Gautham M
  • 4,816
  • 3
  • 15
  • 37
0

It is possible to access both the instance variable and a class variable using reflection. Though this is not a recommended way (as stated by comments shared).

You can use the already implemented dependency injection in testng using google's guice library for the @Before and @After hooks. Sharing an example of the same :


public class Test extends BaseTest {

    String stringOne = "INTER";
    static final String stringTwo = "MISSION";

    @Test(testName = "Sample Test")
    private void reflection_test() {
        System.out.println("-----INSIDE THE SUB CLASS-----");
        System.out.println(stringOne + stringTwo);
    }

}

Now in the @Before which is present in the base class, we add ITestResult as a param to the method (You can read about testng's dependency injection here).

Now using the ITestResult parameter, we can get the test class which can then be used to get the instantiated class object, fields, method, etc using Java reflection. Check the below example :

public class BaseTest {

    @BeforeMethod(alwaysRun = true)
    public void init(ITestResult result) throws IllegalAccessException {
        Class clazz = result.getTestClass().getRealClass();
        System.out.println("-----THIS IS FROM THE PARENT CLASS-----");
        for (Field f : clazz.getDeclaredFields()) {
            System.out.println("Variable Value : " + f.get(this));
        }
        System.out.println();
    }

}

On execution of the test, we'll receive this output :

-----THIS IS FROM THE PARENT CLASS-----
Variable Value : INTER
Variable Value : MISSION

-----INSIDE THE SUB CLASS-----
INTERMISSION
Techrookie89
  • 380
  • 3
  • 14
  • Is this really the output after running this code? – Gautham M May 16 '21 at 05:56
  • Here the fields of the child class are retrieved using the child object created as part of running the test. Breaking of inheritance rules are not happening. Also, you do not need reflection to achieve this. Just a simple `if(this instanceof ChildTest) System.out.println(((ChildTest) this).stringOne);`. Reflection is only helpful when all the fields are required so that you could do it in a loop. From the question, it seems like only a few fields are required. – Gautham M May 16 '21 at 06:14
  • Hey @GauthamM, yes the above output is from executing the code. It would be upto the OP on how many fields would he require to suite his cause (which caters using Reflection or a simple typecast based on instance type). Based on your comment I've made an edit removing the usage of inheritance in my answer. – Techrookie89 May 16 '21 at 06:34
  • Please note that this solution using `ITestResult` would not work for older versions of testNG like `6.8`. Because in such versions, the attributes in `ITestResult` would be null when it reaches BeforeMethod, which would cause the beforeMethod to fail. This has been fixed in newer versions. So i would recommend receiving `Method` as parameter and then using `clazz = method.getDeclaringClass()`. Or you could remove all the parameters and just use `clazz = this.getClass();` – Gautham M May 16 '21 at 08:26