0

I want to run my Test methods multiple times based on a business logic. Is there a way to alter InvocationCount to achieve the same ? any other suggestions are also welcome.

Appu Mistri
  • 768
  • 8
  • 26

2 Answers2

4

You would need to basically leverage an IAnnotationTransformer for doing this.

Here's a sample that shows this in action.

The marker annotation which we are going to be using to indicate that a particular test method needs to be run more than once.

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

import static java.lang.annotation.ElementType.METHOD;

/**
 * A Marker annotation which is used to express the intent that a particular test method
 * can be executed more than one times. The number of times that a test method should be
 * iterated is governed by the JVM argument : <code>-Diteration.count</code>. The default value
 * is <code>3</code>
 */
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface CanRunMultipleTimes {
}

The test class looks like this.

import org.testng.annotations.Test;

import java.util.concurrent.atomic.AtomicInteger;

public class TestClassSample {
    private volatile AtomicInteger counter = new AtomicInteger(1);

    @CanRunMultipleTimes
    @Test
    public void testMethod() {
        System.err.println("Running iteration [" + counter.getAndIncrement() + "]");
    }
}

Here's how the annotation transformer looks like.

import org.testng.IAnnotationTransformer;
import org.testng.annotations.ITestAnnotation;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class SimpleAnnotationTransformer implements IAnnotationTransformer {
    @Override
    public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor, Method testMethod) {
        if (testMethod == null || testMethod.getAnnotation(CanRunMultipleTimes.class) == null) {
            return;
        }

        int counter = Integer.parseInt(System.getProperty("iteration.count", "3"));
        annotation.setInvocationCount(counter);
    }
}

Here's how the suite xml file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="46998341_Suite" verbose="2">
    <listeners>
        <listener class-name="com.rationaleemotions.stackoverflow.qn46998341.SimpleAnnotationTransformer"/>
    </listeners>
    <test name="46998341_Test">
        <classes>
            <class name="com.rationaleemotions.stackoverflow.qn46998341.TestClassSample"/>
        </classes>
    </test>
</suite>

Here's how the output would look like :

... TestNG 6.12 by Cédric Beust (cedric@beust.com)
...
Running iteration [1]
Running iteration [2]
Running iteration [3]
PASSED: testMethod
PASSED: testMethod
PASSED: testMethod

===============================================
    46998341_Test
    Tests run: 3, Failures: 0, Skips: 0
===============================================

===============================================
46998341_Suite
Total tests run: 3, Failures: 0, Skips: 0
===============================================
Krishnan Mahadevan
  • 14,121
  • 6
  • 34
  • 66
0

Can you do it in a class level. Thanks for the help, method level works perfect, just wondering if we can do for Class level also

I tried below but it didn't work. used TYPE

@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @Target({METHOD, TYPE}) public @interface CanRunMultipleTimes { }

sri
  • 55
  • 1
  • 1
  • 8
  • This does not provide an answer to the question. You can [search for similar questions](https://stackoverflow.com/search), or refer to the related and linked questions on the right-hand side of the page to find an answer. If you have a related but different question, [ask a new question](https://stackoverflow.com/questions/ask), and include a link to this one to help provide context. See: [Ask questions, get answers, no distractions](https://stackoverflow.com/tour). – Dwhitz Mar 26 '19 at 15:11