Quick start

Create and execute your first integration test on a Bonita process.

This quick start tutorial assumes that a Bonita platform is running at http://localhost:8080/bonita (Bonita Studio default for example). On this platform, a BDM and a process using this BDM are installed.
No matter where is running your platform and what kind of process is installed on it, you should be able to follow this tutorial and adapt it to your use case.

Integrations tests are built upon the Bonita Test Toolkit, based on the open-source Bonita Java Client.
The Bonita Test Toolkit is only available for Enterprise, Performance, Efficiency, and Teamwork editions.

Test environment setup

We will briefly describe in this section the process used in the test below.

In this process, we are going to create a dinosaur with a name, a color, and decide if he’s hungry or not. Depending on his hunger state, he will go hunting or sleeping.

The following Business Data Model is used:

Dinosaur
Name Type Multiple Mandatory

name

String

false

true

color

String

false

true

hungry

Boolean

false

true

The following process is used:

Quick start process example

The process Pool is called create-dinosaur. It contains a business variable dinosaur of type com.company.bonitasoft.model.Dinosaur.
On the task createDinosaur, a contract is defined to instantiate this business data.
If the field hungry is set to true, then the path to the task goToHunt is selected, else it is the path to the task goToSleep.
To do this, for the Yes path, create a isHungry() expression, which returns dinosaur.hungry. The No path is the default flow.

Create a Bonita test project

