Are you tired of writing tests which have a lot of boilerplate code? If so, get started with Spock Framework >>

Writing Addons With TestProject

After we have written some test cases with the TestProject framework, it’s likely that we can identify duplicate code which is shared by multiple test classes. This blog post describes how we can remove duplicate code from our test suite by writing custom TestProject addons.

After we have finished this blog post, we:

  • Know what a TestProject addon is.
  • Can implement a custom TestProject addon.
  • Know how we can upload our addon to the app.testproject.io website.
  • Can share our addon with the TestProject community.

Let’s start by taking a quick look at TestProject addons.

This blog post is the fifth part of my TestProject tutorial that is sponsored by TestProject.io. However, the views and opinions expressed in this tutorial are mine.

This blog post assumes that:

By the way, you might want to read the other parts of my TestProject tutorial.

What Is an Addon?

An addon is a collection of actions which provide useful features to test cases. For example, an action might clear all fields of a form or log a user in to the tested website. A test case can use addons which are published on the app.testproject.io website.

Because addons can be shared with different projects and different organizations, they cannot have unrestricted access to the host system that runs the TestProject agent. When a TestProject agent runs an addon, it spawns a separate process that has limited access to the host system and to the outside world. If the default permissions aren’t enough for an addon, it can request these permissions:

  • The File System permission allows the addon to access the file system of the host system that runs the TestProject agent. For example, if the addon reads the used test data from a file, it requires this permission.
  • The ADB permission allows the addon to communicate with Android devices by using the Android Debug Bridge tool.
  • The Network permission allows the addon to communicate with the outside world. For example, if the addon gets the used test data by invoking a REST API, it requires this permission. However, if the addon uses only the Selenium API, it doesn’t require this permission.
  • The Env permission allows the addon to access the environment variables of the host system that run runs the TestProject agent.

We are now familiar with the basics. Next, we will find out how we can implement a custom TestProject addon.

Implementing Our Addon

During this blog post we will implement an addon that has an action which clears the search field found from the sidebar of my blog. The HTML markup of the search form looks as follows:

<form class="search_form" 
      method="get" 
      action="https://www.petrikainulainen.net">
    <p>
        <input class="input_text" 
               type="text" 
               id="s" 
               name="s" 
               value="enter search term and press enter">
        <input type="hidden" id="searchsubmit" value="Search">
    </p>
</form>

We can write our action by following these steps:

First, we have to create a new class that contains the source code of our action. As we remember, an action class must implement an interface which identifies the target platform of the action. Because we are writing a web action, we can create our action class by following these steps:

  1. Create a public class that implements the WebAction interface.
  2. Annotate the created class with the @Action annotation and specify the name of our action.
  3. Add an execute() method to the created class. This method takes a WebAddonHelper object as a method parameter and returns an ExecutionResult enum.

After we have created our action class, its source code looks as follows:

import io.testproject.java.annotations.v2.Action;
import io.testproject.java.sdk.v2.addons.WebAction;
import io.testproject.java.sdk.v2.addons.helpers.WebAddonHelper;
import io.testproject.java.sdk.v2.enums.ExecutionResult;
import io.testproject.java.sdk.v2.exceptions.FailureException;

@Action(name = "Clear the search field of the search form")
public class ClearBlogSearchFieldAction implements WebAction {

    @Override
    public ExecutionResult execute(WebAddonHelper webAddonHelper) 
            throws FailureException {

    }
}
We should always specify the name of our action by using the @Action annotation because this name is shown on the test results. If we use a human-friendly name, our test results are easier to read. However, if we won’t specify the name of our action, the test results will use the name of our action class.

Second, we have to implement the execute() method of the WebAction interface by following these steps:

  1. Get a reference to the used WebDriver object.
  2. Find the search field element by using its id (s) as a search criteria.
  3. If the search field element is not visible, report the reason of the test failure and fail the test by returning ExecutionResult.FAILED.
  4. If the search field element is visible, clear its value and return ExecutionResult.PASSED. This return value ensures that the TestProject agent continues the execution of the invoked test.

After we have implemented the execute() method, the source code of our action class looks as follows:

import io.testproject.java.annotations.v2.Action;
import io.testproject.java.sdk.v2.addons.WebAction;
import io.testproject.java.sdk.v2.addons.helpers.WebAddonHelper;
import io.testproject.java.sdk.v2.drivers.WebDriver;
import io.testproject.java.sdk.v2.enums.ExecutionResult;
import io.testproject.java.sdk.v2.exceptions.FailureException;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;

@Action(name = "Clear the search field of the search form")
public class ClearBlogSearchFieldAction implements WebAction {

