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 How to run JUnit 4 test cases in JUnit 5

How to run JUnit 4 test cases in JUnit 5

By Pratik Barjatiya, Community Contributor -

JUnit is an effective framework for Selenium that enables test automation of unit testing. This helps the smallest individual chunks of code as a part of Unit Testing using Selenium Framework.

This helps developers check their code and locate bugs or defective functionality right at the early stages if any occur. Although developers largely use the JUnit frameworks, it is also used by the QAs likewise due to its Assertions feature.

This article discusses what JUnit 5 is and how JUnit 4 test cases can be run in JUnit 5.

What Is JUnit 5? How does it work?

JUnit 5 is the latest version of JUnit that consists of 3 special sub-additives:

  1. JUnit Platform, 
  2. JUnit Jupiter, and 
  3. JUnit Vintage. 

Before discussing the components, it is noteworthy that runtime JUnit 5 at least Java 8 as the runtime environment. However, the unit assessments can nonetheless be compiled with the preceding Java variations and examined with JUnit 5. 

JUnit platform is the primary basis of the testing framework, which facilitates framework development. JUnit Jupiter is used for writing the assessments and the JUnit Vintage is used for strolling in advance variations of JUnit tests, so that the tests on older versions like JUnit 3 and JUnit 4 can be run along with the newer tests on JUnit 5.

JUnit 5 vs JUnit 4

