java - TestNG Listener onFinish(ITestContext context) 无法获取 ThreadLocal 实例(它返回 null)但 onTestFailure(ITestResult result) 工作正常
问题描述
我在这里发现了一个类似的问题,但不一样。
我使用 Selenium 和 TestNG 创建测试。
我实现了 TestNG Listerner,所以在测试失败和测试完成的情况下,我都可以获取 Chrome 浏览器日志。
当我实例化 Chrome 驱动程序时,我将它包装在一个 ThreadLocal 中,以便在我想使用实例时可以使用 getter 和 setter。
TestNg 监听器看起来像这样
public class MyListeners extends TestBase implements ITestListener, ISuiteListener {
@Override
public void onStart(ISuite suite) {
}
@Override
public void onFinish(ISuite suite) {
}
@Override
public void onTestStart(ITestResult result) {
}
@Override
public void onTestSuccess(ITestResult result) {
}
@Override
public void onTestFailure(ITestResult result) {
//I set the attribute "browser" in @Test with value "chrome" so this following block will be run
if (result.getAttribute("browser").equals("chrome")) {
super.grablog(); //Works perfectly fine
}
}
@Override
public void onTestSkipped(ITestResult result) {
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
}
@Override
public void onStart(ITestContext context) {
}
@Override
public void onFinish(ITestContext context) {
int numberOfFailedTest = context.getFailedTests().size();
if (numberOfFailedTest == 0) {
//No Test Fails
//Just a method to know which browser is used
String usedBrowser = null;
Set < ITestResult > passedTest = context.getPassedTests().getAllResults();
Iterator < ITestResult > i = passedTest.iterator();
if (i.hasNext()) {
usedBrowser = i.next().getAttribute("browser").toString();
}
//I set the attribute "browser" in @Test with value "chrome" so this following block will be run
if (usedBrowser.equals("chrome")) {
super.grablog(); // Will not work
}
}
}
}
这个 Listener 类有超类 TestBase,看起来像这样
public class TestBase {
public void initiate(String browser, String URL) throws InterruptedException {
//Initiating Chrome Driver , usual standard procedur
if (browser.equals("chrome")) {
System.setProperty("webdriver.chrome.driver", System.getProperty("user.dir") + "\\src\\test\\resources\\executeable\\chromedriver.exe");
DesiredCapabilities caps = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
caps.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
ChromeOptions options = new ChromeOptions();
options.addArguments("start-maximized");
options.merge(caps);
driver = new ChromeDriver(options);
}
//Wrap the initiated driver to our local Thread
DriverManager.setDriverThread(this.driver);
DriverManager.getDriverThread().manage().window().maximize();
DriverManager.getDriverThread().get(URL);
}
public void grablog() {
Grablog grablog = new Grablog();
grablog.grabbing();
}
}
管理驱动线程的 Driver 类
public class DriverManager {
private static ThreadLocal < WebDriver > driverThread = new ThreadLocal < > ();
public static WebDriver getDriverThread() {
return driverThread.get();
}
public static void setDriverThread(WebDriver driver) {
driverThread.set(driver);
}
}
在我的@Test
课堂上,我调用initiate()
来启动 Chrome 浏览器initiate("chrome", "www.website.com");
(否则,浏览器将无法启动)。
令人困惑的部分在这里。
public class Grablog {
//When TestNG Listener onFinish invoke this grabbing() , then new DriverManager().getDriverThread() will return null (bad)
//When TestNG Listener onTestFailure invoke this grabbing() , then new DriverManager().getDriverThread() will return a driver instance (good)
public void grabbing() {
LogEntries logEntries = new DriverManager().getDriverThread().manage().logs().get(LogType.BROWSER);
//
//Some codes here to save the log to a txt file
//
}
}
new DriverManager().getDriverThread()
将在调用侦听器时返回驱动程序实例OnTestFailure()
(完美,正是我想要的),但在调用null
侦听器时将返回OnFinish()
(不是我想要的)。我不杀死驱动程序实例(不使用quit()
也不close()
使用方法)。
全部成功完成后,将调用@Test
监听器,不抛出异常。OnFinish()
没有抛出错误信息。测试将以绿色勾号结束。全是绿色的。但我没有得到我的日志文件。经过一些故障排除并在调试模式下运行,我发现根本原因是驱动程序实例为空。为什么为空?
我想知道,为什么这两种 Listener 方法的工作方式不同?我怀疑,当OnFinish()
被调用时,所有测试都已完成,因此所有实例都会被垃圾收集器自动销毁?这可能是原因吗?
我试着把它放进去super.grablog()
,public void onTestSuccess(ITestResult result)
它也很好用。只是OnFinish()
工作方式不同。
是否有针对此特定问题的解决方法?或者我可能会做错什么?
在其他帖子中,有人建议在 TestNG Listener 中初始化驱动程序。我稍后可能会尝试,但我更喜欢在我自己的课堂上(而不是在 Listener 中)这样做。谢谢。
1 月 7 日更新:
我用一种方法创建了一个新类,@AfterSuite
并将代码块Listener OnFinish()
从@AfterSuite
. 我在 testng.xml 中列出了新类,因此它将被执行。
我遇到了同样的问题,但这次java.lang.NullPointerException
是由于相同的原因导致的完全相同的行(new DriverManager().getDriverThread()
返回 null)。
解决方案
推荐阅读
- c# - 将 FSharpFun 从 C# 传递到 F#
- javascript - 创建取消按钮...如何在 Node/Express.js 中完全中止请求
- azure - Azure:如何在不重新启动应用服务的情况下重新加载环境变量
- swift - Siri Intent Suggested Invocation Phrase 未显示在 ShortcutViewController 中
- c++ - 当我无法启动 CLR 时如何在 C++ 中重新启动 CLR?
- java - 验证用户输入 UUID
- reactjs - 如何在不使用包装器的情况下在 React 中呈现字符串数组?
- llvm - LLVM IR 中函数名后面的“.number”是什么意思?
- java - Importing pom in dependency management
- oracle - Oracle - '表达式类型错误'返回包中记录类型的表