package test;
import com.google.common.base.Joiner;
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// TODO replace other test IInvokedMethodListener by this one
public class InvokedMethodNameListener implements IInvokedMethodListener, ITestListener {
private final List<String> foundMethodNames = new ArrayList<>();
private final List<String> invokedMethodNames = new ArrayList<>();
private final List<String> failedMethodNames = new ArrayList<>();
private final List<String> failedBeforeInvocationMethodNames = new ArrayList<>();
private final List<String> skippedMethodNames = new ArrayList<>();
private final List<String> skippedAfterInvocationMethodNames = new ArrayList<>();
private final List<String> succeedMethodNames = new ArrayList<>();
private final Map<String, ITestResult> results = new HashMap<>();
private final Map<Class<?>, List<String>> mapping = Maps.newHashMap();
private final boolean skipConfiguration;
private final boolean wantSkippedMethodAfterInvocation;
public InvokedMethodNameListener() {
this(false);
}
public InvokedMethodNameListener(boolean skipConfiguration) {
this(skipConfiguration, false);
}
public InvokedMethodNameListener(boolean skipConfiguration, boolean wantSkippedMethodAfterInvocation) {
this.skipConfiguration = skipConfiguration;
this.wantSkippedMethodAfterInvocation = wantSkippedMethodAfterInvocation;
}
@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
if (!(skipConfiguration && method.isConfigurationMethod())) {
invokedMethodNames.add(getName(testResult));
}
}
@Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
List<String> methodNames = mapping.get(testResult.getMethod().getRealClass());
if (methodNames == null) {
methodNames = Lists.newArrayList();
mapping.put(testResult.getMethod().getRealClass(), methodNames);
}
methodNames.add(method.getTestMethod().getMethodName());
String name = getName(testResult);
switch (testResult.getStatus()) {
case ITestResult.FAILURE:
if (!(skipConfiguration && method.isConfigurationMethod())) {
failedMethodNames.add(name);
}
break;
case ITestResult.SKIP:
if (!(skipConfiguration && method.isConfigurationMethod())) {
if (wantSkippedMethodAfterInvocation) {
skippedAfterInvocationMethodNames.add(name);
} else {
throw new IllegalStateException("A skipped test is not supposed to be invoked");
}
}
break;
case ITestResult.SUCCESS:
if (!(skipConfiguration && method.isConfigurationMethod())) {
succeedMethodNames.add(name);
}
break;
default:
throw new AssertionError("Unexpected value: " + testResult.getStatus());
}
}
@Override
public void onTestStart(ITestResult result) {
foundMethodNames.add(getName(result));
}
@Override
public void onTestSuccess(ITestResult result) {
String name = getName(result);
results.put(name, result);
if (!succeedMethodNames.contains(name)) {
throw new IllegalStateException("A succeed test is supposed to be invoked");
}
}
@Override
public void onTestFailure(ITestResult result) {
String name = getName(result);
results.put(name, result);
if (!failedMethodNames.contains(name)) {
failedBeforeInvocationMethodNames.add(name);
}
}
@Override
public void onTestSkipped(ITestResult result) {
String name = getName(result);
results.put(name, result);
if (!skippedAfterInvocationMethodNames.contains(name)) {
skippedMethodNames.add(name);
}
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
String name = getName(result);
results.put(name, result);
if (!succeedMethodNames.contains(name) || !failedMethodNames.contains(name)) {
throw new IllegalStateException("A FailedButWithinSuccessPercentage test is supposed to be invoked");
}
}
@Override
public void onStart(ITestContext context) {
}
@Override
public void onFinish(ITestContext context) {
}
private static String getName(ITestResult result) {
String testName = result.getName();
String methodName = result.getMethod().getConstructorOrMethod().getName();
String name;
if (testName.contains(methodName)) {
name = methodName;
} else {
name = testName + "#" + methodName;
}
if (result.getParameters().length != 0) {
name = name + "(" + Joiner.on(",").useForNull("null").join(getParameterNames(result.getParameters())) + ")";
}
return name;
}
private static List<String> getParameterNames(Object[] parameters) {
List<String> result = new ArrayList<>(parameters.length);
for (Object parameter : parameters) {
if (parameter == null) {
result.add("null");
} else {
if (parameter instanceof Object[]) {
result.add("[" + Joiner.on(",").useForNull("null").join((Object[]) parameter) + "]");
} else {
result.add(parameter.toString());
}
}
}
return result;
}
public List<String> getInvokedMethodNames() {
return Collections.unmodifiableList(invokedMethodNames);
}
public List<String> getFailedMethodNames() {
return Collections.unmodifiableList(failedMethodNames);
}
public List<String> getSkippedMethodNames() {
return Collections.unmodifiableList(skippedMethodNames);
}
public List<String> getSucceedMethodNames() {
return new ArrayList<>(succeedMethodNames);
}
public List<String> getFailedBeforeInvocationMethodNames() {
return Collections.unmodifiableList(failedBeforeInvocationMethodNames);
}
public List<String> getSkippedAfterInvocationMethodNames() {
return Collections.unmodifiableList(skippedAfterInvocationMethodNames);
}
public ITestResult getResult(String name) {
return results.get(name);
}
public List<String> getMethodsForTestClass(Class<?> testClass) {
return mapping.get(testClass);
}
}