App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Get Started free
Home Guide JUnit Vs TestNG: Differences Between JUnit and TestNG

JUnit Vs TestNG: Differences Between JUnit and TestNG

By Sandra Felice, Community Contributor -

Testing is integral to the Software Development Life Cycle. As technology evolves toward the digital era, testing becomes more of a necessity than a requirement. Testing helps eliminate gaps, errors, or missing requirements in the present system compared to the expected behavior. And one such type of testing is unit testing.

Unit testing refers to testing small units or chunks of code individually and independently. It is the first step during functional testing. It is performed to detect defects early by the developers. It helps in saving costs by detecting bugs early in the lifecycle. There are two types of Unit Testing – Manual testing and Automated Testing.

This article helps you understand more about the two most used Unit testing frameworks – JUnit and TestNG. 

What is JUnit?

JUnit is an open-source unit testing framework for Java. As the name suggests, it is used to test small code units. It is a part of the xUnit architecture. This framework is used by default by Java developers to write as well as execute test cases. 

JUnit follows the approach of “testing first then coding”. This emphasizes setting up test data and testing the small piece of code first and then implementing the same. This increases productivity and helps in improving code stability. JUnit 5 is the latest version of JUnit, with the current release being 5.7.1.

Features of JUnit

  1. It is an open-source framework enabling developers to write and test codes fast, thereby increasing the code quality.
  2. It provides several test annotations to identify test methods.
  3. It provides several assertions to test expected results.
  4. It provides test runners for running tests.
  5. It runs automatically and provides immediate feedback.
  6. It supports debugging of the scripts enabling developers to develop scripts faster.
  7. The latest version – JUnit5 focuses on Java 8 and above.

Test Setup of JUnit

1. Installing and Setting Up

  • JUnit requires Java Version 8 and above.
  • Download Java from here
  • Download JUnit 5 jars (for Java project) from here
  • Open your project and add these external jars through the build path configuration.
  • Set up environment variables.
  • Add the below dependency in pom.xml for running JUnit tests.
<dependencies>

        <dependency>

            <groupId>org.junit.jupiter</groupId>

            <artifactId>junit-jupiter-engine</artifactId>

                  <version>5.7.1</version>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.junit.platform</groupId>

            <artifactId>junit-platform-runner</artifactId>

            <version>5.7.1</version>

            <scope>test</scope>

        </dependency>

        <dependency>

            <groupId>org.junit.jupiter</groupId>

            <artifactId>junit-jupiter-api</artifactId>

            <version>5.7.1</version>

                  <scope>test</scope>

              </dependency>

    </dependencies>

2. Test Suites

The test suite consists of a collection of test cases that lets you run the test cases simultaneously. It’s like a logical grouping of test cases.

JUnit 5 uses @RunWith and @Suite Classes for creating Test Suites.

@RunWith(Suite.class)

 @Suite.SuiteClasses({

   JUnitTestSuiteDemo1.class,

    JUnitTestSuitDemo2.class

  })

3. Test Annotations

JUnit 5 is an annotation-based framework. Annotations are tags that provide additional information about the test methods or the class. They are usually represented by ‘@’.

Some popular annotations of JUnit 5 include:

  • @Test – The MAIN business logic of a program resides here.
  • @BeforeAll – Executes before the first test method of the class runs
  • @AfterAll – Executes after all the test methods of the current class runs
  • @BeforeEach – Executes before each test method
  • @AfterEach – Executes after each test method

4. Exceptions Handling

Exception handling is done via Assertions.assertThrows() API. assertThrows() method asserts that the code throws an exception of the given type when executed. This method fails if there is no exception or exception of some other type.

@Test

void testExpectedException() {

    Assertions.assertThrows(NumberFormatException.class, () -> {

        Integer.parseInt("Hello World"); //would fail since input is not a valid number

    });

}

5. Ignoring Tests

Ignoring tests is important in an automation framework since some test cases can become redundant due to changed requirements or may have to be avoided for some reason. This can be done using @Ignore in JUnit 5.

@Ignore

public void oldTest(){

    System.out.println("This test to be ignored");

}

@Test

public void newTest(){

    System.out.println("Test has been executed");

}

6. Grouping Tests

Grouping tests help in identifying the tests and executing them quickly. JUnit 5 uses @Tag to group the tests.

    @Test

    @Tag("Smoke")

    public void Test_a(){

        System.out.println("Testa has been executed");

    }

    @Test

    @Tag("Smoke")

    public void Test_b(){

        System.out.println("Testb has been executed");

    }