    @Override
    public ExecutionResult execute(WebAddonHelper webAddonHelper)
            throws FailureException {
        WebDriver browser = webAddonHelper.getDriver();

        WebElement searchField = browser.findElement(By.id("s"));
        if (!searchField.isDisplayed()) {
            webAddonHelper.getReporter()
                    .result("No input field was found with the id: s");
            return ExecutionResult.FAILED;
        }

        searchField.clear();
        return ExecutionResult.PASSED;
    }
}
There are three things I want to point out:

  • If our action fails the invoked test, we should always report the reason of the test failure by using the ActionReporter class. This helps us to save a lot of time if a test case fails because we can figure out what went wrong by simply taking a look at the test results.
  • If we want to fail the invoked test, we can return ExecutionResult.FAILED or throw a FailureException.
  • If the Selenium WebDriver (or Appium) throws an exception, the invoked test will fail.

We have now implemented the only action of our addon. Next, we have to create a new addon on the app.testproject.io website.

Creating a New Addon

We can create a new addon by following these steps:

First, we have to open the ‘Addons’ page by clicking the ‘Addons’ link found from the main navigation bar of the website.

The following figure identifies the location of the ‘Addons’ link:

Second, we have to start the create addon wizard by clicking the ‘Create Addon’ link.

The following figure identifies the location of the ‘Create Addon’ link:

After we have started the create addon wizard, we have to finish it by following these steps:

First, we have to specify the general information of the addon. The general information form contains the following fields:

  • The name of the addon.
  • An optional description of the addon.
  • An optional link that points to a page that allows a developer to download the source code of our addon.
  • An optional link that points to the documentation of our addon.
  • Optional tags of the addon. These tags allow us to group related addons.

After we have provided this information, we can proceed to the next step of this wizard by clicking the ‘Next’ button.

The following figure illustrates this step:

Second, we have to specify the permissions of our addon by following these steps:

  1. Specify the permissions by clicking the relevant checkboxes. Because our addon uses only the Selenium API, it doesn’t require any additional permissions.
  2. Download the manifest.json file by clicking the ‘Generate & Download Manifest’ button. This file must be included in the jar file which contains our action classes.
  3. Proceed to the next step of this wizard by clicking the ‘Next’ button.

The following figure illustrates this step:

Third, we have to include the downloaded manifest.json file in the jar file which contains our action classes. We can do this by following these steps:

  1. Move the manifest.json file to the src/main/resources directory of our addon project.
  2. Package the addon by running the command: gradle clean build in the root directory of our addon project.

Fourth, we have to upload the created jar file to app.testproject.io website by following these steps:

  1. Drag the jar file to the upload area of the modal dialog.
  2. Click the ‘Upload File’ button.

The following figure illustrates this step:

Fifth, we have to review the actions found from the uploaded jar file. If the action list contains all actions and the required SDK version is correct, we can create our addon and share it with our team by clicking the ‘Finish’ button.

The following figure illustrates this step:

We have now uploaded our addon to the app.testproject.io website and shared it with our team. However, the odds are that we might want to update our addon or share it with the members of the TestProject community. Let’s move on and find out how we can manage our addons.

Managing Our Addons

When we want to manage our addon, we have to follow these steps:

First, we have to open the ‘Addons’ page by clicking the ‘Addons’ link found from the main navigation bar of the website.

The following figure identifies the location of the ‘Addons’ link:

Second, we have to open the ‘My Addons’ page by clicking the ‘My Addons’ link found from the sidebar of the ‘Addons’ page.

The following figure identifies the location of the ‘My Addons’ link:

Third, we have to open the modal dialog which allows us to manage our addon. We can do this by clicking the HTML element that displays the information of the managed addon.

The following figure illustrates this step:

Fourth, we can perform the preferred operation by using one of these three options:

  • If we want to share our addon with the other members of the TestProject community, we have to click the ‘Share now’ button. This button opens a modal dialog which confirms that we want to share our addon with the TestProject community.
  • If we want to upload a new version of our addon, we have to click the ‘Upload new version’ button. This button starts the upload new version wizard. I won’t describe this wizard in this blog post because it’s almost identical with the create addon wizard.
  • If we want to update the general information of our addon, download the manifest.json file, download a proxy jar, or delete our addon, we have to click the ‘More’ icon (three dots on top of each other).

The following figure illustrates our options:

We have now implemented our addon and uploaded it to the app.testproject.io website. Also, we know how we can manage our addons. Let’s summarize what we learned from this blog post.

Summary

This blog post has taught us seven things:

  • An addon is a component that provides useful features to test cases.
  • Because addons can be shared with different projects and different organizations, they cannot have unrestricted access to the host system that runs the TestProject agent.
  • If the default permissions aren’t enough for an addon, it can request additional permissions.
  • An addon is a collection of actions.
  • An action class must implement an interface which identifies the target platform of the action.
  • If we want write a web action, our action class must implement the WebAction interface.
  • If our action fails the invoked test, we should always report the reason of the test failure by using the ActionReporter class.

P.S. You can get the example application of this blog post from Github.

1 comment… add one

    Leave a Comment