Category Archives: Testing

JUnit 5 Tutorial – New Features with Examples

What is JUnit?

It is an opensource testing framework which performs unit testing on Java based application. The current version is JUnit 5.

What’s New in JUnit 5?

Unlike its previous version, JUnit 5 is composed of several different modules from three different sub directories. (JUnit 5 requires Java 8 at run-time)

JUnit 5JUnit Platform + JUnit Jupiter + JUnit Vintage

1. JUnit Platform:

a) It serves as a foundation for launching testing frameworks on JVM.

b) It defines TestEngine API for developing testing framework that runs on the platform.

c) It provides console launcher to launch the platform from command line.

d) It provides build plugin for maven and Gradle as well as a JUnit4 based runner for running any TestEngine on platform.

2. JUnit Jupiter:

a) It is the combination of new programming model and extension model for writing tests and extensions.

b) It provides a TestEngine for running Jupiter based tests on platform.

3. JUnit Vintage:

a) It provides a TestEngine for running junit 3 and junit 4 based tests on platform.

Installation Guide of JUnit 5:

To install JUnit 5 in the application, please add the following maven dependencies in the respective pom.xml.


 <dependencies>
<!-- JUnit Platform -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-commons</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-engine</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-gradle-plugin</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.0.0-M2</version>
</dependency>

<!-- JUnit Jupiter -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.0.0-M2</version>
</dependency>

<!-- JUnit Vintage -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>4.12.0-M2</version>
</dependency>
</dependencies>

Example: FirstJunit5Test.java


/**
*
*/
package com.abhi.junit5.learning;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
* @author Abhinav
*
*/
@RunWith(JUnitPlatform.class)
class FirstJunit5Test {

@Test
void testCaseFirst(){
assertEquals(2, 1+1);
}

@Test
@CustomTag
void failingTest() {
fail("Failing for failing's sake.");
}
}

JUnit 5 Annotations:

. @Test : It denotes that annoted method is a test method. It does not declare any attributes, since test extensions in junit jupiter operate based on their own annotations.

. @TestFactory : It denotes that annoted method is a test factory for dynamic tests*.

. @DisplayName : It declares the custom display names for the test class or test method. It could be the text with blank spaces, special characters, and even emojis.

. @BeforeEach : It denotes that the annoted method should be executed before each @Test annoted method. Such methods are inherited. Similar to junit 4 @Before.

. @AfterEach : It denotes that the annoted method should be executed after each @Test annoted method. Such methods are inherited. Similar to junit 4 @After.

. @BeforeAll : It denotes that the annoted method should be executed before all @Test annoted method. Such methods must be static and inherited. Similar to junit 4 @BeforeClass.

. @AfterAll : It denotes that the annoted method should be executed after all @Test annoted method. Such methods must be static and inherited. Similar to junit 4 @AfterClass.

. @Nested : It denotes that the annoted class is a nested, non static test class. @BeforeAll and @AfterAll annotations cannnot be used in @Nested test class.

. @Tag : It is used for filtering the test cases either at class or method level. Similar to junit 4 TestNG or categories.

. @Disabled : It is used to disable a test class or test method. Similar to junit 4 @ignore.

. @ExtendWith : It is used to register custom extensions*.

Meta Annotations and Composed Annotations:

In JUnit Jupiter you can define your own custom composed annotations that will automatically inherit the semantics of its meta-annotations.
Example: CustomTag.java

Sample Test Case example: BasicJUnit5Test.java


/**
 *
 */
package com.abhi.junit5.learning;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Sample test class for showcasing the annotations")
class BasicJUnit5Test {

@BeforeAll
 static void beforeALL(){
 System.out.println("It will execute once before executing all the Test case");
 }

 @BeforeEach
 void beforeEach(){
 System.out.println("It will execute each time before executing the Test case");
 }

 @Test
 void passedTestCase(){
 System.out.println("Success Test case");
 }

 @Test
 void failedTestCase(){
 System.out.println("Failed Test case");
 }

 @Test
 @Disabled("For demo purpose")
 void disabledTestCase(){
 System.out.println("Ignored Test case");
 }

 @AfterEach
 void afterEach(){
 System.out.println("It will execute each time after executing any Test case");
 }

 @AfterAll
 static void afterAll(){
 System.out.println("It will execute once After executing all Test case");
 }
}

JUnit 5 Assertions:

JUnit 5 have many assertions methods packaged under JUnit Jupiter. Their are few new assertion methods introduce in JUnit 5 to support the Java 8 lambda expression feature. Else most of them are similar what we had in JUnit 4.

Example: AssertionsJunit5.java


/**
 *
 */
package com.abhi.junit5.learning;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import static org.junit.jupiter.api.Assertions.*;
/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Assertions in JUnit5")
public class AssertionsJunit5 {

@Test
 @DisplayName("Test case to show standard assertion methods.")
 void basicAssertions(){
 assertEquals("Abhi", "Abhi");
 assertNotEquals(4, 2, ()-&amp;amp;gt;"Assertion not equals message.");
 assertTrue(3&amp;amp;gt;2, ()-&amp;amp;gt;"Assertion messages can be lazily evaluated to avoid constructing complex messages unnecessarily.");
 }

 @Test
 @DisplayName("Test case to show Grouped assertion methods.")
 void newAssertion(){
 assertAll("Group Assertions",
 ()-&amp;amp;gt;assertEquals("Abhi", "Abhi"),
 ()-&amp;amp;gt;assertNotEquals(4, 3, ()-&amp;amp;gt;"Assertion not equals message."),
 ()-&amp;amp;gt;assertTrue(3&amp;amp;gt;2, ()-&amp;amp;gt;"Assertion messages can be lazily evaluated to avoid constructing complex messages unnecessarily.")
 );
 }

 @Test
 @DisplayName("Test case to show exception handle through assertion methods.")
 void exceptionAssertion(){
 Throwable exception = expectThrows(NullPointerException.class, ()-&amp;amp;gt;{ throw new NullPointerException("Got exception message");
 });

 assertEquals("Got exception message", exception.getMessage());
 }
}

JUnit 5 Assumptions:

Junit 5 have many assumption methods packaged under JUnit Jupiter. Their are few new assumption methods introduce to support the Java 8 lambda expression feature. Else most of them are similar what we had in JUnit 4.

Example: AssumptionsBasic.java


/**
 *
 */
package com.abhi.junit5.learning;

import static org.junit.jupiter.api.Assumptions.*;
import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

/**
 * @author Abhinav
 *
 */
@RunWith(JUnitPlatform.class)
@DisplayName("Assumptions in JUnit5")
public class AssumptionsBasic {

@BeforeAll
 static void setUp(){
 System.setProperty("TestEnv", "JUnit5");
 System.setProperty("Environment", "Stage");
 }

 @Test
 void showAssumeTrue(){
 assumeTrue("Stage".equals(System.getProperty("Environment")), ()-&amp;amp;gt; "Not on development environment");
 }

 @Test
 void showAssumptionBasic(){
 assumingThat("JUnit5".equals(System.getProperty("TestEnv")),
 ()-&amp;amp;gt;{
 assertEquals(2, 2);
 System.out.println("Inside assumption");
 });

 }
}

You can checkout/clone the JUnit 5 example repository from the mentioned path – https://github.com/erabhinavrana/my-junit5-learning

 

Advertisements

Cucumber with Java – Behavior Driven Development

About Cucumber :

Cucumber is a testing tool that supports Behavior Driven Development (BDD) framework. It defines application behavior using simple English text, defined by a language called Gherkin. Cucumber can be defined as a testing framework, driven by plain English text. It serves as documentation, automated tests, and a development aid – all in one.

Advantages of Cucumber over other tools :

  1. Cucumber supports different languages like Java.net and Ruby.
  2. It acts as a bridge between the business and technical language. We can accomplish this by creating a test case in plain English text called feature file.
  3. It allows the test script to be written without knowledge of any code, it allows the involvement of non-programmers as well.
  4. It serves the purpose of end-to-end test framework unlike other tools.
  5. Due to simple test script architecture, Cucumber provides code re usability.

Feature file:

Each independent functionality of the product under test can be termed as a feature when we talk about Cucumber.

A simple feature file consists of the following keywords/parts :

  1. Feature : Name of the feature under test.
  2. Description (optional) : Describe about feature under test.
  3. Scenario : What is the test scenario.
  4. Given : Prerequisite before the test steps get executed.
  5. When : Specific condition which should match in order to execute the next step.
  6. Then : What should happen if the condition mentioned in When is satisfied.
  7. And & But : It can be used with any other keywords like Given, When and Then.
  8. “”” : It represent the Doc Strings.
  9. | : It represents Data Tables.
  10. @ : It represents Tags/Labels to group Scenarios.
  11. <> : It represents placeholder.
  12.  # : It represents Comments.

Cucumber has got the following few annotations:

Given: It defines the prerequisite for the test to be executed

  • Example:
    GIVEN I am at google search page

When: It defines the trigger point for any test scenario execution.

  • Example:
    WHEN I enter “<search-text>”

Then: It holds the expected result for the test to be executed.

  • Example:
    THEN search result should be successfully listed.

And: It provides the logical AND condition between any two statements. AND can be used in conjunction with GIVEN, WHEN and THEN statement.

  • Example:
    WHEN I enter “<search-text>” AND I clicked on “<search button>”

But: It signifies logical OR condition between any two statements. OR can be used in conjunction with GIVEN, WHEN and THEN statement.

  • Example:
    THEN search should be successful. BUT search home page should not be missing

Scenario: It defines the details of the test scenario.

  • Example:
    Given I am a word press blog user
    WHEN I enter blog name in search-text
    AND I click on search button
    Then Search blog page should be opened

Background: It defines the common instructions that will be executed before each                                           scenario runs.

  • Example :
    Background Go to word-press blog page

Scenario outline: It replaces variable/keywords with the value from the table. Each row in                                      the table is considered to be a scenario.

  • Example :
    Scenario Outline: Search available Abhinav Blogs
    When I enter ‘<blogValue>’ in the search text
    And I clicked on search action
    Then ‘<blogName>’ should be opened

| blogValue        | blogName                           |
| TDD              | Software development Process : TDD and BDD |
| Design Pattern   | Chain of responsibility design pattern     |
| Git              | Git commands                               |
| Date             | Date Format Utility with ThreadLocal   |

The example of feature file to test the scenario of searching the given blog in word press:

blogsearch.feature


#Author: Abhinav rana
#Feature Definition for searching available blogs

@tag
Feature: Blog Search

Background: User navigates to wordpress site
Given I am on Abhinav Rana blog site

Scenario: Search TDD and BDD blog
When I enter &amp;quot;TDD&amp;quot; in the search text
And I clicked on search action
Then &amp;quot;Software development Process : TDD and BDD&amp;quot; blog should be opened

Scenario: Search Design pattern blog
When I enter &amp;quot;design pattern&amp;quot; in the search text
And I clicked on search action
Then &amp;quot;Chain of Responsibility Design Pattern&amp;quot; blog should be opened

Scenario: Search Git command blog
When I enter &amp;quot;Git&amp;quot; in the search text
And I clicked on search action
Then &amp;quot;Git commands&amp;quot; blog should be opened

Scenario: Search Design pattern blog
When I enter &amp;quot;Date&amp;quot; in the search text
And I clicked on search action
Then &amp;quot;Date Format Utility with ThreadLocal&amp;quot; blog should be opened

&amp;lt;p style=&amp;quot;text-align: justify;&amp;quot;&amp;gt;

Step Definitions file:

Steps definition file stores the mapping between each step of the scenario defined in the feature file with a code of function to be executed.

The example of step definition or glue file for the above given feature file:

BlogSearch.java


package com.abhi.cucumber.glue;

import junit.framework.Assert;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import cucumber.annotation.en.And;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;

