Next-Gen App & Browser Testing Cloud
Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Discover JUnit ErrorCollector, a crucial tool for comprehensive test coverage. Learn how it simplifies error handling, ensuring smooth test execution.
Sri Priya
January 13, 2026
In some situations, there is a need to allow the test execution to proceed despite encountering failures. It becomes essential when dealing with complex test cases involving multiple steps and assertions. Stopping the execution, addressing each error, and rerunning the entire test suite is only sometimes practical.
Furthermore, gathering information about these failures is essential for troubleshooting and improving subsequent test runs.
To address such issues, where rerunning the entire test suite becomes necessary, JUnit offers a more effective solution known as ErrorCollector rather than the Soft Assert approach. We will further explore why JUnit’s ErrorCollector surpasses the use of SoftAssert().
The ErrorCollector class in JUnit allows testers to collect multiple errors during test execution without immediately stopping the test. This enables the framework to report all failures at once rather than halting after the first issue is encountered.
When to Use JUnit ErrorCollector?
Using only assertions stops the test at the first failure, forcing reruns for all tests. ErrorCollector helps gather all errors before marking the test as failed.
What Are Methods of the JUnit ErrorCollector Class?
The ErrorCollector class provides several methods to help capture and manage exceptions or assertion failures effectively. Below are some of the most commonly used methods that make error handling more efficient in JUnit tests.
How to Use ErrorCollector in JUnit?
The ErrorCollector feature in JUnit helps gather all errors encountered during test execution without halting after the first failure, improving overall test result visibility.
ErrorCollector is a feature that lets you cover every line of code in a test (irrespective of failure encountered in the code). It is a very crucial and tedious task for anyone to check the failure and output of each & every line in the test.
Even if a line of code fails, the script’s execution continues due to a unique feature called ErrorCollector offered by JUnit. As the name indicates, ErrorCollector gathers all error objects from assert statements, making it particularly useful when we use HardAssert() in our tests.
When an assert statement fails, it doesn’t stop the test; instead, it proceeds to the following line of code, similar to SoftAssert(). However, the JUnit ErrorCollector distinguishes itself by gathering all errors and presenting them at the end of the test run.
However, SoftAssert() doesn’t throw exceptions immediately but records them and throws them all at once using the assertAll() method, allowing the test to continue after each assert statement. To use Soft Assert, include the package org.testng.asserts.SoftAssert in your test execution.
It simplifies validating and rectifying errors in test scripts by providing complete error logs. Ensuring test continuity and addressing errors are crucial in test automation, and ErrorCollector offers an optimal solution. It streamlines the verification and correction of tests, making it more convenient to address all issues at once.
ErrorCollector is available in both JUnit 4 as well as JUnit 5. In this case, we will use JUnit 5, the latest version, to demonstrate the code.
Still using JUnit 4? And wondering how to run your JUnit 4 test on JUnit 5? Worry not! You can get started with this blog on executing JUnit 4 tests on JUnit 5.
Instantiate the ErrorCollector before using it in your class.
@Rule
public ErrorCollector collector = new ErrorCollector();
We will cover more about ErrorCollector usage in the further sections of the blog.
JUnit ErrorCollector is handy when we anticipate that a test case might produce errors or exceptions. It is beneficial when running many tests, say 500 to 1000 or more, and we expect a few of them to encounter issues.
If we rely only on assert statements, any error will force us to stop the entire test execution, fix the problem, and rerun all the tests, including those that encountered errors or exceptions. That is where JUnit ErrorCollector can be helpful.
ErrorCollector collects all the errors or exceptions that occur during the execution of a test case and reports them at the end of the test.
Below are some instances where we can use ErrorCollector in JUnit:
To summarize, JUnit ErrorCollector proves valuable when we need to test numerous scenarios with various inputs while ensuring thorough module testing. By consolidating all errors and exceptions into a single test case, we can save time and effort in test creation and maintenance.
Note: Run JUnit tests across different browsers, versions, and OS combinations. Try TestMu AI Today!
One of the essential features of JUnit is its ability to capture and report errors at the end of the test execution through its significant feature – ErrorCollector. Let’s highlight some key benefits of using ErrorCollector.

