Exploring TestNG Annotations and Assertions: Soft vs. Hard Assertions

In automated testing with TestNG, annotations and assertions play a critical role in creating structured, readable, and effective test scripts. Annotations define the structure of your tests, while assertions validate your expectations against actual outcomes. In this blog post, we'll dive into the basics of TestNG annotations, discuss how soft and hard assertions work, and explore how to use them to maximize the efficiency of your test cases.

What is TestNG?

TestNG is a powerful testing framework inspired by JUnit and NUnit. It is specifically designed to simplify test configuration and to make tests more manageable, especially in Java environments. Its primary advantage lies in its flexibility and robustness, making it a popular choice for automation engineers. With features like annotations, dependency testing, and grouping, TestNG helps in organizing and executing tests effectively.

Understanding TestNG Annotations

Annotations in TestNG help control the flow and structure of test methods. Here’s a quick overview of some commonly used annotations:

  1. @BeforeSuite: Runs once before all tests in the suite.
  2. @AfterSuite: Executes once after all tests in the suite.
  3. @BeforeTest: Runs before each <test> tag in the XML file.
  4. @AfterTest: Executes after each <test> tag.
  5. @BeforeClass: Runs before the first method in the current class.
  6. @AfterClass: Runs after all methods in the current class.
  7. @BeforeMethod: Executes before each @Test method.
  8. @AfterMethod: Executes after each @Test method.
  9. @Test: Marks a method as a test case. We can use parameters like priority, dependsOnMethods, groups, and dataProvider to add more functionality.

Using these annotations, you can structure your tests effectively by defining setup and teardown methods, which execute at different stages in the test lifecycle.

Example TestNG Annotation Usage:

import org.testng.annotations.*;

public class SampleTest {
    
    @BeforeSuite
    public void beforeSuite() {
        System.out.println("Executed before the entire test suite.");
    }

    @BeforeClass
    public void beforeClass() {
        System.out.println("Executed before any methods in the class.");
    }

    @BeforeMethod
    public void beforeMethod() {
        System.out.println("Executed before each test method.");
    }

    @Test
    public void testMethod1() {
        System.out.println("Executing Test Method 1.");
    }

    @AfterMethod
    public void afterMethod() {
        System.out.println("Executed after each test method.");
    }

    @AfterClass
    public void afterClass() {
        System.out.println("Executed after all methods in the class.");
    }

    @AfterSuite
    public void afterSuite() {
        System.out.println("Executed after the entire test suite.");
    }
}

Output:

This code will execute the @BeforeSuite and @AfterSuite methods only once, while @BeforeMethod and @AfterMethod execute for each test method. This approach is especially useful when tests need specific setup and teardown steps.

Types of Assertions in TestNG

Assertions are essential in automated testing to validate that the application under test behaves as expected. TestNG provides two main types of assertions: hard assertions and soft assertions.

1. Hard Assertions

Hard assertions in TestNG are used to immediately halt the execution of a test if an assertion fails. They’re helpful when it’s critical that the test stops as soon as an unexpected condition occurs.

Example of Hard Assertion:

import org.testng.Assert;
import org.testng.annotations.Test;

public class HardAssertionTest {

    @Test
    public void hardAssertExample() {
        System.out.println("Starting Hard Assertion Test.");
        Assert.assertEquals("Hello", "Hello", "Strings do not match!");
        System.out.println("This line will execute as the assertion passed.");
        Assert.assertTrue(5 > 10, "Condition failed!");
        System.out.println("This line will not execute due to assertion failure.");
    }
}

2. Soft Assertions

Unlike hard assertions, soft assertions allow the test to continue even after an assertion fails. This feature can be beneficial when you want to check multiple conditions in a single test method without stopping the execution at the first failure.

To use soft assertions, you need to create an instance of the SoftAssert class. You must call the assertAll() method at the end of the test method to collect all the results. If any assertion fails, assertAll() will mark the test as failed.

Example of Soft Assertion:

import org.testng.annotations.Test;
import org.testng.asserts.SoftAssert;

public class SoftAssertionTest {

    @Test
    public void softAssertExample() {
        SoftAssert softAssert = new SoftAssert();
        
        System.out.println("Starting Soft Assertion Test.");
        softAssert.assertEquals("TestNG", "TestNG", "String Comparison Failed!");
        System.out.println("This line will execute even if assertion fails.");
        
        softAssert.assertTrue(5 > 10, "Condition failed!");
        System.out.println("This line will also execute even if the previous assertion fails.");
        
        softAssert.assertAll(); // Marks the test as failed if any assertion failed
    }
}

In this example, even though the condition 5 > 10 is false, the program continues execution until softAssert.assertAll() is called. If any of the assertions have failed, assertAll() will report the test as failed.

When to Use Hard vs. Soft Assertions

Knowing when to use hard or soft assertions depends on the test requirements:

  • Hard Assertions: Use when a failed assertion should prevent further execution. This approach is useful for critical checks where subsequent steps would be invalid if the assertion fails.

  • Soft Assertions: Use when you want to verify multiple conditions within a single test without halting the test on the first failure. It’s ideal for non-critical verifications where you want to capture all failures in one go.

Best Practices with Assertions

  1. Use Assertions Strategically: Only use assertions that are meaningful and directly related to your test’s objectives.
  2. Combine Hard and Soft Assertions: In complex test cases, combine both types to gain better control. For example, use hard assertions in setup stages and soft assertions for non-critical checks.
  3. Clear and Descriptive Messages: Provide clear and descriptive messages for each assertion, especially in soft assertions, to identify failed steps easily.

Followers