Guide for Java Developers

This document explains how to configure the UTAM compiler, generate UTAM Java page objects, and use them in a UI test. Examples of tests and setup are avalable in the Java recipes repo.

If you write mobile UI tests using Appium, see these additional steps to set up your environment.

Compiler setup

We use Maven for page object generation as part of the build process. You can use an alternative tool rather than Maven if you prefer. We don't mandate a particular version of the Maven plugins. Use the plugin versions that work best for your setup.

There are two main phases in the generation of UTAM page objects:

  1. Delete the previously generated page objects if they exist (cleanup phase)
  2. Create new files with generated page objects (generation phase)

An example of a pom.xml file that's configured to first delete previously generated page objects and then generate new page objects can be found in the Java recipes repo.

Cleanup phase

To remove the previously generated page objects, the example uses maven-clean-plugin. The plugin configuration defines which files need to be deleted relative to the project root.

          <filesets>
            <fileset>
              <directory>src/main/java/utam</directory>
              <includes>
                <include>**</include>
              </includes>
              <excludes>
                <exclude>**/utils/**/*.java</exclude>
              </excludes>
              <followSymlinks>false</followSymlinks>
            </fileset>
          </filesets>

Remember to remove both generated page objects and imperative utilities if you use them.

Generation phase

To run the compiler and generate new page objects, the example uses exec-maven-plugin with two mandatory arguments:

The page object generation runner is implemented in the utam.compiler.EntryPoint class that's part of the utam-compiler package.

To configure the Java compiler, create a JSON configuration file and fill the required properties with appropriate settings for your project. Those properties don't have a default fallback value in Java. Enter values for those properties in the configuration file before running the compiler.

Note: We recommend utam.config.json as the name of the compiler configuration file.

Format of the compiler configuration JSON file

Here's an example of a valid configuration for the Java compiler.

{
  "pageObjectsRootDir" : "/src/main/resources/spec",
  "pageObjectsFileMask" : "(.*)\\.utam\\.json$",
  "pageObjectsOutputDir" : "/src/main/java",
  "resourcesOutputDir" : "/src/main/resources",
  "unitTestsOutputDir" : "/src/test/java",
  "unitTestsRunner": "junit",
  "namespaces": []
}

This section lists all the options supported by the Java compiler. For each option, we describe its JSON type, its default value, if it's required or not, and what it does.

By default, generated Java page objects are in the utam.pageobjects Java package. You can override the default package name by settiing the namespaces option.

In Java, you must pass a --compilerRoot runtime argument to the compiler to set root directory for the compiler, against which all paths will be resolved.

pageObjectsRootDir

The path to the root directory containing JSON page objects. The compiler looks recursively in the root directory for declarative JSON page objects and extensions.

pageObjectsFilesMask

The file mask pattern used by the compiler to find input JSON page objects. It tells the compiler where to find the source JSON page objects relative to the root directory. Declare the file mask as a regular expression.

pageObjectsOutputDir

The relative path from the root directory to the target directory for generated page objects. That's where the compiler generates compiled Java classes from the JSON page objects.

resourcesOutputDir

The target folder for generated resources, such as profile configurations.

unitTestsOutputDir

The root folder where unit tests are generated.

unitTestsRunner

The type of unit test runner. Used to generate unit tests that target that specific runner.

namespaces

namespaces is a list of mappings between a folder in pageObjectsRootDir and the package name prefix for generated page objects. This option allows you to generate different Java packages for JSON page objects in different folders. By default, generated Java page objects are in the utam.pageobjects Java package.

A mapping consists of a pathMatch and a typeMatch.

Let's look at an example configuration file.

{
    "pageObjectsRootDir" : "/src/main/resources/spec",
    "pageObjectsFileMask" : "(.*)\\.utam\\.json$",
    "pageObjectsOutputDir" : "/src/main/java",
    "namespaces": [
        {
          "typeMatch": "utam-lightning",
          "pathMatch": ".*/lightning"
        },
        {
           "typeMatch": "utam-custom",
           "pathMatch": ".*/custom"
        }
    ]
}

A JSON page object in /src/main/resources/spec/lightning/input.utam.json generates a utam.lightning.pageobjects.Input Java page object.

A JSON page object in /src/main/resources/spec/custom/input.utam.json generates a utam.custom.pageobjects.Input Java page object.

version

Version is an optional string that is propagated as @version in the generated page object Javadoc. For example, if the version is set:

{
  "version": "Spring '22"
}

The generated Javadoc in the code is:

/**
 * ...
 * @version Spring '22
 */

If the version isn't set, the current date and time is used:

/**
 * ...
 * @version 2022-12-01 09:12:01
 */

copyright

An optional array of strings that is added at the top of the generated page object. If the copyright is set:

{
  "copyright" : [
    "Copyright (c) 2022, salesforce.com, inc.",
    "All rights reserved."
  ]
}

The generated Javadoc in the code is:

/**
 * Copyright (c) 2022, salesforce.com, inc. All rights reserved.
 */
package pageobjects;

public interface MyPageObject extends PageObject {
  //....
}

Test setup

After you generate UTAM page objects, you can create a UI test that uses the page objects. Before your test can interact with the UI, UTAM needs to have access to a driver and to certain configuration parameters.

For Java, configure WebDriver programatically by first creating an instance of UtamLoaderConfig. Set all configuration parameters, such as [implicit and explicit timeouts] (/guide/explicit-waits#implicit-and-explicit-timeouts) on UtamLoaderConfig. Then, create an instance of UtamLoader, which is the object that can create UTAM page objects.

Add this code in a test class or in a super class or utility class that you can call from a test.

import java.time.Duration;
import utam.core.framework.consumer.UtamLoader;
import utam.core.framework.consumer.UtamLoaderConfig;
import utam.core.framework.consumer.UtamLoaderConfigImpl;
import utam.core.framework.consumer.UtamLoaderImpl;
import utam.core.selenium.factory.WebDriverFactory;

// ...

  UtamLoaderConfig config = new UtamLoaderConfigImpl();
  // configure timeouts
  config.setImplicitTimeout(Duration.ofSeconds(0));
  config.setExplicitTimeout(Duration.ofSeconds(60));

  // webDriver is an instance of org.openqa.selenium.WebDriver
  UtamLoader loader = new UtamLoaderImpl(config, webDriver);

For an example using this configuration code, see the utam-java-recipes repo.

Now, a test can create UTAM page objects by calling the UtamLoader.load() method.

An instance of the WebDriver can be created in the same class as the configuration code or elsewhere. UTAM provides a utility that can create an instance of the driver. Here's an example for Chrome:

import org.openqa.selenium.WebDriver;
import utam.core.driver.DriverType;
import utam.core.selenium.factory.WebDriverFactory;

// ...

  System.setProperty("webdriver.chrome.driver",  "my path to chromedriver here");
  WebDriver driver = WebDriverFactory.getWebDriver(DriverType.chrome);

Write UI tests

See examples in the Java recipes repo.