camunda-community-hub / zeebe-spec

A tool to run tests for BPMN processes on Zeebe
Apache License 2.0
29 stars 5 forks source link
bpmn test-framework zeebe zeebe-tool

Zeebe Spec

License

Compatible with: Camunda Platform 8

[!IMPORTANT] This community extension is unmaintained and outdated. It may not support new Camunda versions.

Thank you to all contributors for making it a great extension. :tada:

A tool to run tests for BPMN processes on Zeebe.

The idea

Install

The tests can be run by calling the SpecRunner directly in code, or by using the JUnit integration.

JUnit Integration

1) Add the Maven dependencies:

<dependency>
  <groupId>org.camunda.community</groupId>
  <artifactId>zeebe-spec-junit-extension</artifactId>
  <version>3.0.0</version>
  <scope>test</scope>
</dependency>

2) Put the spec and BPMN files in the resource folder (e.g. /src/test/resources/)

3) Write a JUnit test class like the following (here in Kotlin):

package my.package

import org.camunda.community.zeebe.spec.SpecRunner
import org.camunda.community.zeebe.spec.assertj.SpecAssertions.assertThat
import org.junit.jupiter.params.ParameterizedTest

@ZeebeSpecRunner
class BpmnTest(private val specRunner: SpecRunner) {

    @ParameterizedTest
    @ZeebeSpecSource(specDirectory = "specs")
    fun `should pass all tests`(spec: ZeebeSpecTestCase) {

        val testResult = specRunner.runSingleTestCase(spec.testCase)

        assertThat(testResult).isSuccessful()
    }

}

4) Run the JUnit test class

Junit test results

Usage

Example spec with one test case:

YAML Spec

testCases:
  - name: fulfill-condition
    description: should fulfill the condition and enter the upper task
    instructions:
      - action: create-instance
        args:
          bpmn_process_id: exclusive-gateway
      - action: complete-task
        args:
          job_type: a
          variables: '{"x":8}'
      - verification: element-instance-state
        args:
          element_name: B
          state: activated

Kotlin Spec

val testSpecFulfillCondition =
    testSpec {
        testCase(
            name = "fulfill-condition",
            description = "should fulfill the condition and enter the upper task"
        ) {
            createInstance(bpmnProcessId = "exclusive-gateway")

            completeTask(jobType = "a", variables = mapOf("x" to 8))

            verifyElementInstanceState(
                selector = byName("B"),
                state = ElementInstanceState.ACTIVATED
            )
        }
    }

The Spec

A spec is written in a YAML text format, or alternative in Kotlin code. It contains the following elements:

Actions

Actions drive the test case forward until the result is checked using the verifications. The following actions are available:

create-instance

Create a new instance of a process.

      - action: create-instance
        args:
          bpmn_process_id: demo
          variables: '{"x":1}'

complete-task

Complete tasks of a given type.

      - action: complete-task
        args:
          job_type: a
          variables: '{"y":2}'

throw-error

Throw error events for tasks of a given type.

      - action: throw-error
        args:
          job_type: b
          error_code: error-1

publish-message

Publish a new message event.

      - action: publish-message
        args:
          message_name: message-1
          correlation_key: key-1
          variables: '{"z":3}'

cancel-instance

Cancel/terminate a process instance.

      - action: cancel-instance
        args:
          process_instance: process-1

await-element-instance-state

Await until an element of the process instance is in the given state.

      - action: await-element-instance-state
        args:
          element_name: B
          state: activated

Verifications

Verifications check the result of the test case after all actions are applied. The following verifications are available:

process-instance-state

Check if the process instance is in a given state.

      - verification: process-instance-state
        args:
          state: completed

element-instance-state

Check if an element of the process instance is in a given state.

      - verification: element-instance-state
        args:
          element_name: B
          state: activated

process-instance-variable

Check if the process instance has a variable with the given name and value. If the element name or id is set then it checks only for (local) variables in the scope of the element.

      - verification: process-instance-variable
        args:
          name: x
          value: '1'

no-process-instance-variable

Check if the process instance has no variable with the given name. If the element name or id is set then it checks only for (local) variables in the scope of the element.

      - verification: no-process-instance-variable
        args:
          name: y
          element_name: B

incident-state

Check if the process instance has an incident in the given state. If the element name or id is set then it checks only for incidents in the scope of the element.

      - verification: incident-state
        args:
          error_type: EXTRACT_VALUE_ERROR
          error_message: "failed to evaluate expression 'key': no variable found for name 'key'"
          state: created
          element_name: B