It contributes to quicker issue identification, enhancing the robustness and reliability of our tests.
You can learn more about assertions through this video:
You can Subscribe to the TestMu AI YouTube channel for more videos on Selenium testing, Cypress testing, and Playwright testing to elevate your testing game!
For instance, ErrorCollector is essential when specific tests need to run on particular browsers and versions with unreliable internet connections. It enables us to continue execution even if a test fails and provides detailed logs of the failure, playing a crucial role in such scenarios.
In a nutshell, JUnit ErrorCollector helps to achieve continuous test execution, improved test coverage, and identify the root cause of the errors. There can be many conditions where test failure analysis can be difficult to handle and monitor. For easy analysis and identification of the root cause, you can use one of the features offered by TestMu AI HyperExecute, an AI-powered end-to-end test orchestration cloud 70% faster than traditional cloud grids.
So what is HyperExecute AI-powered Root Cause Analysis?
The AI-powered Root Cause Analysis (RCA) and Error Detection feature for HyperExecute allows you to identify different error categories and offers a comprehensive overview of their underlying causes. It lets you analyze your test logs and identify the root cause of failures so you can take corrective action quickly.
Want to use this feature? Check out the documentation: AI-Powered Test Failure Analysis in HyperExecute.
The ErrorCollector class in JUnit provides several methods to collect and report errors. Some of the most commonly used methods are:

The checkThat() method within JUnit’s ErrorCollector class lets you assert a test, gather any occurring errors, and continue with the test execution.
public <T> void checkThat(T value, Matcher<T> matcher)
The checkThat() method has two parameters: a String message and a Matcher object. The Matcher object is utilized to confirm if the actual value aligns with the expected value.
The addError() method includes an error in the ErrorCollector. This error can be any throwable object, including exceptions or assertion errors.
public void addError(Throwable error)
This method allows you to add a Throwable error as an input parameter. Although the test execution continues, it will ultimately be marked as failed.
You can use the checkSucceeds() method in JUnit ErrorCollector to run a code block and ensure it doesn’t throw any exceptions. If an exception does occur, the error is collected, but the test keeps running.
public <T> T checkSucceeds(Callable<T> callable)
JUnit provides @Rule annotation, which creates an object of ErrorCollector. Once the object is created, we can add all the errors using the addError(Throwable error) method. You can learn more about it through this blog on annotations in JUnit.
In Java, Throwable is the superclass of both the Exception and Error classes. By using the @Rule annotation, you can conveniently include error objects, and these errors will be logged in the JUnit test result after the respective test cases are executed.
@Rule
public ErrorCollector collector= new ErrorCollector();
To showcase the advantages of JUnit ErrorCollector, let’s take a simple test case that asserts on failure. Below is an example of one test that asserts different conditions.
FileName – TestErrorCollector.java
package com.lambdatest.junit;
import static org.junit.Assert.*;
import org.junit.Test;
public class TestErrorCollector {
@Test
public void testWithAssert() {
assertEquals(100, 200);
assertTrue(false);
assertFalse(false);
}
}
Result:

Only the initial assert statement is carried out in the given test script. The execution doesn’t continue to the remaining two asserts because the first one, the assertEquals statement, fails and interrupts the execution.
Now, let’s address the issue described earlier using JUnit ErrorCollector. We’ve included the addError() method to place the object into an ErrorCollector.
FileName – ErrorCollectorTestAdd.java
package com.lambdatest.junit;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
public class ErrorCollectorTestAdd {
@Rule
public final ErrorCollector collector = new ErrorCollector();
@Test
public void testWithErrorCollector() {
collector.addError(new Throwable("error 1"));
collector.addError(new Throwable("error 2"));
collector.addError(new Throwable("error 3"));
collector.addError(new Throwable("error 4"));
}
}
Result:

All four sample errors are processed, even if they are related to the same test.
Additionally, there’s another method in JUnit ErrorCollector called checkThat(), and we’ll explore how it works below.
package com.lambdatest.junit;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.core.Is.is;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
public class ErrorCollectorTest {
@Rule
public ErrorCollector collector = new ErrorCollector();
@Test
public void myTest() {
collector.checkThat(100, equalTo(200));
collector.checkThat(10, equalTo(200));
}
}
Result:

