How to check if a Test has failed using JUnit?
This blog introduces the JUnit TestWatcher Class. We can use this to detect the Status of a Test Case, and if it has failed, we can then invoke a Method to do something – in this case, report the error and take a screenshot.
There are other approaches to this, but the approach detailed here would be used instead of the usual JUnit @After annotation, and is useful as it will be invoked on any error.
The TestWatcher class Methods
Method | Use |
---|---|
succeeded | Invoked when a test succeeds |
failed | Invoked when a test fails |
skipped | Invoked when a test is skipped due to a failed assumption. |
starting | Invoked when a test is about to start |
finished | Invoked when a test method finishes (whether passing or failing) |
more details about the TestWatcher Class can be found at: https://junit.org/junit4/javadoc/4.12/org/junit/rules/TestWatcher.html
Example Script
So here is an example with two test cases, using the @Before and @Test JUnit annotations, but instead of an @After block, we will use the TestWatcher finished Method instead.
This example uses Selenium WebDriver & JUnit
/* * Example of using the TestWatcher Class to capture a screenshot if * a Test case fails * https://junit.org/junit4/javadoc/4.12/org/junit/rules/TestWatcher.html */ package simplewd; import static org.junit.Assert.*; import java.io.File; import java.io.IOException; import javax.swing.JFileChooser; import org.junit.Before; import org.junit.Test; import org.junit.Rule; import org.junit.rules.TestRule; import org.junit.rules.TestWatcher; import org.junit.runners.model.Statement; import org.junit.runner.Description; import org.openqa.selenium.By; import org.openqa.selenium.OutputType; import org.openqa.selenium.TakesScreenshot; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.io.FileHandler; public class SimpleJUWDTest { WebDriver driver; @Rule public final TestRule watchman = new TestWatcher() { @Override public Statement apply(Statement base, Description description) { return super.apply(base, description); } // This method gets invoked if the test fails for any reason: @Override protected void failed(Throwable e, Description description) { // Print out the error message: System.out.println(description.getDisplayName() + " " + e.getClass().getSimpleName() + "\n"); // Now you can do whatever you need to do with it, for example take a screenshot File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); try { File currPath = new File(new JFileChooser().getFileSystemView().getDefaultDirectory().toString() + "\\screenshot.png"); System.out.println("Screenshot at: " + currPath.toString()); FileHandler.copy(scrFile, currPath ); } catch (IOException e1) { e1.printStackTrace(); } } // This method gets called when the test finishes, regardless of status // If the test fails, this will be called after the method above @Override protected void finished(Description description) { if (driver != null) driver.quit(); } }; @Before public void setUp() throws Exception { driver = new ChromeDriver(); //instantiate a browser driver.get("https://www.edgewordstraining.co.uk/webdriver2"); } @Test public void test() throws InterruptedException { driver.findElement(By.partialLinkText("Login")).click(); driver.findElement(By.id("username")).sendKeys("Edgewords"); driver.findElement(By.id("password")).sendKeys("edgewords123"); driver.findElement(By.linkText("Submit")).click(); Thread.sleep(2000); assertTrue (driver.findElement(By.linkText("Add Record")).isDisplayed()); } @Test public void nextTest() { System.out.println("This is test two"); assertTrue (true); } }
Obviously, in the real-world we could add this TestWatcher to a Base Class, and then inherit into our Test Classes, just like we would with the @Before and @After blocks, so we would only have to write this code once.
About Edgewords
Edgewords is a Training provider, specializing in Automated Testing Tools.
For Selenium WebDriver Java Training, please see our Selenium Training Pages