Слушатель TestNG onFini sh (контекст ITestContext) не может получить экземпляр ThreadLocal (возвращает ноль), НО onTestFailure (результат ITestResult) работает нормально - PullRequest
2 голосов
/ 06 января 2020

Я нашел похожий вопрос здесь , но это не то же самое.

Я использую 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() возвращает ноль).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...