In the above output, both the assert statements are executed even if the first statement fails.
You now grasp the significance of JUnit ErrorCollector and its methods. All the examples mentioned earlier were conducted on a local machine, which does have its limitations. However, you do have the alternative of running tests on a cloud-based platform such as TestMu AI, which can expand your resources with access to multiple browsers and various OS combinations. TestMu AI is an AI-based test orchestration and execution platform for conducting both manual and automated tests at scale. You can test over 3000+ real devices across various browsers and operating systems.
In the next section, we will explore leveraging TestMu AI for automating test scripts with Selenium using JUnit ErrorCollector.
Let’s examine a practical test case that includes assertions for verifying the Page Title and performing a product search in the search field. Despite any inconsistency in the Page Title assertion, the test should still successfully proceed with the product search using ErrorCollector.
Test Scenario
To write test scripts, you can use any IDE like IntelliJ or Eclipse. However, for this demonstration, we will use the Eclipse IDE. Before we delve into writing the test scenarios, let’s take a moment to understand the directory structure of the Eclipse IDE.
To begin, create a package named com.lambdatest.automation under src/test/java. Within this package, you’ll find three classes: ClassWithoutErrorCollector, ErrorCollectorItemsPageTest, and ErrorCollectorTest.

To illustrate, we have used Selenium 4.8 and JUnit 5.9.2 within the automation testing framework.
Before running the tests, there are a few steps you need to take care of.
Step 1: Create a TestMu AI account.
Step 2: Click on Account Settings from the list of options under your profile avatar.

Step 3: Copy the Username and Access key from the Password and Security tab.

Step 4: Now, you need to generate capabilities from the TestMu AI Capabilities Generator, which is more like a configuration that allows you to set the browser of your choice, its version, and operating system.

Step 4: Copy the generated capabilities and paste them into your code.
Let’s now implement the code and run the test on the TestMu AI platform without using ErrorCollector. For that, you need first add some libraries into your pom.xml file.
FileName – pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SeleniumFramework</groupId>
<artifactId>SeleniumFramework</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.8.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Code to click on the Search box field.
driver.findElement(By.cssSelector("div[id='entry_217822'] input[placeholder='Search For Products']")).click();
To locate an element on the website, you can perform an inspection. To do this, visit the website, right-click anywhere, and choose the “Inspect” option. Then, find the element you’re interested in and identify it uniquely using Selenium locators by ID or its CSS Selector property. In this case, we will use the CSS Selector to locate the web element and the click() method to interact with it.

Now that you have the element, all you need to do is add your LT Username and Access Key, which can be found under the capabilities generator.

Simply insert the data generated from the TestMu AI platform into your code snippet, and you’re all set to run your test.
FileName – ClassWithoutErrorCollector.java
package com.lambdatest.automation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import static org.junit.Assert.*;
public class ClassWithoutErrorCollector {
public String username = "LT_USERNAME";
public String accesskey = "LT_ACCESS_KEY";
public static RemoteWebDriver driver = null;
public String gridURL = "@hub.lambdatest.com/wd/hub";
boolean status = false;
@Before
public void setUp() throws Exception {
ChromeOptions browserOptions = new ChromeOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("113.0");
HashMap<String, Object> ltOptions = new HashMap<String, Object>();
ltOptions.put("username", "username");
ltOptions.put("accessKey", "accesskey ");
ltOptions.put("project", "Error Collector");
ltOptions.put("w3c", true);
ltOptions.put("plugin", "java-junit");
browserOptions.setCapability("LT:Options", ltOptions);
try {
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), browserOptions);
} catch (MalformedURLException e) {
System.out.println("Invalid grid URL");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Test
public void testSimple() throws Exception {
// navigating to the application under test
driver.get("https://ecommerce-playground.lambdatest.io/");
// maximize window
driver.manage().window().maximize();
Thread.sleep(1000);
// validating the Page Title
String ActualString = "Your Stores";
String ExpectedString = driver.getTitle();
System.out.println(ExpectedString);
assertEquals(ExpectedString, ActualString);
Thread.sleep(1000);
driver.findElement(By.cssSelector("div[id='entry_217822'] input[placeholder='Search For Products']")).click();
Thread.sleep(1000);
driver.findElement(By.cssSelector("div[id='entry_217822'] input[placeholder='Search For Products']"))
.sendKeys("IPod");
Thread.sleep(3000);
driver.findElement(By.xpath("//button[normalize-space()='Search']")).click();
Thread.sleep(1000);
String ActualProductPageTitle = "Search - iPod";
String ExpectedProductPageTitle = driver.getTitle();
System.out.println(ExpectedProductPageTitle);
Thread.sleep(3000);
}
@After
public void tearDown() throws Exception {
if (driver != null) {
((JavascriptExecutor) driver).executeScript("lambda-status=" + status);
driver.quit();
}
}
}
Result:

