- custom and
- cumulative
The TestWatcher JUNIT class allows overriding the failed() and succeeded() JUNIT methods that are called automatically when tests fail or pass.
Custom code can be added to the overriding methods for storing the tests names and their pass/fail status in HTML files.
Test results are displayed visually by default
Lets start with a simple test class with 4 tests:
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestClass {
@Test
public void testScript1() {
assertTrue(1 < 2);
}
@Test
public void testScript2() {
assertTrue(1 > 2);
}
@Test
public void testScript3() {
assertTrue(1 < 2);
}
@Test
public void testScript4() {
assertTrue(1 > 2);
}
}
When the test class is executed, we will get the following results:
- testScript1 and testScript3: Pass
- testScript2 and testScript4: Fail
There is no option of exporting the execution results to a file.
Use the TestWatcher JUNIT class for getting the pass/fail status for each test
When a test passes or fails during execution phase, the failed() and succeeded() JUNIT methods are being invoked automatically.
The TestWatcher JUNIT class allows overriding the following methods:
- protected void failed(Throwable e, Description description)
failed() method is invoked when a test fails
- protected void finished(Description description)
finished() method is invoked when a test method finishes (whether passing or failing)
- protected void skipped(AssumptionViolatedException e, Description description)
skipped() method is invoked when a test is skipped due to a failed assumption.
- protected void starting(Description description)
starting() method is invoked when a test is about to start
- protected void succeeded(Description description)
succeeded() method is invoked when a test succeeds
Let's see how we can modify the previous test class to take advantage of the TestWatcher class behavior:
- create a class (WatchManClassConsole) that implements a JUNIT rule through the TestWatcher() class
- the succeeded() method is overridden so that the names of passed tests are displayed at the console with the successful status
- the failed() method is overridden so that the names of the failed tests are displayed at the console with the failed status
- the test class needs to extend the WatchManClassConsole class to take advantage of the overridden succeeded() and failed() methods
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestClass2 extends WatchManClassConsole {
@Test
public void testScript1() {
assertTrue(1 < 2); >
}
@Test
public void testScript2() {
assertTrue(1 > 2);
}
@Test
public void testScript3() {
assertTrue(1 < 2);
}
@Test
public void testScript4() {
assertTrue(1 > 2);
}
}
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class WatchManClassConsole {
@Rule
public TestRule watchman = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
@Override
protected void succeeded(Description description) {
System.out.println(description.getDisplayName() + " " + "success!");
}
Override
protected void failed(Throwable e, Description description) {
System.out.println(description.getDisplayName() + " " + e.getClass().getSimpleName());
}
};
}
The result of executing the test class is below:
We have now both visual junit test results and console results.
This is a step in the right direction.
We can create next the cumulative, customized HTML report.
Build the custom, cumulative HTML report for Selenium test results
The last thing to do is writing the code for generating the HTML file that stores the pass/fail results for the test scripts.
The class that uses the TestWatcher overriding capabilities is called now WatchManClassHtml:
- static File and BufferWriter members are used for writing information to the existing test result file
- the setUp() junit method is used for setting up the environment; this includes
- opening the existing test result file
- writing the <HTML> and <BODY> html nodes to the file
- writing the test execution date and time to the file
- the tearDown() junit method is used for cleaning the environment:
- writing the </HTML> and </BODY> html nodes to the file
- closing the BufferWriter object
- opening the HTML file
- succeeded() method writes to the html file the names of the tests that passed
- failed() method writes to the html file the names of the tests that failed
Each time the tests are executed, the tests results are appended to the test results file.
The test class is the same as before.
The only change added to it is to inherit from the WatchManClassHtml class:
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestClass2 extends WatchManClassHtml {
@Test
public void testScript1() {
assertTrue(1 < 2);
}
@Test
public void testScript2() {
assertTrue(1 > 2);
}
@Test
public void testScript3() {
assertTrue(1 < 2);
}
@Test
public void testScript4() {
assertTrue(1 > 2);
}
}
import static org.junit.Assert.*;
import java.awt.Desktop;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class WatchManClassHtml {
static File f;
static BufferedWriter bw;
@BeforeClass
public static void setUp() throws IOException
{
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
Date date = new Date();
f = new File("c:\\temp\\test_results.htm");
bw = new BufferedWriter(new FileWriter(f, true));
bw.write("<html><body>");
bw.write("<h1>Test Case Status - " + dateFormat.format(date) + "</h1>");
}
@AfterClass
public static void tearDown() throws IOException
{
bw.write("</body></html>");
bw.close();
Desktop.getDesktop().browse(f.toURI());
}
@Rule
public TestRule watchman = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
return super.apply(base, description);
}
@Override
protected void succeeded(Description description) {
try {
bw.write(description.getDisplayName() + " " + "success!");
bw.write("<br/>");
}
catch (Exception e1) {
System.out.println(e1.getMessage());
}
}
@Override
protected void failed(Throwable e, Description description) {
try {
bw.write(description.getDisplayName() + " " + e.getClass().getSimpleName());
bw.write("<br/>");
}
catch (Exception e2) {
System.out.println(e2.getMessage());
}
}
};
}
The results of executing the test scripts are below:
Feel free to try the code by yourself and leave any questions about it in the COMMENTS section.
Thanks.
NEXT
thanks for sharing this blog
ReplyDeleteSelenium Training
Hi,
ReplyDeleteI have implemented my test case using testwatcher but there is a lot of space in my html report. How can I get rid of it?
http://engage-staging-test-results.s3-website-ap-southeast-2.amazonaws.com/1CoverNZ/cucumber-html-reports/PriceValidationTestReport.html