After we have have written custom TestProject actions, we want to use them in our test classes. Unfortunately, we have no idea how can do it.
During this blog post we will write two tests for the search function of my blog and both test classes use the custom actions which we wrote in the previous parts of my TestProject tutorial.
After we have finished this blog post, we:
- Know how we can download a TestProject addon proxy.
- Understand how we can use the actions provided by the downloaded addon proxy.
- Can use TestProject actions in our test classes.
Let's start by finding out how we can download a TestProject addon proxy.
This blog post assumes that:
- You are familiar with TestProject
- You can package TestProject tests and addons with Gradle
- You can write tests with TestProject
- You can write custom TestProject addons
- You can input and output parameters to TestProject actions
By the way, you might want to read the other parts of my TestProject tutorial.
Downloading a TestProject Addon Proxy
If we want to use use a custom addon found from the TestProject addon store, we have to download an addon proxy jar file. An addon proxy is a component that allows us to invoke the actual actions provided by a TestProject addon.
When an addon proxy is invoked by the TestProject SDK, the TestProject SDK communicates with the Agent API of the app.testproject.io website and downloads the invoked action (if the action hasn't been downloaded earlier). After the TestProject SDK has downloaded the invoked action, it runs the action in a separate process.
We can download a TestProject addon proxy from the app.testproject.io website by following these steps:
First, we have to choose the addon which we want to use. The app.testproject.io website has an addon store that allows us to download our private addons and addons shared by the other members of the TestProject community. This store has also a search function which provides us an easy way to find addons which are not listed on the main page of the addon store.
After we have found an addon we want to use, we have to open the download dialog by clicking the element that displays the basic information of the addon.
The following figure illustrates the layout of the 'Addons' page (the main page of the addon store):
However, because we want to use the custom addon which we wrote in the previous parts of my TestProject tutorial, we have to open the 'My Addons' page and open the download dialog of our custom addon (Blog Search Addon).
The following figure illustrates the layout of the 'My Addons' page:
Second, we have to download the addon proxy jar file by clicking the 'Proxy' link found from the 'Downloads' section of the modal dialog.
The following figure illustrates this step:
We have now downloaded the jar file that contains our addon proxy. Next, we will find out how we can add our addon proxy to the classpath.
Adding the Downloaded Addon Proxy to the Classpath
Before we can use the actions found from the downloaded jar file, we have to add the jar file to our classpath. We can do this by following these steps:
First, we have to copy the jar file (blog.search.addon.proxy.jar) to the libs directory that is found from the root directory of our Gradle project. After we have copied our jar file to the libs directory, its content should look as follows:
libs |__ blog.search.addon.proxy.jar |__ io.testproject.sdk.java.jar
Second, because we will write code that uses the classes found from the blog.search.addon.proxy.jar file, we have to add this jar file to the compile
dependency configuration. After we have made the required changes to our build.gradle file, its dependencies
block looks as follows:
dependencies { compile files('libs/blog.search.addon.proxy.jar') tpsdk files('libs/io.testproject.sdk.java.jar') }
We have now added our addon proxy jar to our classpath. Let's move on and find out how we can write tests which use custom TestProject actions.
Writing Test Classes Which Use TestProject Actions
Let's write these two test cases for the search function of my blog:
- We have to ensure that the search result page has the expected title.
- We have to verify that the search result page displays at least one search result.
Before we can write our classes, we have to figure out how we can write code that runs TestProject actions. Next, we will find out how we can write this code.
Running TestProject Actions
We can run a TestProject action by invoking the executeProxy()
method of the WebTestHelper
class. When we use this method, we have to know these three things:
- It takes the invoked action (an
ActionProxy
object) as a method parameter. - It returns a value of the
ExecutionResult
enum. The return value of theexecuteProxy()
method specifies the result of the invoked action (ExecutionResult.PASSED
orExecutionResult.FAILED
). - It can throw a checked expection (an
Exception
object).
In other words, when we invoke the execute()
method, we have to write error handler code which ensures that:
- Our test fails if the
execute()
method returnsExecutionResult.FAILED
. - Our test fails if the
execute()
method throws an exception.
The problem is that we cannot take care of these things in our test classes because we don't want to add duplicate code to our test suite. That's why we have to create a utility class that can run TestProject actions and handle errors caused the invoked actions.
We can write this utility class by following these steps:
First, we have to create a package private class called ActionRunner
. After we have created this class, its source code looks as follows:
class ActionRunner { }
Second, we have to add a final
WebTestHelper
field to the ActionRunner
class and implement a constructor that sets the value of the WebTestHelper
field by using constructor injection. After we have implemented our constructor, the source code of the ActionRunner
class looks as follows:
import io.testproject.java.sdk.v2.tests.helpers.WebTestHelper; class ActionRunner { private final WebTestHelper webTestHelper; ActionRunner(WebTestHelper webTestHelper) { this.webTestHelper = webTestHelper; } }
Third, we have to add a private private runAction()
method to the ActionRunner
class. This method takes an ActionProxy
object as a method parameter, and it can throw a FailureException
. After we have added this method to the ActionRunner
class, we have to implement it by following these steps:
- Run the TestProject action.
- If the invoked action returned
ExecutionResult.FAILED
, throw aFailureException
that fails our test. - If the invoked action threw an
Exception
, throw aFailureException
that fails our test.
After we implemented the runAction()
method, the source code of the ActionRunner
class looks as follows:
import io.testproject.java.sdk.v2.addons.proxy.ActionProxy; import io.testproject.java.sdk.v2.enums.ExecutionResult; import io.testproject.java.sdk.v2.exceptions.FailureException; import io.testproject.java.sdk.v2.tests.helpers.WebTestHelper; class ActionRunner { private final WebTestHelper webTestHelper; ActionRunner(WebTestHelper webTestHelper) { this.webTestHelper = webTestHelper; } void runAction(ActionProxy proxy) throws FailureException { try { ExecutionResult result = webTestHelper.executeProxy(proxy); if (result == ExecutionResult.FAILED) { throw new FailureException(String.format( "The invocation of the action proxy: %s failed ", proxy.getDescriptor().getClassName() )); } } catch (Exception e) { throw new FailureException(e.getMessage(), e); } } }
public
access level modifier.We are now ready to write our test classes. Let's move on and find how we can ensure that the search result page has the expected title.
Test 1: The Search Result Page Has the Expected Title
When we want to ensure that the search result page has the expected title, we have to write our test class by following these steps:
First, we have to create a new test class and configure the name and description of our test case. After we have created a new test class, its source code looks as follows:
import io.testproject.java.annotations.v2.Test; import io.testproject.java.sdk.v2.tests.WebTest; @Test( name = "The search result page must have the expected title", description = "Verify that the search result page has the expected title" ) public class BlogSearchResultTitleTest implements WebTest { }
Second, we have to add three input parameters to our test class:
- The
searchPageUrl
specifies the URL of the page that displays the search form. - The
searchTerm
defines the used search term. - The
expectedSearchResultPageTitle
specifies the expected title of the search result page.
After we have added these input parameters to our test class, its source code looks as follows:
import io.testproject.java.annotations.v2.Parameter; import io.testproject.java.annotations.v2.Test; import io.testproject.java.sdk.v2.tests.WebTest; @Test( name = "The search result page must have the expected title", description = "Verify that the search result page has the expected title" ) public class BlogSearchResultTitleTest implements WebTest { @Parameter(description = "Contains the url of the search page") private String searchPageUrl; @Parameter(description = "Contains the submitted search term") private String searchTerm; @Parameter(description = "Contains the expected title of the search result page") private String expectedSearchResultPageTitle; }
Third, we have to implement the execute()
method of the WebTest
interface by following these steps:
- Open the search page.
- Clear the search field by using the
ClearBlogSearchFieldAction
class which we created in an earlier part of this tutorial. - Submit the search form by using the
BlogSearchAction
class which we created in an earlier part of this tutorial. - Ensure that the search result page has the expected title.
After we have implemented the execute()
method of the WebTest
interface, the source code of our test class looks as follows:
import io.testproject.java.annotations.v2.Parameter; import io.testproject.java.annotations.v2.Test; 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 io.testproject.java.sdk.v2.tests.WebTest; import io.testproject.java.sdk.v2.tests.helpers.WebTestHelper; import io.testproject.proxy.addon.BlogSearchAddon; import io.testproject.proxy.addon.net.petrikainulainen.testproject.addon.BlogSearchAction; import io.testproject.proxy.addon.net.petrikainulainen.testproject.addon.ClearBlogSearchFieldAction; @Test( name = "The search result page must have the expected title", description = "Verify that the search result page has the expected title" ) public class BlogSearchResultTitleTest implements WebTest { @Parameter(description = "Contains the url of the search page") private String searchPageUrl; @Parameter(description = "Contains the submitted search term") private String searchTerm; @Parameter(description = "Contains the expected title of the search result page") private String expectedSearchResultPageTitle; @Override public ExecutionResult execute(WebTestHelper webTestHelper) throws FailureException { WebDriver browser = webTestHelper.getDriver(); browser.get(searchPageUrl); ActionRunner actionRunner = new ActionRunner(webTestHelper); ClearBlogSearchFieldAction clearSearchField = BlogSearchAddon .getClearBlogSearchFieldAction(); actionRunner.runAction(clearSearchField); BlogSearchAction blogSearch = BlogSearchAddon.blogSearchAction(searchTerm); actionRunner.runAction(blogSearch); return browser.getTitle().equals(expectedSearchResultPageTitle) ? ExecutionResult.PASSED : ExecutionResult.FAILED; } }
[AddonName]Addon
. This class provides factory methods which allow us to create the invoked actions (ActionProxy
objects). As we can see, in our case, the name of this class is: BlogSearchAddon
.
We have now written a test class which ensures that the search result page has the expected title. Next, we will write a test class which verifies that the search result page displays at least one search result.
Test 2: The Search Result Page Displays at Least One Search Result
When we want to ensure that the search result page displays at least one search result, we have to write our test class by following these steps:
First, we have to create a new test class and configure the name and description of our test case. After we have created a new test class, its source code looks as follows:
import io.testproject.java.annotations.v2.Test; import io.testproject.java.sdk.v2.tests.WebTest; @Test( name = "The search result page must display at least one search result", description = "Verify that the search result page displays at least one search result" ) public class BlogSearchResultCountTest implements WebTest { }
Second, we have to add two input parameters to our test class:
- The
searchPageUrl
specifies the URL of the page that displays the search form. - The
searchTerm
defines the used search term.
After we have added these input parameters to our test class, its source code looks as follows:
import io.testproject.java.annotations.v2.Parameter; import io.testproject.java.annotations.v2.Test; import io.testproject.java.sdk.v2.tests.WebTest; @Test( name = "The search result page must display at least one search result", description = "Verify that the search result page displays at least one search result" ) public class BlogSearchResultCountTest implements WebTest { @Parameter(description = "Contains the url of the search page") private String searchPageUrl; @Parameter(description = "Contains the submitted search term") private String searchTerm; }
Third, we have to implement the execute()
method of the WebTest
interface by following these steps:
- Open the search page.
- Clear the search field by using the
ClearBlogSearchFieldAction
class which we created in an earlier part of this tutorial. - Submit the search form by using the
BlogSearchAction
class which we created in an earlier part of this tutorial. - Extract the number of search results from the search result page by using the
BlogSearchResultFinderAction
class which we created in an earlier part of this tutorial. - Ensure that the search result page displays at least one search result.
After we have implemented the execute()
method of the WebTest
interface, the source code of our test class looks as follows:
import io.testproject.java.annotations.v2.Parameter; import io.testproject.java.annotations.v2.Test; 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 io.testproject.java.sdk.v2.tests.WebTest; import io.testproject.java.sdk.v2.tests.helpers.WebTestHelper; import io.testproject.proxy.addon.BlogSearchAddon; import io.testproject.proxy.addon.net.petrikainulainen.testproject.addon.BlogSearchAction; import io.testproject.proxy.addon.net.petrikainulainen.testproject.addon.BlogSearchResultFinderAction; import io.testproject.proxy.addon.net.petrikainulainen.testproject.addon.ClearBlogSearchFieldAction; @Test( name = "The search result page must display at least one search result", description = "Verify that the search result page displays at least one search result" ) public class BlogSearchResultCountTest implements WebTest { @Parameter(description = "Contains the url of the search page") private String searchPageUrl; @Parameter(description = "Contains the submitted search term") private String searchTerm; @Override public ExecutionResult execute(WebTestHelper webTestHelper) throws FailureException { WebDriver browser = webTestHelper.getDriver(); browser.get(searchPageUrl); ActionRunner actionRunner = new ActionRunner(webTestHelper); ClearBlogSearchFieldAction clearSearchField = BlogSearchAddon .getClearBlogSearchFieldAction(); actionRunner.runAction(clearSearchField); BlogSearchAction blogSearch = BlogSearchAddon.blogSearchAction(searchTerm); actionRunner.runAction(blogSearch); BlogSearchResultFinderAction searchResults = BlogSearchAddon .getBlogSearchResultFinderAction(); actionRunner.runAction(searchResults); return searchResults.actualSearchResultCount > 0 ? ExecutionResult.PASSED : ExecutionResult.FAILED; } }
We have now written two test cases which demonstrate how we can use TestProject actions in our test classes. Let's summarize what we learned from this blog post.
Summary
This blog post has taught us six things:
- If we want to use use a custom addon found from the TestProject addon store, we have to download an addon proxy jar file.
- An addon proxy is a component that allows us to invoke the actual actions provided by a TestProject addon.
- If we want to use an addon in our test classes, we have to add the downloaded addon proxy jar file to the
compile
dependency configuration. - We can run a TestProject action by invoking the
executeProxy()
method of theWebTestHelper
class. - If we don't want to add duplicate error handling code to our test suite, we have to create a utility class that can run TestProject actions and handle errors caused the invoked actions.
- We should create the invoked
ActionProxy
objects by using the factory methods provided by the[AddonName]Addon
class.
P.S. You can get the example application of this blog post from Github.