Как добавить реализацию сделать скриншот теста в TestWatcher JUnit 5

Добрый День коллеги. Нужна ваша помощь, а лучше направить к решение дабы сделать самому.
Вопрос будет больше связан с java, не могу понять как сделать правильно или воообще это можно сделать.

Стек: Java, JUnit5, Playwright, Gradle.
Проблема:
Сделать реализацию добавление скриншота когда тест упал в CustomWatcher implements TestWatcher.

Рассмотрим пример в виде скринов дабы было более понятно:

  1. BaseTest - класс который есть родителем для всех тестов.

    • Добавлен Extension → CustomWatcher который implements TestWatcher - где реализуется метод testFailed в котором собственно нужно реализовать сделать скриншот.
  2. CustomWatcher

// New instance for each test method.
public BrowserContext browserContext;

browserContext - создается для каждого теста свой.

Вопрос.
Как передать ссылку browserContext в CustomWatcher дабы сделать скриншот.

Как уже выше говорил тут вопрос больше к java, у меня не хватает навыков найти решение данной проблемы.

Возможно кто то из вас подскажет куда копать дабы я сам пришел к этому.

Заранее спасибо.

static interface ExtensionContext.Store Store provides methods for extensions to save and retrieve data.
[getStore]

https://junit.org/junit5/docs/5.3.0/api/org/junit/jupiter/api/extension/ExtensionContext.html

передавайте browserContext через него

в тестнг похожее называется ITestcontext

https://www.swtestacademy.com/testng-itestcontext-example/

1 лайк

Добрый День.
Буду пробовать, спасибо

да все так и получается

через
org.junit.jupiter.api.extension.ExtensionContext.getRequiredTestInstance() и рефлексию
и
org.junit.jupiter.api.extension.ExtensionContext.Store.getOrDefault(Object key, Class<String> requiredType, String defaultValue) - второй вариант у меня получился наполовину но может потом отлажу

1 лайк

Вот делал в своё время
https://github.com/pbezpal/testing-roschat-ms/blob/master/src/test/java/chat/ros/testing2/WatcherTests.java

1 лайк

Благодарю за ваш ответ.
Как сделать сам скрин и прикрепить в аллюр это ясно. Мой вопрос был чуток в другом. Но все же спасибо что не прошли мимо.

Ага понял, не дочитал) Я вижу это так:
Сделать класс с переменной, в которой будет храниться значение browserContext, пока выполняется тест
Если тест падает, то вытаскиваете значение browserContext в CustomWatcher.

Т.е, что-то такое

public class BrowserContextTemp {
   private BrowserContext bContext;
   
   public static setBrowserContext(BrowserContext context) {
       bContext = context;
   }

   public static getBrowserContext() {
       return bContext;
   }
}

Ну а дальше в BaseTest вызываешь функцию

BrowserContextTemp.setBrowserContext(browserContext)

А в CustomWatcher получаешь значение, если тест упал

BrowserContext context = BrowserContextTemp.getBrowserContext()

спасибо

ваш пример по моему про немного другое чем в вопросе

@pbezpal5
Ваш Вариант с классом static переменной работает.

  1. Нужно проверить как это будет работать при параллельном запуске при разных потоках.
  2. ExtensionContext.Store.(JUnit 5) - тоже вариант использовать но тут по тяжелее будет с реализацией.

Спасибо!!!

Можно использовать фреймворк lombok, тогда не нужно будет даже писать геттер и сеттер

По идее должно работать корректно при параллельном запуске

lombok - да в курсе, с этой библиотекой работаю постоянно.
Сейчас проверяю как будет при параллельном запуске при разных потоках.
Еще раз вам спасибо что не прошли мимо.
Хорошего Вам вечера.

@sergueik Вам также спасибо.

1 лайк

Спасибо, взаимно)

в своей вариант я использовал

Object testClass = context.getRequiredTestInstance();
		methodName = "getDriver";
		try {
			Method getDriver = testClass.getClass().getMethod(methodName);
			getDriver.setAccessible(true);
			driver = (WebDriver) getDriver.invoke(null);
			LOG.info("driver url is " + driver.getCurrentUrl());
		} catch (InvocationTargetException | NoSuchMethodException
				| SecurityException | IllegalAccessException
				| IllegalArgumentException e) {
			LOG.info("failed to invoke static method");
		}

		LOG.info("Test Failed for test {}: arg {}", context.getDisplayName(), arg);
		if (driver != null) {
			TakesScreenshot screenshot = ((TakesScreenshot) driver);

			File screenshotFile = screenshot.getScreenshotAs(OutputType.FILE);
				String filename = String.format("c:\\temp\\test%02d.jpg", cnt);
				FileUtils.copyFile(screenshotFile, new File(filename));

1 лайк

Спасибо