测试整个过程路径

测试整个过程路径

 

 

为什么要测试流程模型?简短的答案是:从技术角度来看,BPMN是一种编程语言。因此,图应被视为代码。

我们将逐步介绍最佳做法和步骤,以简化测试,并仔细查看许多可用的库,包括:

  1. camunda-bpm-assert
  2. camunda-bpm-assert场景
  3. camunda-bpm-mockito
  4. camunda-bpm-jgiven
  5. flowcov-camunda
  6. camunda-bpm-process-test-coverage

在测试模型时,您可能会遇到以下问题:

  1. 何时以及如何使用这些不同的库?
  2. 究竟应该测试什么–模型和/或执行的代码?
  3. 如何处理对其他模型的依赖性?
  4. 如何衡量我的考试覆盖率?

我们将主要关注第一个测试范围并使用Java编写单元测试。

 测试整个流程路径

 

今天的主题是:测试整个流程路径

让我们看一下以下订单履行过程:

订单过程

 

“整个过程路径”表示从头到尾进行测试。对于复杂的模型,我们经常看到测试用例仅覆盖某些部分。在我们的流程中,一个示例是分别测试订单取消。您可能要采用此方法的原因是,之前和之后的序列已经过测试,或者各个测试用例变得更大且修改起来更复杂。

 

但是,您应该始终测试整个过程路径,以确保:

  1. 考虑到过程中的依赖关系:对之前或之后执行的元素进行更改可能会产生副作用。对于处理所需的变量更改尤其如此。
  2. 测试用例的定义得到简化:乍一看,这听起来是矛盾的。但是我们发现,考虑整个流程场景可以简化测试用例的定义。特别是在仅考虑替代方案中活动和数据的不同行为时。
  3. 过程中的调整变得更加容易:因为考虑了整个过程,所以可以更加确定地对过程进行调整。

但是,在某些情况下,测试流程的各个活动是有意义的。一个示例是可重用组件。例如,任务“发送取消”可以是用于发送电子邮件的可重用服务任务。但是,它不仅应在订单履行过程中进行测试,而且还应在单独的范围内进行测试。

 

使用camunda-bpm-assert库,可以非常轻松地测试这些小的可重用组件。但是,测试更复杂的过程会导致冗余或不清楚的代码。因此,camunda-bpm-assert-scenario可用于测试整个过程路径。

定义默认行为:首先,为所有元素定义默认行为。这也适用于不在“快乐道路”上的任务,例如“取消订单”任务。这意味着在各个方案中仅需要指定行为差异。

 

@Before

public void defaultScenario() {

    MockitoAnnotations.initMocks(this);

    Mocks.register("sendCancellationDelegate", new SendCancellationDelegate());

 

    //Happy-Path

    when(testOrderProcess.waitsAtUserTask(TASK_CHECK_AVAILABILITY))

            .thenReturn(task -> {

                task.complete(withVariables(VAR_PRODUCTS_AVAILABLE, true));

            });

 

    when(testOrderProcess.waitsAtUserTask(TASK_PREPARE_ORDER))

            .thenReturn(TaskDelegate::complete);

 

    when(testOrderProcess.waitsAtUserTask(TASK_DELIVER_ORDER))

            .thenReturn(task -> {

                task.complete(withVariables(VAR_ORDER_DELIVERED, true));

            });

 

    //Further Activities

    when(testOrderProcess.waitsAtUserTask(TASK_CANCEL_ORDER))

            .thenReturn(TaskDelegate::complete);

}

标识具有不同输出的活动:此步骤是关于标识提供替代输出的活动,以便该过程根据输出采用不同的路径。这些活动通常位于“包含”或“专用”网关之前。在我们的示例中,这适用于两个任务。

“交付订单”活动甚至还有两个附加方案。

  1. 订单无法成功交付,第二天将重试
  2. 无法交货,必须取消订单。

在确定了不同的场景之后,现在可以实施特定的测试用例。

实施测试用例:为了使实施尽可能简单,仅考虑与流程相关的变量。

为此,您仅需启动场景。之后,可以检查某些元素或结束事件是否已完成。

 

@Test

public void shouldExecuteHappyPath() {

    Scenario.run(testOrderProcess)

            .startByKey(PROCESS_KEY)

            .execute();

 

    verify(testOrderProcess)

            .hasFinished(END_EVENT_ORDER_FULLFILLED);

}

发送取消

我们需要覆盖“检查可用性”任务的行为:

 

@Test

public void shouldExecuteCancellationSent() {

    when(testOrderProcess.waitsAtUserTask(TASK_CHECK_AVAILABILITY)).thenReturn(task -> {

        task.complete(withVariables(VAR_PRODUCTS_AVAILABLE, false));

    });

 

    Scenario.run(testOrderProcess)

            .startByKey(PROCESS_KEY)

            .execute();

 

    verify(testOrderProcess)

            .hasFinished(END_EVENT_CANCELLATION_SENT);

}

取消订单

为了测试这一点,我们需要在“交付订单”任务中抛出错误而不是完成它:

 

@Test

public void shouldExecuteOrderCancelled() {

    when(testOrderProcess.waitsAtUserTask(TASK_DELIVER_ORDER)).thenReturn(task -> {

        taskService().handleBpmnError(task.getId(), "OrderCancelled");

    });

 

    Scenario.run(testOrderProcess)

            .startByKey(PROCESS_KEY)

            .execute();

           

    verify(testOrderProcess)

            .hasCompleted(TASK_CANCEL_ORDER);

    verify(testOrderProcess)

            .hasFinished(END_EVENT_ORDER_CANCELLED);

}

两次交付

要使用计时器事件执行循环,然后完成该过程,我们需要为“交付订单”任务定义两种不同的方案:

 

@Test

public void shouldExecuteDeliverTwice() {

    when(testOrderProcess.waitsAtUserTask(TASK_DELIVER_ORDER)).thenReturn(task -> {

        task.complete(withVariables(VAR_ORDER_DELIVERED, false));

    }, task -> {

        task.complete(withVariables(VAR_ORDER_DELIVERED, true));

    });

 

    Scenario.run(testOrderProcess)

            .startByKey(PROCESS_KEY)

            .execute();

 

    verify(testOrderProcess, times(2))

            .hasCompleted(TASK_DELIVER_ORDER);

    verify(testOrderProcess)

            .hasFinished(END_EVENT_ORDER_FULLFILLED);

}

 

相关教程