mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
fit test case name fetcher for gradle build
This commit is contained in:
parent
9ab737ce57
commit
1bf6ab3b21
@ -1,10 +0,0 @@
|
||||
package com.alibaba.testable.core.constant;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public final class ConstPool {
|
||||
|
||||
public static final String TEST_POSTFIX = "Test";
|
||||
|
||||
}
|
@ -108,7 +108,7 @@ public class InvokeVerifier {
|
||||
public InvokeVerifier times(int count) {
|
||||
if (lastVerification == null) {
|
||||
// when used independently, equals to `withTimes()`
|
||||
System.out.println("Warning: [" + TestableUtil.getPreviousStackLocation() + "] using \"times()\" method "
|
||||
System.out.println("Warning: [" + TestableUtil.previousStackLocation() + "] using \"times()\" method "
|
||||
+ "without \"with()\" or \"withInOrder()\" is not recommended, please use \"withTimes()\" instead.");
|
||||
return withTimes(count);
|
||||
}
|
||||
|
@ -1,27 +1,32 @@
|
||||
package com.alibaba.testable.core.util;
|
||||
|
||||
import com.alibaba.testable.core.constant.ConstPool;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author flin
|
||||
*/
|
||||
public class TestableUtil {
|
||||
|
||||
/**
|
||||
* [0]Thread.getStackTrace() → [1]currentSourceMethodName() → [2]MockMethod -> [3]SourceMethod
|
||||
*/
|
||||
private static final int INDEX_OF_SOURCE_METHOD = 3;
|
||||
/**
|
||||
* [0]Thread.getStackTrace() → [1]previousStackLocation() → [2]Invoker -> [3]Caller of invoker
|
||||
*/
|
||||
private static final int INDEX_OF_CALLER_METHOD = 3;
|
||||
/**
|
||||
* Just a special number to identify test worker thread
|
||||
*/
|
||||
private static final int TEST_WORKER_THREAD_PRIORITY = 55555;
|
||||
|
||||
/**
|
||||
* Get the last visit method in source file
|
||||
* @param testClassRef usually `this` variable of the test class
|
||||
* @return method name
|
||||
*/
|
||||
public static String currentSourceMethodName(Object testClassRef) {
|
||||
Class<?> testClass = testClassRef.getClass();
|
||||
String testClassName = getRealClassName(testClass);
|
||||
String sourceClassName = testClassName.substring(0, testClassName.length() - ConstPool.TEST_POSTFIX.length());
|
||||
String sourceMethod = findLastMethodFromSourceClass(sourceClassName, getMainThread().getStackTrace());
|
||||
if (sourceMethod.isEmpty()) {
|
||||
return findLastMethodFromSourceClass(sourceClassName, Thread.currentThread().getStackTrace());
|
||||
}
|
||||
return sourceMethod;
|
||||
return Thread.currentThread().getStackTrace()[INDEX_OF_SOURCE_METHOD].getMethodName();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -31,7 +36,7 @@ public class TestableUtil {
|
||||
*/
|
||||
public static String currentTestCaseName(Object testClassRef) {
|
||||
Class<?> testClass = testClassRef.getClass();
|
||||
String testClassName = getRealClassName(testClass);
|
||||
String testClassName = getOuterClassName(testClass.getName());
|
||||
return currentTestCaseName(testClassName);
|
||||
}
|
||||
|
||||
@ -41,10 +46,28 @@ public class TestableUtil {
|
||||
* @return method name
|
||||
*/
|
||||
public static String currentTestCaseName(String testClassName) {
|
||||
String testCaseName = findFirstMethodFromTestClass(testClassName, getMainThread().getStackTrace());
|
||||
// try current thread
|
||||
String testCaseName = findFirstMethodFromTestClass(testClassName, Thread.currentThread().getStackTrace());
|
||||
if (testCaseName.isEmpty()) {
|
||||
return findFirstMethodFromTestClass(testClassName, Thread.currentThread().getStackTrace());
|
||||
Set<Thread> threads = Thread.getAllStackTraces().keySet();
|
||||
// try find previously marked thread
|
||||
Thread testWorkerThread = findTestWorkerThread(threads);
|
||||
if (testWorkerThread != null) {
|
||||
testCaseName = findFirstMethodFromTestClass(testClassName, testWorkerThread.getStackTrace());
|
||||
if (!testCaseName.isEmpty()) {
|
||||
return testCaseName;
|
||||
}
|
||||
}
|
||||
// travel all possible threads
|
||||
for (Thread t : threads) {
|
||||
testCaseName = findFirstMethodFromTestClass(testClassName, t.getStackTrace());
|
||||
if (!testCaseName.isEmpty()) {
|
||||
t.setPriority(TEST_WORKER_THREAD_PRIORITY);
|
||||
return testCaseName;
|
||||
}
|
||||
}
|
||||
}
|
||||
System.err.println("testCaseName: " + testCaseName);
|
||||
return testCaseName;
|
||||
}
|
||||
|
||||
@ -52,44 +75,45 @@ public class TestableUtil {
|
||||
* Get file name and line number of where current method was called
|
||||
* @return in "filename:linenumber" format
|
||||
*/
|
||||
public static String getPreviousStackLocation() {
|
||||
// 0 - Thread.getStackTrace(), 1 - this method, 2 - code call this method, 3 - code call the caller method
|
||||
StackTraceElement stack = getMainThread().getStackTrace()[3];
|
||||
public static String previousStackLocation() {
|
||||
StackTraceElement stack = Thread.currentThread().getStackTrace()[INDEX_OF_CALLER_METHOD];
|
||||
return stack.getFileName() + ":" + stack.getLineNumber();
|
||||
}
|
||||
|
||||
private static String findLastMethodFromSourceClass(String sourceClassName, StackTraceElement[] stack) {
|
||||
for (StackTraceElement element : stack) {
|
||||
if (element.getClassName().equals(sourceClassName)) {
|
||||
return element.getMethodName();
|
||||
private static Thread findTestWorkerThread(Set<Thread> threads) {
|
||||
for (Thread t : threads) {
|
||||
if (t.getPriority() == TEST_WORKER_THREAD_PRIORITY) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String findFirstMethodFromTestClass(String testClassName, StackTraceElement[] stack) {
|
||||
for (int i = stack.length - 1; i >= 0; i--) {
|
||||
if (stack[i].getClassName().equals(testClassName)) {
|
||||
return stack[i].getMethodName();
|
||||
if (getOuterClassName(stack[i].getClassName()).equals(testClassName)) {
|
||||
return stack[i].getClassName().indexOf('$') > 0 ?
|
||||
// test case using async call
|
||||
getMethodNameFromLambda(stack[i].getClassName()) :
|
||||
// in case of lambda method
|
||||
getMethodNameFromLambda(stack[i].getMethodName());
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String getRealClassName(Class<?> testClass) {
|
||||
String className = testClass.getName();
|
||||
int posOfInnerClass = className.lastIndexOf('$');
|
||||
private static String getMethodNameFromLambda(String originName) {
|
||||
int beginOfMethodName = originName.indexOf('$');
|
||||
if (beginOfMethodName < 0) {
|
||||
return originName;
|
||||
}
|
||||
int endOfMethodName = originName.indexOf('$', beginOfMethodName + 1);
|
||||
return originName.substring(beginOfMethodName + 1, endOfMethodName);
|
||||
}
|
||||
|
||||
private static String getOuterClassName(String className) {
|
||||
int posOfInnerClass = className.indexOf('$');
|
||||
return posOfInnerClass > 0 ? className.substring(0, posOfInnerClass) : className;
|
||||
}
|
||||
|
||||
private static Thread getMainThread() {
|
||||
for (Thread t : Thread.getAllStackTraces().keySet()) {
|
||||
if (t.getId() == 1L) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
// usually impossible to go here
|
||||
return Thread.currentThread();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.alibaba.testable.core.util;
|
||||
|
||||
import com.alibaba.testable.core.accessor.PrivateAccessor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TestableUtilTest {
|
||||
|
||||
@Test
|
||||
void should_get_outer_class_name() {
|
||||
assertEquals("com.alibaba.testable.demo.DemoMockTest",
|
||||
PrivateAccessor.<String>invokeStatic(TestableUtil.class, "getOuterClassName", "com.alibaba.testable.demo.DemoMockTest$should_able_to_get_source_method_name$1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_get_async_method_name_from_inner_class_name() {
|
||||
assertEquals("should_able_to_get_source_method_name",
|
||||
PrivateAccessor.<String>invokeStatic(TestableUtil.class, "getAsyncMethodName", "com.alibaba.testable.demo.DemoMockTest$should_able_to_get_source_method_name$1"));
|
||||
assertEquals("should_able_to_get_source_method_name",
|
||||
PrivateAccessor.<String>invokeStatic(TestableUtil.class, "getAsyncMethodName", "lambda$should_able_to_get_source_method_name$0"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user