7. Parameterizing Tests

Parameterizing Tests helps test the same test scenario with different sets of inputs. In JUnit 5, the following dependency needs to be added to parameterize the tests along with @ParameterizedTest.

<dependency>

   <groupId>org.junit.jupiter</groupId>

   <artifactId>junit-jupiter-params</artifactId>

   <version>5.7.1</version>

   <scope>test</scope>

</dependency>


@ParameterizedTest

@ValueSource(ints = {1, 3, 5, -3, 15, Integer.MAX_VALUE}) // six numbers

void isOdd_ShouldReturnTrueForOdd(int num) {

    assertTrue(Numbers.isOdd(num));

}

Writing JUnit Test cases

A simple JUnit test case will look something like this.

 import org.junit.jupiter.api.AfterAll;

    import org.junit.jupiter.api.AfterEach;

    import org.junit.jupiter.api.Assertions;

    import org.junit.jupiter.api.BeforeAll;

    import org.junit.jupiter.api.BeforeEach;

    import org.junit.jupiter.api.Disabled;

    import org.junit.jupiter.api.Tag;

    import org.junit.jupiter.api.Test;

    import com.howtodoinjava.junit5.examples.Calculator;

    public class DemoApp {

        @BeforeAll

        static void setupFirst(){

            System.out.println("@BeforeAll executed");
        }

        @BeforeEach

        void setupSecond(){

            System.out.println("@BeforeEach executed");
        }
 
        @Tag("DEV")

        @Test

        void testCalculatorOne()

        {

            System.out.println("======TEST ONE ADD EXECUTED=======");

            Assertions.assertEquals( 8 , Calculator.add(4, 4));

        }
  
        @Tag("PROD")

        @Disabled

        @Test

        void testCalculatorTwo()

        {

            System.out.println("======TEST TWO ADD EXECUTED=======");

            Assertions.assertEquals( 10 , Calculator.add(6, 4));

        }

        @AfterEach

        void tearThis(){

            System.out.println("@AfterEach executed");

        }
   
        @AfterAll

        static void tear(){

            System.out.println("@AfterAll executed");

        }

    }

What is TestNG?

TestNG is a Java-based test automation framework that was inspired by JUnit. It overcomes all the limitations of JUnit along with additional functionalities. This makes it more powerful and easier to use. NG here stands for “Next Generation”.

It is designed to cover a range of test categories such as Unit testing, Functional testing, Integration testing, etc. It is extremely popular and helps testers organize the test cases in a structured way. This helps in maintaining the readability of the scripts. The current version of TestNG is 7.6.0.

Features of TestNG

  • It’s an open-source testing framework.
  • It uses more Java features.
  • It supports multiple Before and After test annotations.
  • It supports XML-based test configurations.
  • It supports the parameterization of test methods.
  • It supports multi-threading testing.
  • It allows users to perform data-based testing.
  • It allows for report generation using HTML and XML reports.
  • It contains open APIs which are publicly available to the developers.
  • It supports execution in parallel.

Test Setup of TestNG

1. Installing and setting up

  • Download Java from here
  • Download TestNG jar (for Java project) from here
  • Open your project and add these external jars through Build path configuration.
  • Add the below dependency in pom.xml for running TestNG tests.
<dependency>

    <groupId>org.TestNG</groupId>

    <artifactId>TestNG</artifactId>

    <version>7.6.0</version>

    <scope>test</scope>

</dependency>

2. Test Suites

In TestNG, Test Suites are defined in an XML file.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE suite SYSTEM "http://TestNG.org/TestNG-1.0.dtd">

    <suite name="TestSuite" parallel="tests">

        <test name="DemoTest">

           <classes>

            <class name="com.pages.LoginPageTest"></class>

            <class name="com.pages.HomePageTest"></class>

            <class name="com.pages.ProductPageTest"></class>

           </classes>

        </test>

</suite>

3. Test Annotations

Some popular annotations of TestNG include:

  • @Test – MAIN program logic place
  • @BeforeClass – Executes before the first test method of the class
  • @AfterClass – Executes after all the test methods of the current class
  • @BeforeMethod – Executes before each test method
  • @AfterMethod – Executes after each test method

4. Exceptions Handling

Exception handling is done via the expectedExceptions parameter along with @Test annotation. 

@Test(expectedExceptions = ArithmeticException.class)

public void DivideByZeroTest() {

    int i = 20/0;

}

5. Ignoring Tests