As you can see, the test execution came to a halt at the first assert statement. To tackle this problem, we can utilize ErrorCollector.
The following two classes, ErrorCollectorTest and ErrorCollectorItemsPageTest, use JUnit ErrorCollector to ensure that the test execution continues without interruption.
FileName – ErrorCollectorTest.java
package com.lambdatest.automation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
public class ErrorCollectorTest {
public String username = "LT_USERNAME";
public String accesskey = "LT_ACCESS_KEY";
public static RemoteWebDriver driver = null;
public String gridURL = "@hub.lambdatest.com/wd/hub";
boolean status = false;
@Before
public void setUp() throws Exception {
ChromeOptions browserOptions = new ChromeOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("113.0");
HashMap<String, Object> ltOptions = new HashMap<String, Object>();
ltOptions.put("username", username);
ltOptions.put("accessKey", accesskey);
ltOptions.put("project", "Error Collector");
ltOptions.put("w3c", true);
ltOptions.put("plugin", "java-junit");
browserOptions.setCapability("LT:Options", ltOptions);
try {
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), browserOptions);
} catch (MalformedURLException e) {
System.out.println("Invalid grid URL");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Rule
public final ErrorCollector collector = new ErrorCollector();
@Test
public void testWithErrorCollector() throws InterruptedException {
System.out.println("FirstParallelUnitTest first() start => " + Thread.currentThread().getName());
// navigating to the application under test
driver.get("https://ecommerce-playground.lambdatest.io/");
// maximize window
driver.manage().window().maximize();
Thread.sleep(1000);
// validating the Page Title
String ActualString = "Your Stores";
String ExpectedString = driver.getTitle();
System.out.println("value coming in : " + ExpectedString);
System.out.println("value to check : " + ActualString);
collector.checkThat("Check values match", ActualString, equalTo(ExpectedString));
collector.checkThat(ExpectedString, equalTo(ActualString));
collector.checkThat(ExpectedString, "Not matched",equalTo(ActualString));
driver.findElement(By.cssSelector("div[id='entry_217822'] input[placeholder='Search For Products']")).click();
Thread.sleep(1000);
driver.findElement(By.cssSelector("div[id='entry_217822'] input[placeholder='Search For Products']"))
.sendKeys("IPod");
Thread.sleep(3000);
driver.findElement(By.xpath("//button[normalize-space()='Search']")).click();
Thread.sleep(1000);
String ActualProductPageTitle = "Search - iPod";
String ExpectedProductPageTitle = driver.getTitle();
System.out.println(ExpectedProductPageTitle);
Thread.sleep(3000);
System.out.println("Test Completed");
}
private Matcher equalTo(String actualString) {
// TODO Auto-generated method stub
return null;
}
}
FileName – ErrorCollectorItemsPageTest.java
package com.lambdatest.automation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
public class ErrorCollectorItemsPageTest {
public String username = "LT_USERNAME";
public String accesskey = "LT_ACCESS_KEY";
public static RemoteWebDriver driver = null;
public String gridURL = "@hub.lambdatest.com/wd/hub";
boolean status = false;
@Before
public void setUp() throws Exception {
ChromeOptions browserOptions = new ChromeOptions();
browserOptions.setPlatformName("Windows 10");
browserOptions.setBrowserVersion("113.0");
HashMap<String, Object> ltOptions = new HashMap<String, Object>();
ltOptions.put("username", username);
ltOptions.put("accessKey", accesskey);
ltOptions.put("project", "Error Collector");
ltOptions.put("w3c", true);
ltOptions.put("plugin", "java-junit");
browserOptions.setCapability("LT:Options", ltOptions);
try {
driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + gridURL), browserOptions);
} catch (MalformedURLException e) {
System.out.println("Invalid grid URL");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
@Rule
public final ErrorCollector collector = new ErrorCollector();
@Test
public void testWithErrorCollector() throws InterruptedException {
System.out.println("SecondParallelUnitTest first() start => " + Thread.currentThread().getName());
// navigating to the application under test
driver.get("https://ecommerce-playground.lambdatest.io/");
// maximize window
driver.manage().window().maximize();
Thread.sleep(1000);
// clicking on MyAccount dropdown
driver.findElement(
By.xpath("//ul[@class='navbar-nav horizontal']//span[@class='title'][normalize-space()='Blog']"))
.click();
// validating the Page Title
String ActualString = "Blog-Poco Theme";
String ExpectedString = driver.getTitle();
System.out.println("value coming in : " + ExpectedString);
System.out.println("value to check : " + ActualString);
collector.checkThat("Check values match", ActualString, equalTo(ExpectedString));
collector.checkThat(ExpectedString, equalTo(ActualString));
collector.checkThat(ExpectedString, "Not matched", equalTo(ActualString));
Thread.sleep(3000);
/// navigate to account login page
driver.findElement(By.xpath("//a[@role='button']//span[@class='title'][normalize-space()='My account']"))
.click();
Thread.sleep(3000);
System.out.println(driver.getTitle());
System.out.println("Test Completed");
}
private Matcher equalTo(String actualString) {
// TODO Auto-generated method stub
return null;
}
}
Step 1: Import the packages of JUnit and other methods.

Step 2: Create the RemoteWebDriver reference. RemoteWebDriver is a class that implements the WebDriver interface to execute the tests on the RemoteWebDriver server on a remote machine. It is implemented under the package below.

Step 3: The method implemented in @BeforeTest annotation sets the browser’s capabilities. A RemoteWebDriver instance is created with the desired browser capabilities, with the Selenium Grid URL set to the cloud-based Selenium Grid on TestMu AI [@hub.lambdatest.com/wd/hub].

Step 4: All the test navigation steps are implemented under the @Test annotation. Here is how we navigate to the desired URL.

Step 5: Checking the actual Title of the page and the expected Title of the page.

Step 6: Inspect the ‘Search Box’ text field using any locator. We have used CSS Selector as a locator and entered the “IPod” text in the search field using the sendKeys() method in Selenium.



Step 7: Thread.sleep() in Selenium pauses the current thread for a specified time, often 3000 milliseconds, to wait for a page or application to load before continuing with the next code line.

However, it is preferred to use Selenium’s implicit and explicit waits over Thread.sleep(), allowing more efficient and responsive synchronization with the web page, reducing unnecessary wait times. For a deeper understanding of implicit and explicit wait commands in Selenium, refer to this article on Selenium Waits.
Step 8: To utilize JUnit rules, we apply the @Rule annotation to methods or fields. Keep in mind that the annotated methods must be public and non-static.
This concept involves rules or methods that provide outcomes. In this case, we’re implementing the @Rule annotation, which gathers and reports all errors together in one go.

Step 9: Collecting all the errors and asserting.

TestMu AI Dashboard
The tests were successfully executed on TestMu AI’s Selenium Grid, and the TestMu AI Web Automation Dashboard indicates the status of the test execution.

In summary, by using the JUnit ErrorCollector defined under the @Rule annotation, we can handle test failures in our test script without prematurely stopping the tests during execution. The JUnit ErrorCollector allows us to proceed with the test execution even when errors occur.
The ErrorCollector gathers error objects as they occur, accumulates them, and reports them once the test run finishes. The benefit of utilizing the JUnit ErrorCollector is that it enables us to review and verify all the collected errors after the test execution.
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance