camunda-community-hub / bpmn-driven-testing

Visually select paths through a BPMN process as test cases. Generate and enrich those test cases for easier unit testing of your process implementations.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BPMN Driven Testing

Compatible with: Camunda Platform 7 Maven plugin Gradle plugin

Camunda Platform 7 extension, which is able to generate test code based on an extended BPMN model.

The extension lets the developer focus on testing the business logic, rather than writing boilerplate code. The generated test code handles process instance start at any selected flow node and advances a process instance in case of wait states. Since the test code is generated, there is no need to deal with process definition keys and flow node IDs. Moreover any breaking changes (e.g. a user task becomes an external task) in the BPMN process will already be visible at design time as test compile errors.

The extension consists of:

⚠️ Version 0.10.0 supports only Camunda 7.21 (Java 11+) and drops test code generation for JUnit 4. For older Camunda versions (Java 8+) and JUnit 4 support, please rely on version 0.9.0.

Features

  • Visual test case selection
  • Automatic path finding with
    • Support for embedded sub processes
    • Support for boundary events
    • BPMN collaborations with multiple expanded participants
    • Loop detection
  • Generated test cases provide
    • Automatic handling of wait states
    • Call activity stubbing for isolated testing - see test
    • Fluent API to override default behavior
    • Multi instance (activity/embedded subprocess) support - see integration tests
  • Spring/Spring Boot test support - see advanced-spring* under integration tests
  • Testing of arbitrary paths through a BPMN process
  • Test case validation and migration, when a BPMN process was changed - see docs
  • camunda-process-test-coverage extension support - see coverage* under integration tests

How does it work?

Select test cases

After modeling, a developer uses the Camunda Modeler plugin to define suitable test cases by selecting a start and an end flow node. The modeler plugin finds all possible paths through the BPMN process. Each path can be added as a test case.

order-fulfillment-happy-path.png

Optionally a test case can be named and described. Names and descriptions are reflected in the generated test code.

order-fulfillment-happy-path-edit.png

When the BPMN model is saved, the selected test cases are attached to the BPMN process in form of a custom extension element.

<bpmn:process id="order-fulfillment" isExecutable="true">
  <bpmn:extensionElements>
    <bpmndt:testCases>
      <bpmndt:testCase>
        <bpmndt:name>Happy Path</bpmndt:name>
        <bpmndt:path>
          <bpmndt:node>orderReceivedStartEvent</bpmndt:node>
          <bpmndt:node>checkAvailabilityUserTask</bpmndt:node>
          <bpmndt:node>Gateway_0dw0zxn</bpmndt:node>
          <bpmndt:node>approveOrderSendTask</bpmndt:node>
          <bpmndt:node>prepareOrderUserTask</bpmndt:node>
          <bpmndt:node>deliverOrderUserTask</bpmndt:node>
          <bpmndt:node>orderFulfilledEndEvent</bpmndt:node>
        </bpmndt:path>
      </bpmndt:testCase>
    </bpmndt:testCases>
  </bpmn:extensionElements>

  <!-- ... -->
</bpmn:process>

Generate test code

To generate the code for the selected test cases, a developer must run the generator goal of the bpmn-driven-testing-maven-plugin or the generateTestCases task of the bpmn-driven-testing-gradle-plugin.

The goal (or task) finds all *.bpmn files under src/main/resources and looks for BPMN processes with a bpmndt:testCases extension element. Each test case will result in a JUnit 5 extension - in this example: generated.order_fulfillment.TC_Happy_Path.

Implement tests

In this example, TC_Happy_Path must be imported and used as a JUnit 5 extension (a public field, which is annotated with @RegisterExtension).

@RegisterExtension
public TC_Happy_Path tc = new TC_Happy_Path();

Calling createExecutor() on the test rule, provides a fluent API, which is used to specify variables, business key and/or beans that are considered during test case execution. After the specification, execute() is called to create a new process instance and exeute the test case.

Moreover the default behavior of wait states and call activities can be adjusted using fluent APIs. For each applicable flow node a "handle*" method is generated - for example: handleCheckAvailabilityUserTask().

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import generated.order_fulfillment.TC_Happy_Path;

public class OrderFulfillmentTest {

  @RegisterExtension
  public TC_Happy_Path tc = new TC_Happy_Path();

  @Test
  public void testItemsAvailable() {
    // fluent API for user task "checkAvailabilityUserTask"
    tc.handleCheckAvailabilityUserTask()
      .verify((pi, task) -> {
        // verify wait state
        pi.variables().containsEntry("customerId", 123);

        task.hasCandidateGroup("group-xyz");
      })
      .withVariable("available", true)
      .complete();

    // enrich and execute test case
    tc.createExecutor()
      .withBusinessKey("order-20210623-0001")
      .withVariable("customerId", 123)
      .withVariable("customerType", "NEW")
      .withBean("approveOrder", new ApproveOrderDelegate())
      .verify(pi -> {
        // verify state after execution
        pi.isEnded();
      })
      .execute();
  }
}

When a test is started, the generated code handles the creation of the process engine as well as the process definition deployment. On the other hand, the test case execution handles the process instance start, applies the specified behavior and verifies that the process instance has passed the correct activities.

A developer can solely focus on the actual implementation!

More screenshots

order-fulfillment-canceled-by-customer.png
Arbitrary paths
order-fulfillment-invalid-path.png
Test case validation

About

Visually select paths through a BPMN process as test cases. Generate and enrich those test cases for easier unit testing of your process implementations.

License:Apache License 2.0


Languages

Language:Java 78.9%Language:JavaScript 16.4%Language:RobotFramework 3.8%Language:CSS 0.8%Language:Shell 0.1%