Deep Dive into JUnit Assertions with WebDriver and Custom Assertions

Deep Dive into JUnit Assertions with WebDriver and Custom Assertions

JUnit assertions are a cornerstone of Java testing, enabling developers to write tests that verify code behavior. In this article, we’ll explore the various JUnit assertions, their applications in Selenium WebDriver tests, and delve into a custom assertion example with the DateTimeAssert class.

Understanding JUnit Assertions

JUnit offers a suite of assertion methods that validate different conditions in tests. Here’s a brief overview of some key methods:

  • assertEquals(): Verifies that two values are equal.
  • assertNotEquals(): Ensures two values are not equal.
  • assertTrue(): Checks that a condition is true.
  • assertFalse(): Verifies a condition is false.
  • assertNull(): Checks that an object is null.
  • assertNotNull(): Ensures an object is not null.
  • assertSame(): Tests if two references point to the same object.
  • assertNotSame(): Ensures two references do not point to the same object.
  • assertArrayEquals(): Verifies that two arrays are equal.
  • assertIterableEquals(): Asserts that two iterables are equal.
  • assertAll(): Groups multiple assertions in a single test.
  • assertThrows(): Expects a specific exception to be thrown.

Here is sample usage of the assertions:

@TestMethodOrder(value = MethodOrderer.Random.class)
public class CalculatorTests {
    private final Calculator _calculator = new Calculator();

    @BeforeAll
    public static void setUpClass() {
        System.out.println("This is @BeforeAll annotation");
    }

    @BeforeEach
    public void setUp() {
        System.out.println("This is @BeforeEach annotation");
    }

    @NightlyRunTest
    @Order(2)
    public void test_Addition() {
        System.out.println("This is test 1");
        var actualResult = _calculator.add(1, 1);

        Assertions.assertEquals(2, actualResult);
    }

    @Test
    @Order(1)
    public void testAdditionDifferentNumbers() {
        System.out.println("This is test 2");
        var actualResult = _calculator.add(2, 1);

        Assertions.assertEquals(3, actualResult);
    }

    @AfterEach
    public void tearDown() {
        System.out.println("This is @After annotation");
    }

    @AfterAll
    public static void tearDownClass() {
        System.out.println("This is @AfterAll annotation");
    }
}

The tests are verifying the following simple class:

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public int divide(int a, int b) {
        if (b == 0)
            throw new ArithmeticException("/ by zero");
        return a/b;
    }
}

In this snippet, we see the setup for a test class for a Calculator. The @TestMethodOrder(MethodOrderer.Random.class) annotation suggests that the test methods within this class will be executed in a random order. This approach is useful to ensure that tests are independent of each other. The goal here is to test various operations of a Calculator class, such as addition, subtraction, multiplication, and division, ensuring they perform correctly under different scenarios.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("nightlyRun")
@Test
public @interface NightlyRunTest {
}

The @NightlyRunTest annotation is a custom annotation that combines the standard @Test annotation with a @Tag. This allows for easily filtering and running a specific subset of tests, in this case, those intended for a nightly run.

JUnit Assertions in WebDriver Tests

In Selenium WebDriver tests, assertions are used to validate the state of web elements and interactions. For instance, after clicking a button on a webpage, assertTrue() could be used to assert that a confirmation message is displayed.

public class FirstSeleniumTests {
    private WebDriver driver;

    @BeforeAll
    public static void setUpClass() {
        WebDriverManager.chromedriver().setup();
    }

    @BeforeEach
    public void setUp() {
        driver = new ChromeDriver();
    }

