0
0
JUnittesting~15 mins

TestWatcher for reporting in JUnit - Build an Automation Script

Choose your learning style9 modes available
Automate test reporting using JUnit TestWatcher
Preconditions (2)
Step 1: Create a TestWatcher extension class that overrides testSuccessful, testFailed, and testDisabled methods
Step 2: In each overridden method, log the test method name and its result (success, failure, or disabled)
Step 3: Attach the TestWatcher extension to the sample test class using @ExtendWith annotation
Step 4: Run the test class
Step 5: Observe the console output for correct reporting of each test method's result
✅ Expected Result: The console shows messages indicating each test method's name and whether it passed, failed, or was skipped
Automation Requirements - JUnit 5
Assertions Needed:
Verify that the TestWatcher logs the correct test method name and status for each test
Best Practices:
Use @ExtendWith to register the TestWatcher extension
Use descriptive log messages for clarity
Keep the TestWatcher class reusable for other test classes
Avoid hardcoding test method names; use the provided ExtensionContext
Automated Solution
JUnit
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
import java.util.Optional;

class ReportingTestWatcher implements TestWatcher {

    @Override
    public void testSuccessful(ExtensionContext context) {
        String testName = context.getDisplayName();
        System.out.println("[PASS] Test succeeded: " + testName);
    }

    @Override
    public void testFailed(ExtensionContext context, Throwable cause) {
        String testName = context.getDisplayName();
        System.out.println("[FAIL] Test failed: " + testName + ". Reason: " + cause.getMessage());
    }

    @Override
    public void testDisabled(ExtensionContext context, Optional<String> reason) {
        String testName = context.getDisplayName();
        System.out.println("[SKIP] Test disabled: " + testName + ". Reason: " + reason.orElse("No reason provided"));
    }
}

@ExtendWith(ReportingTestWatcher.class)
public class SampleTests {

    @Test
    void testSuccess() {
        // This test will pass
        int sum = 2 + 3;
        assert sum == 5;
    }

    @Test
    void testFailure() {
        // This test will fail
        int product = 2 * 2;
        assert product == 5 : "Product should be 5";
    }

    @Test
    void testAnotherSuccess() {
        // Another passing test
        String text = "hello".toUpperCase();
        assert text.equals("HELLO");
    }

    @Test
    @org.junit.jupiter.api.Disabled("Not implemented yet")
    void testDisabled() {
        // This test is disabled
    }
}

The ReportingTestWatcher class implements JUnit 5's TestWatcher interface to listen to test lifecycle events.

We override testSuccessful, testFailed, and testDisabled methods to print messages to the console with the test name and status.

The SampleTests class uses @ExtendWith to attach the watcher. It contains tests that pass, fail, and one disabled test to demonstrate all cases.

When running the tests, the console will show clear messages indicating which tests passed, failed, or were skipped, helping with reporting.

Common Mistakes - 4 Pitfalls
Not using @ExtendWith to register the TestWatcher
{'mistake': 'Hardcoding test method names instead of using ExtensionContext', 'why_bad': 'Hardcoding names makes the watcher inflexible and error-prone if tests change.', 'correct_approach': "Use context.getDisplayName() to get the current test's name dynamically."}
Printing messages without clear status labels
Ignoring the cause parameter in testFailed method
Bonus Challenge

Extend the TestWatcher to write the test results to a file instead of console output.

Show Hint