Capture screenshot when Selenium test fails

Хочу делать скриншот при каждом фейле теста. У Селениума есть для этого методы, мне остаётся только определить момент, когда их вызвать. То есть момент, когда тест упал, а браузер ещё не закрылся. Я попробовал обернуть код теста в конструкцию try {} catch (Throwable) {} и это работает, но копипастить одинаковое тело catch во все полтысячи тестов выглядит тупо. Есть ли более элегантное, но не слишком сложное решение? Либо вообще другой подход к решению задачи?

Сделайте свой метод CaptureScreenshot и поставьте его обработчиком для exception-ов, например:

{syntaxhighlighter brush: csharp;fontsize: 100; first-line: 1; }driver = new FirefoxDriver(profile); webdriver = new EventFiringWebDriver(driver); webdriver.ExceptionThrown += CaptureScreenshot;{/syntaxhighlighter}

Тесты написаны на Селениум 1...

Вот такая реализация должна помочь.

{syntaxhighlighter brush: java;fontsize: 100; first-line: 1; }public static void obtainSnapshotIfNeed(ExtendedSelenium selenium, ITestResult result) { if (result == null) { return; } // skip if internal server (selenium) error if (result.getThrowable() != null && "Internal Server Error".equals(result.getThrowable().getMessage())) { return; }

	if (!result.isSuccess()) {
		obtainSnapshot(selenium, result);
	}
}

private static void obtainSnapshot(ExtendedSelenium selenium, ITestResult result) {
	String imageName = result.getTestClass().getName() + "." + result.getName();
	if (!new File(getCaptureScreenShotPath()).exists()) {
		new File(getCaptureScreenShotPath()).mkdirs();
	}
	String imagePath = getCaptureScreenShotPath() + imageName + ".png";
	try {
		String base64Screenshot = selenium.captureEntirePageScreenshotToString("background=#FFFFFF");
		byte[] decodedScreenshot = Base64.decodeBase64(base64Screenshot.getBytes());
		FileOutputStream fos = new FileOutputStream(new File(imagePath));
		fos.write(decodedScreenshot);
		fos.close();
		Reporter.log("<a href=\"file:///" + imagePath + "\">Screenshot " + imageName + "</a>");
		System.err.println("Screenshot Path " + imagePath);
	} catch (Exception e) {
		System.err.println("Couldn't save screenshot " + imageName + ": " + e.getMessage());
		e.printStackTrace();
	}
}{/syntaxhighlighter}</p><p>Вызов этого метода нужно делать в tearDown(). После прохождения теста.</p><p>{syntaxhighlighter brush: bash;fontsize: 100; first-line: 1; }@AfterTest(alwaysRun = true)

public void tearDown() {
obtainSnapshotIfNeed(selenium, result);
}{/syntaxhighlighter}

Спасибо за пример! Сделал немного другую реализацию с использованием тестового фреймворка TestNG, а именно реализацией интерфейса ITestListener - вызываю метод создания скриншота в его методе onTestFailure. Это как альтернатива tearDown и не нужна проверка !result.isSuccess() Smile

Да, через листенер тоже вариант  и я бы даже сказал более красивый. :) 

А можно вас попросить кинуть в эту ветку обсуждения пример реализации?

http://qtp-help.blogspot.com/2010/07/testng-take-screenshot-of-failed-test.html

Попробовал реализовать скриншоты так, как описано в http://qtp-help.blogspot.com/2010/07/testng-take-screenshot-of-failed-test.html
Однако при попытке снять скриншот вылазит ошибка java.lang.UnsupportedOperationException: captureScreenshot
Подскажите пожалуйста как её исправить.

потому что этот метод используется в Selenium RC, а для веб драйвера вам нужен приблизительно вот такой вот код

 

WebDriver driver = new FirefoxDriver();
driver.get("http://www.google.com/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// Now you can do whatever you need to do with it, for example copy somewhere
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));

На python реализовал вот так:

 

import sys
browser = webdriver.Firefox()
 
и в методе tearDown():
if sys.exc_info()[0]:
      browser.get_screenshot_as_file('screenshot-%s.png')

 

Я у себя делаю внутренними методами Java - так надежнее и не зависит от селениума . Могу дать  пример 

ну раз сказал, давай уже :)

 

Из  кода  выпилил  всякие проверки -  если  они вам будут нужны, то сами вставите  
 
Get the screen size
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenSize = toolkit.getScreenSize();
Rectangle rect = new Rectangle(0, 0, screenSize.width,
screenSize.height);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(rect);
File file;
 
// Save the screenshot as a jpg
Boolean b = new File(screenShotPatch).mkdir();
file = new File(screenShotName);
ImageIO.write(image, "jpg", file);

От робота отказался в свое время, ибо нервы не железные. На линуксе бесполезно использовать. Не умеет работать из-под демонов + танцы с бубном в случае хэдлес энваемент.

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