    @Test
    public void properCheckboxSelected() throws Exception {
        driver.navigate().to("https://lambdatest.github.io/sample-todo-app/");

        LocalDate birthDay = LocalDate.of(1990, 10, 20);
        // us 10/20/1990
        DateTimeFormatter usDateFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy");
        String dateToType = usDateFormat.format(birthDay);

        WebElement todoInput = driver.findElement(By.id("sampletodotext"));
        todoInput.sendKeys(dateToType);

        var addButton = driver.findElement(By.id("addbutton"));
        addButton.click();

        var todoCheckboxes = driver.findElements(By.xpath("//li[@ng-repeat]/input"));

        todoCheckboxes.get(2).click();

        var todoInfos = driver.findElements(By.xpath("//li[@ng-repeat]/span"));

        Assertions.assertEquals("20-10-1990", todoInfos.get(5).getText());

        String expectedUrl = "https://lambdatest.github.io/sample-todo-app/";
        Assertions.assertTrue(expectedUrl.equals(driver.getCurrentUrl()), "URL does not match");

        String notExpectedUrl = "https://www.lambdatest.com/";
        Assertions.assertFalse(notExpectedUrl.equals(driver.getCurrentUrl()), "URL match");

        var expectedItems = new String[] {
            "First Item",
            "Second Item",
            "Third Item",
            "Fourth Item",
            "Fifth Item",
            "20-10-1990"
        };
        var actualToDoInfos = todoInfos.stream().map(e - > e.getText()).toArray();
        Assertions.assertArrayEquals(expectedItems, actualToDoInfos);

        Exception exception = Assertions.assertThrows(ArithmeticException.class, () - > new Calculator().divide(1, 0));

        Assertions.assertEquals("/ by zero", exception.getMessage());

        Assertions.assertTimeout(ofMinutes(2), () - > {
            // perform your tasks
        });

        Assertions.assertAll(
            () - > Assertions.assertTrue(expectedUrl.equals(driver.getCurrentUrl()), "URL does not match"),
            () - > Assertions.assertFalse(notExpectedUrl.equals(driver.getCurrentUrl()), "URL match"),
            () - > Assertions.assertArrayEquals(expectedItems, actualToDoInfos)
        );

        double actualDoubleValue = 2.999;
        double expectedDoubleValue = 3.000;

        Assertions.assertEquals(expectedDoubleValue, actualDoubleValue, 0.001);

        var currentTime = LocalDateTime.now();
        var currentTimeInPast = LocalDateTime.now().minusMinutes(3);

        DateTimeAssert.assertEquals(currentTime, currentTimeInPast, DateTimeDeltaType.MINUTES, 4);
    }

    @AfterEach
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}

Let’s discuss in details the important parts of the example.

Assertions.assertEquals("20-10-1990", todoInfos.get(5).getText());

This assertion checks if the text of the sixth element in todoInfos matches the string “20-10-1990”. It verifies that the text in the web application is as expected.

Assertions.assertTrue(expectedUrl.equals(driver.getCurrentUrl()), "URL does not match");

This asserts that the current URL of the WebDriver matches the expected URL. The test will pass if the condition is true.

Assertions.assertFalse(notExpectedUrl.equals(driver.getCurrentUrl()), "URL match");

This asserts that the current URL of the WebDriver does not match notExpectedUrl. The test will pass if the URL is different.

Assertions.assertArrayEquals(expectedItems, actualToDoInfos);

This checks if the array of expected items matches the array of texts from todoInfos. It’s used to verify multiple elements in a collection.

Exception exception = Assertions.assertThrows(ArithmeticException.class, () - > new Calculator().divide(1, 0));
Assertions.assertEquals("/ by zero", exception.getMessage());

This tests if the specified action divide(1, 0) throws an ArithmeticException. It then checks if the exception message is as expected.

Deep Dive into DateTimeAssert Class

The DateTimeAssert class illustrates a custom assertion approach.

public class DateTimeAssert {
    public static void assertEquals(LocalDateTime expectedDate, LocalDateTime actualDate, DateTimeDeltaType deltaType, int count) throws Exception {
        if (((expectedDate == null) && (actualDate == null))) {
            return;
        }
        else if ((expectedDate == null)) {
            throw new NullPointerException("The expected date was null");
        }
        else if ((actualDate == null)) {
            throw new NullPointerException("The actual date was null");
        }

        Duration expectedDelta = DateTimeAssert.getTimeSpanDeltaByType(deltaType, count);

        double totalSecondsDifference = Math.abs((actualDate.until(expectedDate, ChronoUnit.SECONDS)));

        if ((totalSecondsDifference > expectedDelta.getSeconds())) {
            var exceptionMessage =String.format("Expected Date: {0}, Actual Date: {1} \nExpected Delta: {2}, Actual Delta in seconds- {3} (Delta Type: " +
                    "{4})", expectedDate, actualDate, expectedDelta, totalSecondsDifference, deltaType);
            throw new Exception(exceptionMessage);
        }
    }

    private static Duration getTimeSpanDeltaByType(DateTimeDeltaType type, int count) {
        Duration result;
        switch (type) {
            case DAYS:
                result = Duration.ofDays(count);
                break;
            case MINUTES:
                result = Duration.ofMinutes(count);
                break;
            default:
                throw new NotImplementedException("The delta type is not implemented.");
        }
        return result;
    }
}

The class provides a method assertEquals(LocalDateTime expectedDate, LocalDateTime actualDate, DateTimeDeltaType deltaType, int count) which compares two LocalDateTime objects with a specified tolerance. This method checks if two dates are within a certain tolerance. The parameters deltaType and count define the type and magnitude of the permissible delta, making this a versatile tool for date comparisons in tests.

To learn even more about the topic check this video:

Play video

Conclusion

JUnit assertions are an integral part of Java testing, offering a wide range of methods to validate different conditions. Their application in Selenium WebDriver tests enhances the robustness of web application testing. Custom assertions like those in the DateTimeAssert class further expand the capabilities of JUnit, allowing for more tailored and complex test scenarios.

Related Articles

Web Automation Java

Playwright Tutorial: Exploring Test Automation with Java

Playwright, developed by Microsoft and launched in early 2020, is a powerful framework for web testing and automation. It offers a range of benefits:

Playwright Tutorial: Exploring Test Automation with Java

Java, Web Automation Java

Selenium WebDriver Tor Network Integration Java Code

For a long time, I wanted to write automation using the Tor Web Browser. My preferred automation framework is Selenium WebDriver. However, I found out that ther

Selenium WebDriver Tor Network Integration Java Code

Java, Web Automation Java

Automate Telerik Kendo Grid with WebDriver with Java and JavaScript

Have you had this problem trying to automate custom-tuned web controls? Probably, your team has purchased these from some dedicated UI controls vendor. There ar

Automate Telerik Kendo Grid with WebDriver with Java and JavaScript

Java, Web Automation Java

30 Advanced WebDriver Tips and Tricks Java Code

This is the next article from the WebDriver Series where I will share with you 30 advanced tips and tricks using Java code. I wrote similar articles separated i

30 Advanced WebDriver Tips and Tricks Java Code

Resources, Web Automation Java

Most Complete Selenium WebDriver Kotlin Cheat Sheet

As you know, I am a big fan of Selenium WebDriver. You can find tones of useful Kotlin/Java code in my Web Automation Java Series. I lead automated testing cour

Most Complete Selenium WebDriver Kotlin Cheat Sheet

Web Automation Java

Playwright Tutorial: IFrame and Shadow DOM Automation

In this post, we will go through the basics of IFrames and Shadow DOM, and we will learn the strategies of automating these complex HTML structures with Playwri

Playwright Tutorial: IFrame and Shadow DOM Automation
Anton Angelov

About the author

Anton Angelov is Managing Director, Co-Founder, and Chief Test Automation Architect at Automate The Planet — a boutique consulting firm specializing in AI-augmented test automation strategy, implementation, and enablement. He is the creator of BELLATRIX, a cross-platform framework for web, mobile, desktop, and API testing, and the author of 8 bestselling books on test automation. A speaker at 60+ international conferences and researcher in AI-driven testing and LLM-based automation, he has been recognized as QA of the Decade and Webit Changemaker 2025.