Ignoring tests can be done by passing a parameter in the @Test method.

    @Test

    public void test1() {

        System.out.println("This is test1");

    } 

    @Test(enabled = false)

    public void test2() {

        System.out.println("This is test2");

    }

6.Grouping Tests

Grouping tests can be done by passing parameters in the @Test method.

    @Test(groups = { "Sanity", "Regression" })

    public void test_method1()

    {

        //Test implementation

    }

7. Parameterizing Tests

Parameterizing tests are done by @Parameters. The parameter value is passed in the TestNG XML file.

    @Test()

    @Parameters("username")

    public void test1(String username) {

        System.out.println("The username "+username + " is passed");

    }




    <test name="DemoTest">

        <parameter name = "username" value = "Alex"/>

Parameterizing tests can also be done by @DataProviders. It enables multiple input values to test.

@Test(dataProvider = "credentials")

Writing TestNG Test cases

A simple TestNG test case will look something like this.

package newtest.com;

import org.testng.annotations.Test;

import org.testng.annotations.BeforeMethod;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.DataProvider;

import org.testng.annotations.BeforeClass;

import org.testng.annotations.AfterClass;

import org.testng.annotations.BeforeTest;

import org.testng.annotations.AfterTest;

import org.testng.annotations.BeforeSuite;

import org.testng.annotations.AfterSuite;
 

public class NewTestng {

  @Test(dataProvider = "dp")

  public void f(Integer n, String s) {

      System.out.println(" *Parameterized method*");    

      System.out.println("Integer "+n+" String "+s);

  }

  @BeforeMethod

  public void beforeMethod() {

      System.out.println("Before Method");

  }

@AfterMethod

  public void afterMethod() {

      System.out.println("After Method");

  }

  @DataProvider

  public Object[][] dp() {

    return new Object[][] {

      new Object[] { 1, "a" },

      new Object[] { 2, "b"},

    };

  }

  @BeforeClass

  public void beforeClass() {

      System.out.println("Before Class");

  }

  @AfterClass

  public void afterClass() {

      System.out.println("After Class");

  }

  @BeforeTest

  public void beforeTest() {

      System.out.println("Before Test");

  }

  @AfterTest

  public void afterTest() {

      System.out.println("After Test");

  }

  @BeforeSuite

  public void beforeSuite() {

      System.out.println("Before Suite");

  }

  @AfterSuite

  public void afterSuite() {

      System.out.println("After Suite");

  }

}

JUnit vs TestNG: Core Differences

Here is the tabular comparison between JUnit and TestNG:

CriteriaJUnitTestNG
FrameworkOpen Source Testing frameworkOpen Source Java-based Testing framework
Supported TestingUnit TestingUnit Testing, Functional Testing, Integration Testing, end-to-end Testing, etc.
AnnotationsDo not support advanced annotation like @BeforeGroups, @AfterGroupsSupports advanced and unique annotations like @BeforeGroups, @AfterGroups
Test SuiteUses @RunWith, @Suite to run the test suiteUses an XML file to run the test suite
Dependency TestsMissing Dependency testsSupports Dependency Tests
Grouping TestsDoes not provide Grouping of test cases together Allows Grouping and executing of test cases together
Order of TestsDoes not supportSupports ordering of test methods via a priority attribute
AssumptionsSupports Assumptions to skip tests based on certain conditionsDoes not support Assumptions
Custom NameProvides provision for Custom descriptive names for testsDoes not provide Custom names
ReportingIntegrates with Maven to generate HTML reportsHas built-in HTML reports
ListenersSupports listeners through Listeners APISupports listeners through annotations
Ease of useRunning tests requires a certain amount of dependency

Eg. for parameterization, one might need JUnit Jupiter

Writing and running tests is very easy

JUnit and TestNG are popular test automation frameworks in the Java community and used widely by people. TestNG however, only provides a few additional features in comparison to Junit. Hence, the choice of the “right” testing framework for test automation is purely based on the project requirements and flexibility. 

Irrespective of whether you choose TestNG or JUnit, the true potential of these frameworks can only be exploited by running the tests on real browsers and devices under real user conditions. BrowserStack offers a Cloud-based Selenium grid of 3000+ real browsers and devices for testing purposes. BrowserStack allows you to perform manual and automated tests using different frameworks and languages. You can seamlessly run Selenium, Cypress, Playwright, and Puppeteer tests on 3000+ devices and browsers.

Start Testing now

Tags
Automation Frameworks Automation Testing

Featured Articles

JUnit vs NUnit: Framework Comparison

TestNG vs Cucumber: Core Differences

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack