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. |
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:
Name | Type | Multiple | Mandatory |
---|---|---|---|
name |
String |
false |
true |
color |
String |
false |
true |
hungry |
Boolean |
false |
true |
The following process is used:
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.release>11</maven.compiler.release>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>3.1.2</maven-failsafe-plugin.version>
<!-- Bonita -->
<bonita-test-toolkit.version>3.0.0</bonita-test-toolkit.version>
<!-- Test -->
<junit.version>5.10.0</junit.version>
<assertj-core.version>3.24.2</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-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
</plugin>
<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 isfalse
. Disable SSL certificate check when connecting to remote runtime using HTTPS. -
-Dbonita.client.http.connection.timeout=30
Default is30
. Timeout in seconds used for the HTTP connection timeout.
Generated report
Once the tests are run, a report is generated.
It shows a set of metrics for each test, and the diagram of each process. If the test launch several process instances, a diagram of each instance is displayed.
For details on the reports, see the Tests Report page.
With the test above, you should get a report similar to this one: