This content is dedicated to our next version. It is work in progress: its content will evolve until the new version is released. Before that time, it cannot be considered as official.

Quick start

Create and execute a first integration test on a basic 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 small BDM and basic process using this BDM are installed.
No matter where is your platform running and what kind of process is installed on it, you should be able to follow this quick start tutorial and adapt it to your use case.

The complete solution can be downloaded here, and the Bonita project used in the solution here.

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. It is not mandatory to reproduce this process to write a first test, any kind a basic process can be used.
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 hungry state, he will go to hunt or go to sleep.

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 contains a business data dinosaur of type com.company.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.

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>
        <maven-project-info-plugin.version>3.1.2</maven-project-info-plugin.version>

        <!-- Bonita -->
        <bonita-test-toolkit.version>0.0.1-SNAPSHOT</bonita-test-toolkit.version>

        <!-- Test -->
        <junit.version>5.8.1</junit.version>
        <assertj-core.version>3.21.0</assertj-core.version>
        <awaitility.version>4.1.1</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 ProcessIT.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.TaskPredicates.*;
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.BonitaTestToolkitFactory.Configuration;
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 org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

@BonitaTests(clearBDM = true, deleteProcessInstances = true) (1)
class CreateDinosaurIT {

    @Test
    void should_create_an_hungry_tyrannosaurus(BonitaTestToolkit toolkit) {  (2)
        var user = toolkit.getUser("walter.bates"); (3)
        var processDef = toolkit.getProcessDefinition("Dinosaur"); (4)
        final BusinessObjectDAO<BusinessData> businessObjectDAO = toolkit.getBusinessObjectDAO("com.company.model.Dinosaur"); (5)

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

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

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

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

        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> businessData = businessObjectDAO.query("findByName", List.of("name=Tyrannosaurus"), 0, 10);
        assertThat(businessData).hasSize(1);
        assertThat(businessData.get(0).getStringField("name")).isEqualTo("Tyrannosaurus");
        assertThat(businessData.get(0).getStringField("color")).isEqualTo("Brown");
        assertThat(businessData.get(0).getBooleanField("hungry")).isTrue();
    }

}
1 BonitaTests is an annotation that register a JUnit 5 extension. It’s a convenient way to setup a Bonita test class. This extension allows to inject a BonitaTestToolkit correctly instantiated in test methods.
2 The BonitaTestToolkit, injected by the BonitaTestExtension, is the main entry point to interact with the targeted Bonita platform.
3 The toolkit offers the possibility to retrieve an existing user on the targeted Bonta platform. Users are used to execute processes during the test scenario.
4 A process definition represents a deployed process on the targeted Bonita platform. It is used to start cases of a given process.
5 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.
6 The process under test is started using its process definition.
7 Using the awaitility library and the TaskPredicates factory offers the possibility to express assertions on asynchronous Bonita concepts (task executions, process instantiation…​).
8 Contracts can be built using a ContractBuilder and a ComplexInputBuilder if required. It creates a key-value model representing the contract required to execute the task.
9 Pending user tasks can be retrieved from the ProcessInstance. Different actions and assertions can be performed on user tasks.

Run the tests

Using Maven command line

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

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