Create a new Maven project with the following pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.company.test</groupId>
    <artifactId>bonita-process-test</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>Bonita process test</name>
    <description>Maven project to test Bonita processes</description>

    <properties>
        <!-- maven -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <maven-failsafe-plugin.version>2.22.2</maven-failsafe-plugin.version>
        <maven-dependency-plugin.version>3.2.0</maven-dependency-plugin.version>

        <!-- Bonita -->
        <bonita-test-toolkit.version>1.0.5</bonita-test-toolkit.version>

        <!-- Test -->
        <junit.version>5.9.1</junit.version>
        <assertj-core.version>3.23.1</assertj-core.version>
        <awaitility.version>4.2.0</awaitility.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.junit</groupId>
                <artifactId>junit-bom</artifactId>
                <version>${junit.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency> (1)
            <groupId>com.bonitasoft</groupId>
            <artifactId>bonita-test-toolkit</artifactId>
            <version>${bonita-test-toolkit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId> (2)
            <artifactId>assertj-core</artifactId>
            <version>${assertj-core.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.awaitility</groupId> (3)
            <artifactId>awaitility</artifactId>
            <version>${awaitility.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>${maven-failsafe-plugin.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-failsafe-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>integration-test</goal>
                        <goal>verify</goal>
                    </goals>
                </execution>
            </executions>
          </plugin>
        </plugins>
    </build>
</project>
1 The Bonita Test Toolkit dependency
2 Fluent assertion library
3 Asynchronous systems test library

In src/test/java/com/company/test, create a class CreateDinosaurIT.java with the following content:

package com.company.bonita.test;

import static com.bonitasoft.test.toolkit.predicate.ProcessInstancePredicates.*;
import static com.bonitasoft.test.toolkit.predicate.UserTaskPredicates.*;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

import java.util.List;
import com.bonitasoft.test.toolkit.BonitaTestToolkit;
import com.bonitasoft.test.toolkit.contract.ComplexInputBuilder;
import com.bonitasoft.test.toolkit.contract.ContractBuilder;
import com.bonitasoft.test.toolkit.junit.extension.BonitaTests;
import com.bonitasoft.test.toolkit.model.BusinessData;
import com.bonitasoft.test.toolkit.model.BusinessObjectDAO;
import com.bonitasoft.test.toolkit.model.Task;
import com.bonitasoft.test.toolkit.model.QueryParameter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

@BonitaTests (1)
class CreateDinosaurIT {

    @BeforeEach (2)
    void beforeEach(BonitaTestToolkit toolkit){
        toolkit.deleteBDMContent(); (3)
        toolkit.deleteProcessInstances(); (4)
    }

    @Test
    void should_create_an_hungry_tyrannosaurus(BonitaTestToolkit toolkit) {  (5)
        var user = toolkit.getUser("walter.bates"); (6)
        var processDef = toolkit.getProcessDefinition("create-dinosaur"); (7)
        final BusinessObjectDAO<BusinessData> businessObjectDAO = toolkit.getBusinessObjectDAO("com.company.bonitasoft.model.Dinosaur"); (8)

        assertThat(businessObjectDAO.find(0, 10)).isEmpty();

        var processInstance = processDef.startProcessFor(user); (9)

        await().until(processInstance, processInstanceStarted()
                .and(containsPendingUserTasks("CreateDinosaur"))); (10)

        var complexInputBuilder = ComplexInputBuilder.complexInput()
                .textInput("name", "Tyrannosaurus")
                .textInput("color", "Brown")
                .booleanInput("hungry", true);
        var task1Contract = ContractBuilder.newContract().complexInput("dinosaurInput", complexInputBuilder).build(); (11)
        var task1 = processInstance.getFirstPendingUserTask("CreateDinosaur"); (12)

        await().until(task1, hasCandidates(user)
                .and(taskReady()));

        task1.execute(user, task1Contract);

        await().until(task1, taskArchived());
        await().until(processInstance, processInstanceArchived());
        assertThat(processInstance.searchTasks()).map(Task::getName).containsExactlyInAnyOrder("CreateDinosaur", "goToHunt");
        assertThat(processInstance.getFirstTask("goToHunt").isArchived()).isTrue();

        // Data assertions
        final List<BusinessData> result = businessObjectDAO.query("findByName",
                                                         List.of(QueryParameter.stringParameter("name", "Tyrannosaurus")), 0, 10);
        assertThat(result)
            .hasSize(1)
            .allSatisfy(dino -> {
                assertThat(dino.getStringField("name")).isEqualTo("Tyrannosaurus");
                assertThat(dino.getStringField("color")).isEqualTo("Brown");
                assertThat(dino.getBooleanField("hungry")).isTrue();
            });
    }

}
1 @BonitaTests is an annotation that register a JUnit 5 extension. It’s a convenient way to set up a Bonita test class. This extension allows injecting a BonitaTestToolkit correctly instantiated in test methods.
2 This method is executed before each test of this class
3 Delete the content of the BDM of the target runtime
4 Delete all the process instances (active and archived) of the target runtime
5 The BonitaTestToolkit, injected by the BonitaTestExtension, is the main entry point to interact with the targeted Bonita platform.
6 The toolkit offers the possibility to retrieve an existing user on the targeted Bonita platform. Such users are used to execute processes and tasks during test scenarios.
7 A process definition represents a deployed process on the targeted Bonita platform. It is used to start cases.
8 Using the toolkit, you can create a BusinessObjectDAO. It has to match an existing BusinessObject defined in the installed Business Data Model, and is used to retrieve instances of this business object.
9 The process under test is started using its process definition.
10 The awaitility library and the TaskPredicates factory allow you to express assertions on asynchronous Bonita concepts (task executions, process instantiation…​).
11 Contracts can be built using a ContractBuilder and a ComplexInputBuilder. It creates a key-value model representing the contract required to execute the task.
12 Pending user tasks can be retrieved from the ProcessInstance. Several actions and assertions can be performed on user tasks.

Run the tests

Using Maven command line

# Parameters 'bonita.url', 'bonita.tech.user' and 'bonita.tech.password' are optionals.
# Use them if your runtime runs on an other URL than localhost:8080/bonita,
# or with technical user credentials different from install / install.

mvn verify [-Dbonita.url=<TARGET_RUNTIME_URL> -Dbonita.tech.user=<TECHNICAL_USER_USERNAME> -Dbonita.tech.password=<TECHNICAL_USER_PASSWORD>]

Advanced usage

The test toolkit communicates with the target Bonita Runtime using HTTP. It is possible to fine tune some HTTP specific options using the following arguments:

  • -Dbonita.client.disable.certificate.check=true|false Default is false. Disable SSL certificate check when connecting to remote runtime using HTTPS.

  • -Dbonita.client.http.connection.timeout=30 Default is 30. Timeout in seconds used for the HTTP connection timeout.

To Go further

Now that you have successfully implemented your first Integration test, you can adapt this example to test your own process!