1

I have two classes: page1 and page2. From page2 I want to call a variable that ran in page1 that will be randomly chosen to be either "Internal" or "External", and make a determination from that whether to execute a few @test methods in my page2 class. I do not want any skipExceptions.

I want Something like this below. If the location equals "External" then it's expected that the page will not display certain features. In which, I want do not want the test cases for those missing features to be run.

if(page1.location.equals("External")){
    annotation.setEnabled(false);
}

I was following the example explained here: How to disable TestNG test based on a condition but I'm still not quite able to understand it. How do I apply it to a specific @Test and not a whole class?

Gautham M
  • 4,816
  • 3
  • 15
  • 37
Jeff B
  • 13
  • 3
  • It would probably be better if you explained the scenarios and what tests you want to run based on Page 1 state, etc. What you've described doesn't seem like a good way to go about this. Your scripts should be independent of each other and should not depend on each other's state. Things like that will break parallelism which will likely make running ALL the tests faster than only running certain tests based on state sequentially. – JeffC May 04 '21 at 21:57
  • I added some additional details. However, since the variable on page1 is randomly selecting "Internal" or "External" and not hard coded, It must be run and make the determination at run time as to whether or not the certain test cases on page2 should be executed or not. – Jeff B May 05 '21 at 00:36
  • @JeffB It is not possible using Annotation Transformer. Because the annotation transformer method is run before any of the test methods are run. Then only the tests are executed. Is it okay for you if the skipped test cases are marked as "success" in the test report? Then there is a solution. – Gautham M May 13 '21 at 13:10
  • @GauthamM Ideally, I don't want the skipped test cases to even show in the report at all. I was also thinking about the Annotation Transformer some more and what you said. What if I generate a random number between 1 or 2. If 1, then execute test path A. If 2, then execute test path B. If I do that in a BeforeSuite, would that work? If yes, I'm hoping to get a better explanation of the Annotation Transformer and how to execute it between two test paths. – Jeff B May 15 '21 at 01:00
  • @JeffB you need to have the random number logic in your annotation transformer. Because, the transformer is invoked even before `BeforeSuite`. – Gautham M May 15 '21 at 06:09

1 Answers1

0

The requirement in the comment is not possible using Annotation transformer. This is because the transformer is run before any test is run. This is done to finalize the annotations before test execution starts.

The field m_enabled is used to determine if the test method could be run or not. Even though you could change the m_enabled to false midway during test execution, it does not help as the test execution has reached a point where the tests that are to be run are already finalized and m_enabled is not checked afterwards.

So for this requirement, which disables a test method using the result of a different test such that the disabled test would not appear on the test report is not possible. But, based on your comment "What if I generate a random number between 1 or 2. If 1, then execute test path A. If 2, then execute test path B", in this case you could use the transformer to enable/disable certain methods because this logic is independent of any test result. For this you could define a transformer as follows:

public class MyTransformer implements IAnnotationTransformer {
    private final List<String> pathOneMethods = List.of("testA","testB");
    private final List<String> pathTwoMethods = List.of("testB","testC");

    private final Random r = new Random(); //java.util
    private final List<String> selectedPath;
    
    public MyTransformer() {
        selectedPath = (r.nextBoolean()) ? pathOneMethods : pathTwoMethods;
    }

    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        if(testMethod != null && !selectedPath.contains(testMethod.getName())) {
            annotation.setEnabled(false);
        }
    }

}

Annotation transformers cannot be included as part of @Listeners in the code. It has to be specified in the testng.xml as <listeners> inside the <suite> tag.

<suite>
    ................
    ................
    <listeners>
        <listener class-name = "com.code.MyTransformer"></listener>
    </listeners>    
    ................
    ................
</suite>

Gautham M
  • 4,816
  • 3
  • 15
  • 37
  • Thank you. I will try this. My only concern is I have about 100 test cases in each path. Is there a way to do this by class instead of testMethod? – Jeff B May 15 '21 at 20:37
  • @JeffB Put the class names in the those lists and instead of `testMethod.getName()` do `testMethod.getDeclaringClass().getName()` – Gautham M May 16 '21 at 01:56
  • @JeffB Also upvote and accept the answer if it solves the question – Gautham M May 16 '21 at 01:56