Я нашел похожий вопрос здесь , но это не то же самое.
Я использую Selenium и TestNG для создания теста.
Я реализовал TestNG Listerner, поэтому как в случае неудачи теста, так и в случае окончания теста sh я могу получить Chrome журнал браузера.
Когда я создаю экземпляр Chrome драйвера, я оборачиваю его в ThreadLocal, чтобы я мог использовать getter и setter, когда я хочу использовать экземпляр.
TestNg listerner выглядит так
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()
вернет экземпляр драйвера при вызове Listener OnTestFailure()
(идеально, именно то, что я хочу), но вернет null
когда Listener OnFinish()
вызывается (не то, что я хочу). Я не уничтожаю экземпляр драйвера (не используется ни метод quit()
, ни close()
).
Когда все @Test
fini sh успешно, прослушиватель OnFinish()
будет вызван, без исключений. Нет сообщения об ошибке. Тест завершится sh с зеленой галочкой. Все зеленые. Но я не получаю свой лог-файл. После некоторого устранения неполадок и работы в режиме отладки я обнаружил, что причиной root был экземпляр драйвера, равный NULL. Почему ноль?
Мне интересно, почему эти 2 метода Слушателя работают по-разному? Я подозреваю, что когда вызывается OnFinish()
, все тесты завершены, поэтому все экземпляры будут автоматически уничтожены сборщиком мусора? Может ли это быть причиной?
Я попытался вставить super.grablog()
в public void onTestSuccess(ITestResult result)
, и он также прекрасно работает. Только OnFinish()
работает по-другому.
Есть ли обходное решение для этой конкретной проблемы? Или что я мог сделать неправильно?
В другом посте кто-то предложил инициализировать драйвер в TestNG Listener. Я мог бы попробовать это позже, но я предпочитаю делать это в моем собственном классе (а не в Слушателе). Спасибо.
ОБНОВЛЕНИЕ 7 Янв:
Я создал новый класс с одним методом @AfterSuite
и переместил блок кода из Listener OnFinish()
в @AfterSuite
. Я перечислил новый класс в моем тесте. xml, поэтому он будет выполнен.
Я сталкиваюсь с той же проблемой, но на этот раз java.lang.NullPointerException
отображается на той же строке, вызванной той же самой причиной (new DriverManager().getDriverThread()
возвращает ноль).