Here are the core differences between JUnit 5 and JUnit 4:

  1. In JUnit 4, the whole lot consists and is wrapped collectively in contrast to JUnit 5.  JUnit 5 consists of 3 additives specifically JUnit Platform, JUnit Jupiter, and JUnit Vintage.
  2. JUnit 4 calls for a Java 5 (or above), while JUnit 5 calls for Java 8 (or maybe better).
  3. JUnit 4 doesn`t aid any third-celebration integration plugins and IDEs. In JUnit 5, the JUnit Platform provides aid for build tools and integrated development platforms and famous IDEs like Eclipse, Visual Studio, and IntelliJ.
  4. JUnit Asserts are an essential part of the JUnit framework. In JUnit 4, assertions (or asserts) are grouped below org.junit.Assert package deal which includes all of the announcement techniques. In JUnit 5, assertions techniques are grouped and can be imported from org.junit.jupiter.Assertions
  5. Like assertions, Assumptions techniques also are imported from special programs in JUnit 4 and JUnit 5. In JUnit 4, they’re imported from org.junit.Assume and in JUnit 5 they’re imported from org.junit.jupiter.api.Assumptions
  6. When returning errors/blunders messages in assertions, the order of the parameters differs as seen below

In JUnit 4,

public static void assertEquals(String message, long expected, long actual)

In JUnit 5,

public static void assertEquals(long expected, long actual, String message)

Here are some of the annotations that vary in JUnit 4 and JUnit 5:

JUNIT 4JUNIT 5
@Before@BeforeEach
@After@AfterEach
@BeforeClass@BeforeAll
@AfterClass@AfterAll
@Ignore@Disabled
@Category@Tag

@Rule and @ClassRule annotations in JUnit 4 are removed. Instead, @ExtendWith and @RegisterExtension should be used.

JUnit 4 Operation of @Test annotation

@Test(expected = Exception.class)

public void testThrowsException() throws Exception {

}

JUnit 5 Operation of @Test annotation

@Test

void testThrowsException() throws Exception {

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

    

    });

}

Annotations In JUnit 4 And JUnit 5

Annotations are vital in JUnit, which are listed as follows:

  • @Test – Annotation used to define and declare a test.
  • @RepeatedTest – Annotation used to specify that the function is a template for the tests that can be repeated a specific number of times.
  • @TestFactory– Annotation used for defining a system which is a test plant for robust tests that are generated at runtime.
  • @TestMethodOrder – Annotation used to define the order of carrying out the tests.
  • @DisplayName – Annotation used to specify a custom display name for the function or class.
  • @Tag – Annotation used to filter the tests at function or class position by defining the markers.
  • @Disabled – Annotation used to disable a test system or class.
  • @ParameterizedTest – Annotation used to indicate that the function is a parameterized test. These parameterized tests are analogous to normal test styles but you have to specify a source to give parameters for each incantation which in turn is used in the test.
  • @BeforeEach – Annotation used to specify that the specific test system has to be executed before each@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory system.
  • @AfterEach – Annotation used to specify that the specific test system has to be executed after each@Test, @RepeatedTest, @ParameterizedTest, or @TestFactory system.
  • @BeforeAll – Annotation used to specify that the specific test system has to be executed before all @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory system.
  • @AfterAll – Annotation used to specify that the specific test system has to be executed after all @Test, @RepeatedTest, @ParameterizedTest, or @TestFactory system.
PURPOSEJUNIT 5JUNIT 4
To define and declare a test@Test@Test
To execute before all test methods in the current class@BeforeAll@BeforeClass
To execute before each test method@BeforeEach@Before
To execute after all test methods in the current class@AfterAll@AfterClass
To execute after each test method@AfterEach@After
For tagging and filtering the tests@Tag@Category
To disable a test method or class@Disabled@Ignore
For nested tests@Nested

Step-by-Step Execution Flow Of Annotations In JUnit 5

Let us see the series wherein those annotations are carried out in JUnit 5.

  1. The technique applied below the @BeforeAll annotation is carried out.
  2. The technique applied below the @BeforeEach annotation executes earlier than the primary take a look at.
  3. The technique applied below the @Test annotation is carried out.
  4. The technique applied below the @AfterEach annotation runs after the test is carried out.
  5. The technique applied below the @AfterAll annotation might be carried out on the give up.

In Selenium Automation Testing with the JUnit, you would possibly need to put in force more than one take a look at scenarios (or techniques) below the equal class (or special classes). 

As visible in the sooner part of the JUnit 5 tutorial, it’s vital to understand the execution order of the techniques applied below special annotations.

Here is the order of execution in case there are multiple tests to take a look at techniques withinside the class:

  1. The technique applied below the @BeforeAll annotation is carried out as soon as.
  2. The technique applied below the @BeforeEach annotation executes earlier than the primary take a look at.
  3. The technique applied below the @Test annotation is carried out.
  4. The technique applied below the @AfterEach annotation runs after the take a look at the case is carried out.
  5. The technique applied below the @BeforeEach annotation is carried out earlier than the second test case.
  6. The technique applied below the @Test annotation is carried out.
  7. The technique applied below the @AfterEach annotation is carried out after the execution of the second test case.
  8. The technique that has been annotated with @AfterAll is carried out as soon as on the give up.

Thus, for more than one take a look at instances, the techniques applied below @BeforeAll and @AfterAll annotations are carried out most effective as soon as, at the start and give up of the take a look at.

Alternatively, take a look at the techniques applied below the @BeforeEach and @AfterEach annotations are carried out before and after respectively, for every and each take a look at case.

Migrating Tests from JUnit 4 to JUnit 5

One of the not unusual place questions that involves JUnit customers is `Is it possible to run JUnit 4 assessments in JUnit 5`? By giving up on this phase of JUnit 5 tutorial, you’ll be in a role to run JUnit 4 assessments in JUnit 5. You can migrate assessments written in JUnit 4 to JUnit 5 with minimum effort. 

Here are the steps to carry out the migration:

  1. The JUnit Vintage engine in JUnit 5 facilitates strolling, take a look at instances written in JUnit 4 (or JUnit 3) utilising the JUnit Platform.
  2. Annotations like @Before and @After in present JUnit 4 assessments should get replaced with equal annotations in JUnit 5 (i.e. @BeforeEach and @AfterEach respectively).
  3. Import accurate package deal for Assertions (i.e. org.junit.jupiter.Assertions) and Assumptions
  4. Make absolute the JUnit 4 annotations that are unsupported in JUnit 5 and replace those annotations with the ones supported in JUnit 5.
  5. In case your JUnit 4 design is defined with certain rules, the migration has to be done gradually. There are many rules of JUnit 4 that are compatible with JUnit Jupiter.
  6. The junit-jupiter-migration support module provides support for the @Ignore reflection in JUnit 4 which is original to Jupiter’s @Disabled reflection. Still, this is still in the experimental phase

For instance, let’s perceive how to run the test project that contains unit tests fabricated utilising JUnit 4 and JUnit 5.

Assuming having tests composed utilising JUnit 4. Adding the JUnit 5 tests to it. The pom.xml record would look like below:

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

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>  <groupId>RunJUnitTest</groupId>

<artifactId>RunJUnitTest</artifactId>

<version>1.0-SNAPSHOT</version>

 

<dependencies>

     <dependency>

         <groupId>org.slf4j</groupId>

         <artifactId>slf4j-nop</artifactId>

         <version>1.7.28</version>

         <scope>test</scope>

     </dependency>

     <dependency>

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

         <artifactId>junit-platform-launcher</artifactId>

         <version>1.2.0</version>

     </dependency>

     <dependency>

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

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

         <version>5.2.0</version>

     </dependency>

     <dependency>

         <groupId>org.junit.vintage</groupId>

         <artifactId>junit-vintage-engine</artifactId>

         <version>5.2.0</version>

     </dependency>

     <dependency>

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

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

         <version>5.2.0</version>

         <scope>test</scope>

     </dependency>

     <dependency>

         <groupId>junit</groupId>

         <artifactId>junit</artifactId>

         <version>4.12</version>

         <scope>test</scope>

     </dependency>

     <dependency>

         <groupId>org.slf4j</groupId>

         <artifactId>slf4j-nop</artifactId>

         <version>1.7.28</version>

         <scope>test</scope>

     </dependency>

     <dependency>

         <groupId>org.seleniumhq.selenium</groupId>

         <artifactId>selenium-java</artifactId>

         <version>4.0.0-alpha-7</version>

     </dependency>

     <dependency>

         <groupId>org.seleniumhq.selenium</groupId>

         <artifactId>selenium-remote-driver</artifactId>

         <version>4.0.0-alpha-7</version>

     </dependency>

     <dependency>

         <groupId>org.seleniumhq.selenium</groupId>

         <artifactId>selenium-chrome-driver</artifactId>

         <version>4.0.0-alpha-7</version>

     </dependency>

     <dependency>

         <groupId>junit</groupId>

         <artifactId>junit</artifactId>

         <version>4.12</version>

         <scope>test</scope>

     </dependency>

     <dependency>

         <groupId>org.apache.httpcomponents</groupId>

         <artifactId>httpclient</artifactId>

         <version>4.5.13</version>

     </dependency>

</dependencies>

 

<properties>

     <maven.compiler.source>15</maven.compiler.source>

     <maven.compiler.target>15</maven.compiler.target>

</properties>

</project>

 

JUnit 4 Test

package com.browserstack;




import com.browserstack.local.Local;

import org.apache.http.NameValuePair;

import org.apache.http.client.entity.UrlEncodedFormEntity;

import org.apache.http.client.methods.HttpPut;

import org.apache.http.impl.client.HttpClientBuilder;

import org.apache.http.message.BasicNameValuePair;

import org.json.simple.JSONArray;

import org.json.simple.JSONObject;

import org.json.simple.parser.JSONParser;

import org.junit.After;

import org.junit.Before;

import org.junit.runner.RunWith;

import org.junit.runners.Parameterized.Parameter;

import org.junit.runners.Parameterized.Parameters;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.remote.DesiredCapabilities;

import org.openqa.selenium.remote.RemoteWebDriver;

import org.openqa.selenium.remote.SessionId;




import java.io.FileReader;

import java.io.IOException;

import java.io.UnsupportedEncodingException;

import java.net.URI;

import java.net.URISyntaxException;

import java.net.URL;

import java.util.*;




@RunWith(Parallelized.class)

public class BrowserStackJUnitTest {

public static String username, accessKey;

private static JSONObject config;

public WebDriver driver;

@Parameter(value = 0)

public int taskID;

private Local l;




@Parameters

public static Iterable<? extends Object> data() throws Exception {

     List<Integer> taskIDs = new ArrayList<Integer>();




     if (System.getProperty("config") != null) {

         JSONParser parser = new JSONParser();

         config = (JSONObject) parser.parse(new FileReader("src/test/resources/conf/" + System.getProperty("config")));

         int envs = ((JSONArray) config.get("environments")).size();




         for (int i = 0; i < envs; i++) {

             taskIDs.add(i);

         }

     }




     return taskIDs;

}




public static void mark(SessionId sessionID, String status, String reason) throws URISyntaxException, IOException {

     URI uri = new URI("https://" + username + ":" + accessKey + "@api.browserstack.com/automate/sessions/" + sessionID + ".json");

     HttpPut putRequest = new HttpPut(uri);




     ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

     nameValuePairs.add((new BasicNameValuePair("status", status)));

     nameValuePairs.add((new BasicNameValuePair("reason", reason)));

     putRequest.setEntity(new UrlEncodedFormEntity(nameValuePairs));




     HttpClientBuilder.create().build().execute(putRequest);

}




@Before

public void setUp() throws Exception {

     JSONArray envs = (JSONArray) config.get("environments");




     DesiredCapabilities capabilities = new DesiredCapabilities();




     Map<String, String> envCapabilities = (Map<String, String>) envs.get(taskID);

     Iterator it = envCapabilities.entrySet().iterator();

     while (it.hasNext()) {

         Map.Entry pair = (Map.Entry) it.next();

         capabilities.setCapability(pair.getKey().toString(), pair.getValue().toString());

     }




     Map<String, String> commonCapabilities = (Map<String, String>) config.get("capabilities");

     it = commonCapabilities.entrySet().iterator();

     while (it.hasNext()) {

         Map.Entry pair = (Map.Entry) it.next();

         if (capabilities.getCapability(pair.getKey().toString()) == null) {

             capabilities.setCapability(pair.getKey().toString(), pair.getValue().toString());

         }

     }




     username = System.getenv("BROWSERSTACK_USERNAME");

     if (username == null) {

         username = (String) config.get("user");

     }




     accessKey = System.getenv("BROWSERSTACK_ACCESS_KEY");

     if (accessKey == null) {

         accessKey = (String) config.get("key");

     }




     if (capabilities.getCapability("browserstack.local") != null && capabilities.getCapability("browserstack.local") == "true") {

         l = new Local();

         Map<String, String> options = new HashMap<String, String>();

         options.put("key", accessKey);

         l.start(options);

     }




     driver = new RemoteWebDriver(new URL("https://" + username + ":" + accessKey + "@" + config.get("server") + "/wd/hub"), capabilities);

}




@After

public void tearDown() throws Exception {

     driver.quit();

     if (l != null) l.stop();

}

}

 

JUnit 5 Test

package tests; //*




import org.openqa.selenium.By;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.remote.RemoteWebDriver;

import org.openqa.selenium.remote.SessionId;

import org.openqa.selenium.support.ui.ExpectedConditions;

import org.openqa.selenium.support.ui.WebDriverWait;

import runners.WebDriverTest;

import utils.MarkSessionStatus;




public class SingleTest {




@WebDriverTest

void singleTest(WebDriver driver) {

     SessionId sessionId = ((RemoteWebDriver)driver).getSessionId();

     MarkSessionStatus sessionStatus = new MarkSessionStatus(sessionId);




     try {

         driver.get("https://bstackdemo.com/");

         final WebDriverWait wait = new WebDriverWait(driver, 10);

         wait.until(ExpectedConditions.titleIs("StackDemo"));

         String product_name = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id='1']/p"))).getText();

         WebElement cart_btn = wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//*[@id='1']/div[4]")));

         cart_btn.click();

         wait.until(ExpectedConditions.visibilityOfElementLocated(By.className("float-cart__content")));

         final String product_in_cart = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id='__next']/div/div/div[2]/div[2]/div[2]/div/div[3]/p[1]"))).getText();

         if (product_name.equals(product_in_cart)) {

             sessionStatus.markTestStatus("passed", "Product has been successfully added to the cart!");

         } else {

             sessionStatus.markTestStatus("failed", "There was some issue!");

         }

     } catch (Exception e) {

         sessionStatus.markTestStatus("failed", "There was some issue!");

         System.out.println("Exception: " + e.getMessage());

     }

     driver.quit();

}




//@WebDriverTest

void bstackTest(WebDriver driver) {

     driver.get("https://bstackdemo.com/");

     System.out.println("Test 1: " + Thread.currentThread().getName());

     driver.quit();

}

}


Parallel Tests in JUnit 5

package runners; //*




import org.json.simple.JSONObject;

import org.json.simple.parser.JSONParser;

import org.junit.jupiter.api.extension.*;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.remote.DesiredCapabilities;

import org.openqa.selenium.remote.RemoteWebDriver;

import utils.SetupLocalTesting;




import java.io.FileReader;

import java.net.MalformedURLException;

import java.net.URL;

import java.util.*;

import java.util.stream.Stream;




public class BstackRunner implements TestTemplateInvocationContextProvider {

public WebDriver driver;

public DesiredCapabilities capabilities;

public String username, accesskey, server;

private JSONObject mainConfig;

private JSONObject browserConfig;

private JSONObject profileConfig;

private JSONObject testConfig;

private JSONObject platformConfig;

private JSONObject commonCapsConfig;

private HashMap<String, String> allCapsMap;

private HashMap<String, String> commonCapsMap;




public BstackRunner() {

     this.username = setupCredsAndServer().get("username");

     this.accesskey = setupCredsAndServer().get("accesskey");

     this.server = setupCredsAndServer().get("server");

}




public HashMap<String, String> setupCredsAndServer() {

     try {

         JSONParser parse = new JSONParser();

         mainConfig = (JSONObject) parse.parse(new FileReader("src/test/resources/caps.json"));

         server = (String) mainConfig.get("server");

         username = System.getenv("BROWSERSTACK_USERNAME");

         if (username == null) {

             username = (String) mainConfig.get("user");

         }

         accesskey = System.getenv("BROWSERSTACK_ACCESS_KEY");

         if (accesskey == null) {

             accesskey = (String) mainConfig.get("key");

         }

     } catch (Exception e) {

         System.out.println(e.getMessage());

     }

     HashMap<String, String> creds = new HashMap();

     creds.put("username", username);

     creds.put("accesskey", accesskey);

     creds.put("server", server);

     return creds;

}




@Override

public boolean supportsTestTemplate(ExtensionContext extensionContext) {

     return true;

}




@Override

public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext extensionContext) {

     List<TestTemplateInvocationContext> desiredCapsInvocationContexts = new ArrayList<>();

     //picks the test profile based on the maven command executed - single, local, parallel

     String profile = System.getProperty("config");




     try {

         testConfig = (JSONObject) mainConfig.get("tests");

         profileConfig = (JSONObject) testConfig.get(profile);

         platformConfig = (JSONObject) profileConfig.get("platform");

         commonCapsConfig = (JSONObject) profileConfig.get("common_caps");

         commonCapsMap = (HashMap<String, String>) commonCapsConfig;

         Iterator platformIterator = platformConfig.keySet().iterator();




         while (platformIterator.hasNext()) {

             capabilities = new DesiredCapabilities();

             Iterator commonCapsIterator = commonCapsMap.entrySet().iterator();

             while (commonCapsIterator.hasNext()) {

                 Map.Entry capsName = (Map.Entry) commonCapsIterator.next();

                 capabilities.setCapability((String) capsName.getKey(), capsName.getValue());

             }

             final String platformName = (String) platformIterator.next();

             browserConfig = (JSONObject) platformConfig.get(platformName);

             allCapsMap = (HashMap<String, String>) browserConfig;

             Iterator finalCapsIterator = allCapsMap.entrySet().iterator();

             while (finalCapsIterator.hasNext()) {

                 Map.Entry pair = (Map.Entry) finalCapsIterator.next();

                 capabilities.setCapability((String) pair.getKey(), pair.getValue());

             }

             //Initialising local testing connection

             if (capabilities.getCapability("browserstack.local") != null && capabilities.getCapability("browserstack.local").toString().equals("true")) {

                 HashMap<String, String> localOptions = new HashMap<>();

                localOptions.put("key", accesskey);

                 //Add more local options here, e.g. forceLocal, localIdentifier, etc.

                 SetupLocalTesting.createInstance(localOptions);

             }

             desiredCapsInvocationContexts.add(invocationContext(capabilities));

         }

     } catch (Exception e) {

         System.out.println(e);

     }

     return desiredCapsInvocationContexts.stream();

}




private TestTemplateInvocationContext invocationContext(DesiredCapabilities caps) {

     return new TestTemplateInvocationContext() {




         @Override

         public List<Extension> getAdditionalExtensions() {




             return Collections.singletonList(new ParameterResolver() {

                 @Override

                 public boolean supportsParameter(ParameterContext parameterContext,

                                                  ExtensionContext extensionContext) {

                     return parameterContext.getParameter().getType().equals(WebDriver.class);

                 }




                 @Override

                 public Object resolveParameter(ParameterContext parameterContext,

                                                ExtensionContext extensionContext) {

                     try {

                         driver = new RemoteWebDriver(new URL("https://" + username + ":" + accesskey + "@" + server + "/wd/hub"), caps);

                     } catch (MalformedURLException e) {

                         e.printStackTrace();

                     }

                     return driver;

                 }

             });

         }

     };

}

}

Refer to the BrowserStack’s JUnit Repository on GitHub to learn more about executing JUnit 5 Tests on real devices

Advantages Of Using JUnit 5 For Unit Testing

Some of the core benefits of JUnit 5 are:

  1. Offers specific functions to outline the assessments in evaluation to the preceding versions.
  2. Allows using lambda features withinside the assessments for assertions in addition to assumptions.
  3. Offers distinguished annotations with well-described functions that may be used to beautify the unit assessments.
  4. Allows use of more than one runner.
  5. It has a specific extensible architecture.
  6. Migrates current tests written with preceding JUnit versions.

JUnit testing is the most preferred testing method if the project has been developed in Java. It is powerful and continually evolving for better test case execution. It has become a preferred choice for Test-driven development cycle.

Selenium is a convenient tool when it comes to automated web testing and using it along with JUnit is even more beneficial. JUnit supports multiple assertions and annotations. Using BrowserStack Automate, developers can conveniently run unit testing using Java with Selenium.

However, tests, no matter how well crafted, cannot be regarded as conclusive if they are not run on real devices. Emulators and simulators cannot replicate real user conditions properly, especially when it comes to aspects like weak networks and screen orientation. To compensate for these inadequacies, run tests directly on a real device cloud.

Use parallel testing. Instead of running tests sequentially, parallel testing allows for simultaneous test execution. By running JUnit Tests on cloud Selenium Grid you can run your Unit tests on multiple real browser-device combinations simultaneously, significantly reducing time and effort.

Run JUnit Tests on Real Device Cloud

Tags
Automation Testing Unit Testing Website Testing

Featured Articles

JUnit Testing Tutorial: JUnit in Java

Test Automation using JUnit Annotations and Selenium

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack