Testing of Web Application using Serenity with JUnit4

HOME

In the previous tutorial, I have explained Serenity BDD with Cucumber for Web Application. In this tutorial, I will explain the Integration of Serenity with JUnit4. This tutorial gives an idea of how to set up a new project where we like to use Serenity as BDD Framework and JUnit as a Testing framework.

Pre-Requisite

  1. Java 11 installed
  2. Maven installed
  3. Eclipse or IntelliJ installed

This framework consists of:

  1. Java 11
  2. Maven – 3.8.1
  3. Serenity – 2.6.0
  4. Serenity Maven – 2.6.0
  5. JUnit – 4.13.2
  6. Maven Surefire Plugin – 3.0.0-M5
  7. Maven Failsafe Plugin – 3.0.0-M5
  8. Maven Comiler Plugin – 3.8.1

Implementation Steps

  1. Update Properties section in Maven pom.xml
  2. Add repositories and pluginRepository to Maven pom.xml
  3. Add Serenity and JUnit dependencies to POM.xml
  4. Update Build Section of pom.xml
  5. Create test code under src/test/java folder
  6. Create NavigateActions class under src/test/java
  7. Create Page Object Classes – StepLoginPage, StepDashBoardPage and StepForgetPasswordPage under src/test/java
  8. Create serenity.conf file under src/test/resources
  9. Create serenity.properties file in the root of the project
  10. Run the tests through commandline which generates Serenity Report

Project Structure

This project consists of various classes – ApplicationLoginTests (This is the Test Class which is going to contain all the tests). NavigationActions is the Action class that is used to open the webpage or application. StepLoginPage, StepDashboardPage, and StepForgotPasswordPage are the Page Object classes that contain multiple functionalities of that page and that helps to keep the code clean.

Step 1 – Update Properties section in Maven pom.xml

 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <serenity.version>2.6.0</serenity.version>
    <serenity.maven.version>2.6.0</serenity.maven.version>
    <junit.version>4.13.2</junit.version>
    <maven.surefire.plugin.version>3.0.0-M5</maven.surefire.plugin.version>
    <maven.failsafe.plugin.version>3.0.0-M5</maven.failsafe.plugin.version>
    <maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>

Step 2 – Add repositories and pluginRepository to Maven pom.xml

<repositories>
        <repository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray</name>
            <url>https://jcenter.bintray.com</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <id>central</id>
            <name>bintray-plugins</name>
            <url>https://jcenter.bintray.com</url>
        </pluginRepository>
    </pluginRepositories>

Step 3 – Add Serenity and JUnit dependencies to POM.xml