public class BlogSearch {

WebDriver webDriver = null;

@Given(&amp;quot;^I am on Abhinav Rana blog site$&amp;quot;)
public void I_am_on_Abhinav_Rana_blog_site() throws Throwable {
webDriver = new ChromeDriver();
webDriver.navigate().to(&amp;quot;https://abhinavranaweb.wordpress.com/blog/&amp;quot;);
}

@When(&amp;quot;^I enter \&amp;quot;([^\&amp;quot;]*)\&amp;quot; in the search text$&amp;quot;)
public void I_enter_in_the_search_text(String searchTxt) throws Throwable {
webDriver.findElement(By.name(&amp;quot;s&amp;quot;)).sendKeys(searchTxt);
}

@And(&amp;quot;^I clicked on search action$&amp;quot;)
public void I_clicked_on_search_action() throws Throwable {
webDriver.findElement(By.name(&amp;quot;submit&amp;quot;)).submit();
}

@Then(&amp;quot;^\&amp;quot;([^\&amp;quot;]*)\&amp;quot; blog should be opened$&amp;quot;)
public void blog_should_be_opened(String arg1) throws Throwable {

Assert.assertNotNull(By.partialLinkText(arg1));
Assert.assertNotNull(webDriver.findElement(By.partialLinkText(arg1)));
Assert.assertEquals(&amp;quot;Blog Title Matched&amp;quot;, webDriver.findElement(By.partialLinkText(arg1)).getText(), arg1);
webDriver.findElement(By.partialLinkText(arg1)).click();
webDriver.close();
}

}

The example of Runnable file for the above given feature and its glue code is:

BlogSearchRunner.java

/**
*
*/
package com.abhi.cucumber.runner;

import org.junit.runner.RunWith;

import cucumber.junit.Cucumber;

/**
* @author Abhinav
*
*/

@RunWith(Cucumber.class)
@Cucumber.Options(format = {&quot;pretty&quot;,&quot;html:target/cucumber&quot;},
features = {&quot;com/abhi/cucumber/feature&quot;},glue = {&quot;com.abhi.cucumber.glue&quot;})
public class BlogSearchRunner {

}

You can checkout/clone the cucumber example repository from the mentioned path – https://github.com/erabhinavrana/my-cucumber-basic

Software development Process : TDD and BDD

Software development Process:

A software development process or life cycle is a structure imposed on the development of a software product. There are several models for such processes, each describing approaches to a variety of tasks or activities that take place during the process.
Two most known development process are:

TDD (Test driven development):

It is an iterative development process. In this process we first write test cases for our business requirement. Initially these test cases will get failed. After that we start writing the application code and retest the test cases. If some of the test cases are getting failed then we need to write the code for making those test cases passed. And this iteration will keep running till the time comes when all the test cases starts getting passed.

At last when all test cases passed that means all the business logic for which test cases written have been implemented and working as expected.

Benefits of Test Driven Development:

  • Test first environment for development turns out to be bug free code.
  • Each Iteration we write test cases and it turns out to be automated regression pack. It ensures that earlier features are working fine.
  • These test cases serves as documentation and helps in future reference.

Drawback of Test Driven Development:

  • It should be consider as a part of your project estimation.
  • The maintenance of test project is an overhead of a project.
  • Rewrite the test case when requirement got changed.

TDD tools : JUnit

BDD (Behavior driven development):

Behavior Driven Development approach of testing is an extension of Test Driven Development approach. Similar to TDD in BDD also we write test case first and then add the application code to make that test case get passed.

The major difference we will see here are:

  • Test cases are written in plain descriptive English language.
  • Test cases are more focused on the behavior of application and more user focused.

Benefits of Behavior Driven Development:

  • It is driven by business values.
  • It act as a bridge between Business & Technical language.

BDD Tools : Cucumber or SpecFlow

Cucumber:

  • It is a testing framework which supports BDD (Behavior driven development).
  • It defines the application in a plain simple English language called Gherkin(Feature file).
  • It is itself written in a ruby but can be used with any other language like java, c#, python etc.

Spec-Flow:

Spec-flow inspires from cucumber framework. It brings the same concept to the .Net world.

Need of cucumber (BDD Framework):

  • Cucumber directly interacts with the developer code but the tests are written in a language that is quite easy to understand by the stakeholders.
  • It removes many misunderstandings long before it creates any issues in the code.
  • It reduces the scope of rework.

Example of BDD feature file:

Feature: Blog post

Blog post should be easy and friendly

Scenario: Successful blog post
User should get a confirmation mail and the URL of recently posted blog

Given I have chosen to post a blog
When I post a blog with valid details
Then I should receive a confirmation email
And I should see a URL of recently posted blog

Scenario: Failure blog post
Someone tries to post a blog with incorrect details

Given I have chosen to post a blog
When I post a blog with invalid details
Then I should be told that the details are not correct
And I should be offered the option to correct the details

 

To know more about cucumber implementation, visit Cucumber with Java – Behavior Driven Development