With browser tests, it can often be challenging to track down the issue that caused a failure. By itself a failure message along with a stack trace is hardly enough to go on. Especially when you run the test again and it passes.
A simple way to gain insight into your test failures is to capture screenshots at the moment of a failure. And it’s a quick and easy thing to add to your tests.
Let’s dig in with an example.
Example
Java
// filename: Screenshot.java
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;
public class Screenshot {
WebDriver driver;
@Before
public void setUp() throws Exception {
driver = new FirefoxDriver();
}
@Rule
public TestRule watcher = new TestWatcher() {
@Override
protected void failed(Throwable throwable, Description description) {
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
try {
FileUtils.copyFile(scrFile,
new File("failshot_"
+ description.getClassName()
+ "_" + description.getMethodName()
+ ".png"));
} catch (IOException exception) {
exception.printStackTrace();
}
}
@Override
protected void finished(Description description) {
driver.quit();
}
};
@Test
public void OnError() {
driver.get("http://the-internet.herokuapp.com");
assertThat(false, is(true));
}
}
Python
# filename: screenshot.py
import sys
import unittest
from selenium import webdriver
class ScreenShotOnFailure(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
def tearDown(self):
if sys.exc_info()[0]:
self.driver.save_screenshot("failshot_%s.png" % self._testMethodName)
self.driver.quit()
def test_example_1(self):
driver = self.driver
driver.get('http://the-internet.herokuapp.com')
assert driver.title == 'blah blah blah'
if __name__ == "__main__":
unittest.main()
Ruby
# filename: screenshot.rb
require 'selenium-webdriver'
require 'rspec/expectations'
include RSpec::Matchers
def setup
@driver = Selenium::WebDriver.for :firefox
end
def teardown
@driver.quit
end
def run
setup
begin
yield
rescue RSpec::Expectations::ExpectationNotMetError => error
puts error.message
@driver.save_screenshot "./#{Time.now.strftime("failshot__%d_%m_%Y__%H_%M_%S")}.png"
end
teardown
end
run do
@driver.get 'http://the-internet.herokuapp.com'
expect(@driver.find_element(css: 'h1').text).to eql 'blah blah blah'
end
C#
// filename: Screenshot.cs
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
using System.Drawing.Imaging;
public class Screenshot
{
IWebDriver Driver;
[SetUp]
public void SetUp()
{
Driver = new FirefoxDriver();
}
[TearDown]
public void TearDown()
{
if (TestContext.CurrentContext.Result.Outcome.Status.Equals(TestStatus.Failed))
TakeScreenshot();
Driver.Quit();
}
private void TakeScreenshot()
{
string SaveLocation = @"C:\Tempquot; +
"failshot_" +
TestContext.CurrentContext.Test.FullName +
".png";
ITakesScreenshot ScreenshotDriver = (ITakesScreenshot) Driver;
ScreenshotDriver.GetScreenshot().SaveAsFile(SaveLocation, ImageFormat.Png);
}
[Test]
public void ScreenShotOnFailure()
{
Driver.Navigate().GoToUrl("http://the-internet.herokuapp.com");
Assert.That(false.Equals(true));
}
}
When you save this file and run it here is what will happen:
- Open the browser
- Visit the page
- Fail
- Capture a screenshot in the current working directory with the name
failshot_Screenshot_OnError.png
- Close the browser