Bạn cần phải cẩn thận khi nắm giữ các giá trị truyền vào người nghe như IInvokedMethodListener
như một thực hiện ngây thơ (kể cả những người trong câu trả lời hiện có) sẽ không được thread-safe. Vì TestNG có thể chạy thử nghiệm đồng thời, nên có thể xem giá trị được lưu trữ từ trình nghe của một thử nghiệm khác. Dưới đây là một ví dụ với hai bài kiểm tra, testA()
và testB()
:
beforeInvocation(testA)
cửa hàng testA
beforeInvocation(testB)
cửa hàng testB
ghi đè testA
testA()
lấy testB
(!!)
testB()
lấy testB
Lớp TestMethodCapture
dưới đây xử lý tình trạng cuộc đua này một cách chính xác bằng cách liên kết người nghe và thử nghiệm của nó thông qua một ThreadLocal
, đảm bảo rằng các thử nghiệm chạy đồng thời sẽ không ghi đè lên nhau.
Thậm chí tốt hơn, nó không giới hạn chỉ lấy tên của kiểm tra, nó giữ một tham chiếu đến cả ITestNGMethod
và ITestResult
trường hợp liên quan đến việc kiểm tra hiện hành, vì vậy bạn cũng có thể kiểm tra của phương pháp class, test groups, và parameters.
Bạn có thể sử dụng nó như vậy:
@Listeners(TestMethodCapture.class)
public class TestMethodCaptureTest {
@Test
public void fooBar() {
// will print "fooBar"
System.out.println(TestMethodCapture.getTestMethod().getMethodName());
}
}
Và đây là chính lớp:
/**
* Captures the currently executing test method so it can be accessed by the test,
* e.g. to retrieve the test method's name. This class is thread-safe.
*
* <p>Register this class as a
* <a href="http://testng.org/doc/documentation-main.html#testng-listeners">TestNG
* listener</a>, then access the method and result from test code with the static
* {@link #getTestMethod} and {@link #getTestResult} methods.
*
* <p>Annotating a test class with {@code @Listeners(TestMethodCapture.class)} is the
* suggested way to enable capturing if your test's correctness will depend on this
* listener being enabled.
*/
public class TestMethodCapture implements IInvokedMethodListener {
private static ThreadLocal<ITestNGMethod> currentMethods = new ThreadLocal<>();
private static ThreadLocal<ITestResult> currentResults = new ThreadLocal<>();
@Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
currentMethods.set(method.getTestMethod());
currentResults.set(testResult);
}
@Override
public void afterInvocation(IInvokedMethod method, ITestResult testResult) {
currentMethods.remove();
currentResults.remove();
}
public static ITestNGMethod getTestMethod() {
return checkNotNull(currentMethods.get(),
"Did you forget to register the %s listener?", TestMethodCapture.class.getName());
}
/**
* Parameters passed from a data provider are accessible in the test result.
*/
public static ITestResult getTestResult() {
return checkNotNull(currentResults.get(),
"Did you forget to register the %s listener?", TestMethodCapture.class.getName());
}
}
Nếu bạn không sử dụng Guava (tại sao không ??) bạn có thể thêm phương thức checkNotNUll()
như thế này để biên dịch:
private static <T> T checkNotNull(T o, String msg, Object param) {
if (o == null) {
throw new NullPointerException(String.format(msg, param));
}
return o;
}
Câu trả lời này rất cũ. Câu trả lời của Dmitry là câu trả lời đơn giản nhất đòi hỏi ít nỗ lực nhất. – gorbysbm