<dependencies>
   <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-core</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-junit</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>
      
        <dependency>
            <groupId>net.serenity-bdd</groupId>
            <artifactId>serenity-screenplay-webdriver</artifactId>
            <version>${serenity.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>      
</dependencies>

Step 4 – Update Build Section of pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${maven.surefire.plugin.version}</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>${maven.failsafe.plugin.version}</version>
                <configuration>
                    <includes>
                        <include>**/*.java</include>
                    </includes>
                    <parallel>methods</parallel>
                    <useUnlimitedThreads>true</useUnlimitedThreads>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                </configuration>
            </plugin>
           <plugin>
               <groupId>net.serenity-bdd.maven.plugins</groupId>
               <artifactId>serenity-maven-plugin</artifactId>
               <version>${serenity.version}</version>
               <dependencies> 
                  <dependency>
                       <groupId>net.serenity-bdd</groupId>
                       <artifactId>serenity-single-page-report</artifactId>
                       <version>${serenity.version}</version>
                  </dependency>                
               </dependencies>
               <configuration>
                   <tags>${tags}</tags>
                   <reports>single-page-html</reports> 
               </configuration>
               <executions>
                  <execution>
                      <id>serenity-reports</id>
                      <phase>post-integration-test</phase>
                      <goals>
                          <goal>aggregate</goal>
                      </goals>
                   </execution>
               </executions>
           </plugin>
        </plugins>
    </build>
</project>

Step 5 – Create Test Class – ApplicationLoginTests under src/test/java folder

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;

import net.serenitybdd.core.Serenity;
import net.serenitybdd.junit.runners.SerenityRunner;
import net.thucydides.core.annotations.Managed;
import net.thucydides.core.annotations.Steps;
import net.thucydides.core.annotations.Title;

@RunWith(SerenityRunner.class)
public class ApplicationLoginTests {

	@Managed
	WebDriver driver;

	@Steps
	NavigateActions navigate;

	@Steps
	StepLoginPage loginPage;

	@Steps
	StepDashBoardPage dashboardPage;

	@Steps
	StepForgotPasswordPage forgetPasswordPage;

	@Test
	@Title("Login to application with valid credentials navigates to DashBoard page")

	public void successfulLogin() {

		// Given
		navigate.toTheHomePage();

		// When
		loginPage.inputUserName("Admin");
		loginPage.inputPassword("admin123");
		loginPage.clickLogin();

		// Then
		Serenity.reportThat("Passing valid credentials navigates to DashBoard page",
				() -> assertThat(dashboardPage.getHeading()).isEqualToIgnoringCase("DashBoard"));
	}

	@Test
	@Title("Login to application with invalid credential generates error message")
	public void unsuccessfulLogin() {

		// Given
		navigate.toTheHomePage();

		// When
		loginPage.inputUserName("Admin");
		loginPage.inputPassword("admin1232");
		loginPage.clickLogin();

		// Then
		Serenity.reportThat("Passing invalid credentials generates error message",
				() -> assertThat(loginPage.loginPageErrorMessage()).isEqualToIgnoringCase("Invalid credentials"));
	}

	@Test
	@Title("Verify Forgot your password link")
	public void clickForgetPasswordLink() {

		// Given
		navigate.toTheHomePage();

		// When
		loginPage.clickForgetPasswordLink();

		// Then
		Serenity.reportThat("Open Forget Password Page after clicking forget password link",
				() -> assertThat(forgetPasswordPage.getHeadingForgetPasswordPage())
						.isEqualToIgnoringCase("Forgot Your Password?"));
	}
}

  1. The tests run using the Serenity test runner – @RunWith(SerenityRunner.class).
  2. The @Steps annotation marks a Serenity step library.
  3. Create the test following the Given/When/Then pattern and using step methods from the step library.
  4. The @Title annotation lets you provide your own title for this test in the test reports.

Step 6 – Create NavigateActions class under src/test/java

This class is used to open a web browser with the URL specified. This class is extended from UIInteractionSteps.

openPageNamed() method open an environment-specific page defined in the serenity.conf file under the pages section. The value of loginForm is derived from serenity.config:

public class NavigateActions extends UIInteractionSteps {

    @Step
    public void toTheHomePage() {
        // openUrl("https://opensource-demo.orangehrmlive.com/");

        openPageNamed("loginForm");
    }
}

serenity.config (partial config file)

pages{
  loginForm = "https://opensource-demo.orangehrmlive.com/"
  }

Step 7 – Create Page Object Classes – StepLoginPage, StepDashBoardPage and StepForgetPasswordPage under src/test/java

StepLoginPage

public class StepLoginPage extends PageObject {

    @FindBy(name = "txtUsername")
    WebElementFacade username;

    @FindBy(name = "txtPassword")
    WebElementFacade txtPassword;

    @FindBy(name = "Submit")
    WebElementFacade submitButton;

    @FindBy(id = "spanMessage")
    WebElementFacade errorMessage;

    @FindBy(xpath = "//*[@id='forgotPasswordLink']/a")
    WebElementFacade forgotPasswordLinkText;

    @Step("Enter Username")
    public void inputUserName(String userName) {
        $("[name='txtUsername']").sendKeys((userName));
    }

    @Step("Enter Password")
    public void inputPassword(String passWord) {
        txtPassword.sendKeys((passWord));
    }

    @Step("Click Submit Button")
    public void clickLogin() {
        submitButton.click();
    }

    @Step("Error Message on unsuccessful login")
    public String loginPageErrorMessage() {
        return errorMessage.getText();
    }

    @Step("Click Forget Password Link")
    public void clickForgetPasswordLink() {
        forgotPasswordLinkText.click();
    }
}

StepDashBoardPage.java

public class StepDashBoardPage extends PageObject {

    @FindBy(xpath = "//*[@id='content']/div/div[1]/h1")
    WebElementFacade dashboardPageTitle;

    @Step("Heading of DashBoard Page")
    public String getHeading() {
        return dashboardPageTitle.getText();
    }

}

StepForgetPasswordPage.java

public class StepForgotPasswordPage extends PageObject {

    @FindBy(xpath = "//*[@id='content']/div[1]/div[2]/h1")
    WebElementFacade forgetLink;

    @Step("Verify Forget Password Page ")
    public String getHeadingForgetPasswordPage() {

        return forgetLink.getText();
    }
}

Keep in mind to use @FindBy annotation from:

import org.openqa.selenium.support.FindBy;

PageObject class is imported from:

import net.thucydides.core.pages.PageObject;

The JUnit Serenity integration provides some special support for Serenity Page Objects. In particular, Serenity will automatically instantiate any PageObject fields in the JUnit test. When a field of type StepLoginPage is declared in the test, Serenity instantiates it for you. The page is automatically instantiated and ready to be used.

@Managed                                                                
WebDriver driver;

@Managed declares a WebDriver instance that will be managed by Serenity. The WebDriver instance will be initialized automatically.

The driver parameter lets you define what WebDriver driver you want to run these tests in. Possible values include Firefox, chrome, iexplorer, phantomjs, appium, safari, edge, and htmlunit.  The default browser in Serenity is Firefox. There are multiple ways to configure webDriver. One of the ways is to mention with @Managed as shown below:

@Managed(driver="chrome")

Step 8 – Create serenity.conf file under src/test/resources

Serenity.conf file is used to specify various features like the type of webdriver used, various test environments, run test in headless mode, and many more options. Serenity.config can also contain settings like start size, disable sandbox, disable gpu, and others that need to be added to the chrome.switches setting. 

webdriver{
    driver = chrome

}

chrome {
  switches ="""--start-maximized;--test-type;--no-sandbox;--ignore-certificate-errors;
                   --disable-popup-blocking;--disable-default-apps;--disable-extensions-file-access-check;
                   --incognito;--disable-infobars,--disable-gpu"""
  }

pages{
  loginForm = "https://opensource-demo.orangehrmlive.com/"
  }

Step 9 – Create serenity.properties file in the root of the project

serenity.project.name = Serenity and Junit Demo

Step 10 – Run the tests through commandline which generates Serenity Report

Open commandline and go to the location where pom.xml of the project is present and type the below command.

mvn clean verify

Below is the execution status.

There is 2 types of reports are generated – Index.html and Serenity-Summary.html

  1. Index.html

 We can see the value of the @Title annotation, ‘Login to application with valid credentials navigates to DashBoard page’, added as the heading. The value of @Step annotation, ‘Enter Username’, ‘Enter Password’ is added to the Report as various steps.

This report contains a screenshot of each step also.

2. Emailable Report (Serenity-Summary.html)

These reports are present under /target/site/serenity.

Skipping the tests

In Serenity, you use the @Pending annotation, either for a test or for a @Step-annotated method, to indicate that the scenario is still being implemented and that the results are not available yet. These tests appear as ‘Pending’ (shown in blue) in the test reports.

@Test
	@Pending
	@Title("Verify Forgot your password link")
	public void clickForgetPasswordLink() {

		// Given
		loginPage.open();

		// When
		loginPage.clickForgetPasswordLink();

		// Then
		Assert.assertTrue(forgetpasswordPage.ForgetPasswordPage());
	}

Tests marked with @Ignore will appear as ‘Ignored’ (from JUnit) appears as grey in the test reports.

We are done! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s