第12章 ビジネスプロセスのテスト
ビジネスプロセスは動的に更新でき、エラーを発生させる可能性があるため、プロセスビジネスのテストは、他の開発アーティファクトと同様のビジネスプロセスライフサイクルの一部でもあります。
ビジネスプロセスのユニットテストにより、特定のユースケースでプロセスが想定通りに動作するようになります。たとえば、特定の入力に基づいて出力をテストできます。単体テストを簡素化するために、Red Hat Process Automation Manager には org.jbpm.test.JbpmJUnitBaseTestCase クラスが含まれています。
JbpmJUnitBaseTestCase は、Red Hat Process Automation Manager 関連のテストに使用するベーステストケースクラスとして実行されます。JbpmJUnitBaseTestCase は、以下の使用領域を提供します。
JUnit ライフサイクルメソッド
表12.1 JUnit ライフサイクルメソッド
メソッド 説明 setUpこのメソッドは
@Beforeのアノテーションが付けられます。データソースおよびEntityManagerFactoryを設定し、シングルトンのセッション ID を削除します。tearDownこのメソッドは
@Afterとしてアノテーションが付けられます。履歴を削除し、EntityManagerFactoryおよびデータソースを閉じ、RuntimeManagerおよびRuntimeEnginesを破棄します。ナレッジベースおよびナレッジセッション管理メソッド: セッションを作成するには、
RuntimeManagerおよびRuntimeEngineを作成します。以下のメソッドを使用してRuntimeManagerを作成および破棄します。表12.2
RuntimeManagerおよびRuntimeEngineの管理方法メソッド 説明 createRuntimeManager特定のアセットセットと選択したストラテジーに対して
RuntimeManagerを作成します。disposeRuntimeManagerテストの範囲でアクティブな
RuntimeManagerを破棄します。getRuntimeEngine指定されたコンテキスト用に新しい
RuntimeEngineを作成します。アサーション: アセットの状態をテストするには、以下のメソッドを使用します。
表12.3 管理メソッド
RuntimeManagerおよびRuntimeEngineアサーション 説明 assertProcessInstanceActive(long processInstanceId, KieSession ksession)指定した
processInstanceIdを持つプロセスインスタンスがアクティブかどうかを確認します。assertProcessInstanceCompleted(long processInstanceId)指定した
processInstanceIdを持つプロセスインスタンスが完了しているかどうかを確認します。セッション永続性が有効な場合にこのメソッドを使用できます。それ以外の場合は、assertProcessInstanceNotActive(long processInstanceId, KieSession ksession)を使用します。assertProcessInstanceAborted(long processInstanceId)指定された
processInstanceIdを持つプロセスインスタンスが中断されているかどうかを確認します。セッション永続性が有効な場合にこのメソッドを使用できます。それ以外の場合は、assertProcessInstanceNotActive(long processInstanceId, KieSession ksession)を使用します。assertNodeExists(ProcessInstance process, String… nodeNames)指定したプロセスに指定されたノードが含まれているかどうかを検証します。
assertNodeActive(long processInstanceId, KieSession ksession, String… name)指定した
processInstanceIdを持つプロセスインスタンスに、指定されたノード名を持つアクティブなノードが 1 つ以上含まれるかどうかを確認します。assertNodeTriggered(long processInstanceId, String… nodeNames)指定したプロセスインスタンスの実行中に、指定した各ノードに対してノードインスタンスがトリガーされているかどうかを確認します。
assertProcessVarExists(ProcessInstance process, String… processVarNames)指定したプロセスに指定されたプロセス変数が含まれているかどうかを検証します。
assertProcessNameEquals(ProcessInstance process, String name)指定した名前が指定されたプロセス名と一致するかどうかを確認します。
assertVersionEquals(ProcessInstance process, String version)指定したプロセスバージョンが指定されたプロセスバージョンと一致するかどうかを確認します。
ヘルパーメソッド: 以下のメソッドを使用して、永続性を使用または使用しない特定のプロセスセットに対して新しい
RuntimeManagerおよびRuntimeEngineを作成します。永続性の詳細は、Red Hat Process Automation Manager のプロセスエンジン を参照してください。表12.4 管理メソッド
RuntimeManagerおよびRuntimeEngineメソッド 説明 setupPoolingDataSourceデータソースを設定します。
getDs設定したデータソースを返します。
getEmf設定済みの
EntityManagerFactoryを返します。getTestWorkItemHandlerデフォルトのワークアイテムハンドラーに加えて登録できるテストワークアイテムハンドラーを返します。
clearHistory履歴ログを消去します。
以下の例は、開始イベント、スクリプトタスク、および終了イベントが含まれます。JUnit テスト例では、新規セッションを作成し、hello.bpmn プロセスを開始し、プロセスインスタンスが完了し、StartProcess ノード、Hello ノード、および EndProcess ノードが実行されているかどうかを確認します。
図12.1 hello.bpmn プロセスの JUnit テストの例

public class ProcessPersistenceTest extends JbpmJUnitBaseTestCase {
public ProcessPersistenceTest() {
super(true, true);
}
@Test
public void testProcess() {
createRuntimeManager("hello.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine();
KieSession ksession = runtimeEngine.getKieSession();
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
assertProcessInstanceNotActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "StartProcess", "Hello", "EndProcess");
}
}
JbpmJUnitBaseTestCase は、ユニットテストの一環として事前定義された RuntimeManager ストラテジーをすべてサポートします。そのため、1 つのテストの一部として RuntimeManager を作成するときに使用されるストラテジーを指定するだけで十分です。以下の例は、ユーザータスクを管理するタスクサービスでの PerProcessInstance ストラテジーの使用を示しています。
public class ProcessHumanTaskTest extends JbpmJUnitBaseTestCase {
private static final Logger logger = LoggerFactory.getLogger(ProcessHumanTaskTest.class);
public ProcessHumanTaskTest() {
super(true, false);
}
@Test
public void testProcessProcessInstanceStrategy() {
RuntimeManager manager = createRuntimeManager(Strategy.PROCESS_INSTANCE, "manager", "humantask.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get());
KieSession ksession = runtimeEngine.getKieSession();
TaskService taskService = runtimeEngine.getTaskService();
int ksessionID = ksession.getId();
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello");
assertProcessInstanceActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "Start", "Task 1");
manager.disposeRuntimeEngine(runtimeEngine);
runtimeEngine = getRuntimeEngine(ProcessInstanceIdContext.get(processInstance.getId()));
ksession = runtimeEngine.getKieSession();
taskService = runtimeEngine.getTaskService();
assertEquals(ksessionID, ksession.getId());
// let John execute Task 1
List<TaskSummary> list = taskService.getTasksAssignedAsPotentialOwner("john", "en-UK");
TaskSummary task = list.get(0);
logger.info("John is executing task {}", task.getName());
taskService.start(task.getId(), "john");
taskService.complete(task.getId(), "john", null);
assertNodeTriggered(processInstance.getId(), "Task 2");
// let Mary execute Task 2
list = taskService.getTasksAssignedAsPotentialOwner("mary", "en-UK");
task = list.get(0);
logger.info("Mary is executing task {}", task.getName());
taskService.start(task.getId(), "mary");
taskService.complete(task.getId(), "mary", null);
assertNodeTriggered(processInstance.getId(), "End");
assertProcessInstanceNotActive(processInstance.getId(), ksession);
}
}12.1. 外部サービスとの統合テスト
ビジネスプロセスには、多くの場合は、外部サービスの呼び出しが含まれます。ビジネスプロセスのユニットテストでは、特定のサービスが正しく要求されているかどうかを検証するテストハンドラーを登録し、要求されたサービスのテスト応答を提供できます。
外部サービスとの対話をテストするには、デフォルトの TestWorkItemHandler ハンドラーを使用します。TestWorkItemHandler を登録して、特定タイプのワークアイテムをすべて収集できます。また、TestWorkItemHandler にはタスクに関連するデータも含まれます。ワークアイテムは、特定の電子メールを送信したり特定のサービスを呼び出すなど、作業単位 1 つを表します。TestWorkItemHandler は、プロセスの実行中に特定のワークアイテムが要求されているかどうかを確認し、関連付けられたデータが正しいことを確認します。
以下の例は、メールタスクを検証する方法と、電子メールが送信されていない場合に例外が発生するかどうかを示しています。ユニットテストは、メールの要求時に実行されるテストハンドラーを使用し、送信者や受信者などの電子メールに関連するデータをテストできます。abortWorkItem() メソッドがメール配信の失敗についてエンジンに通知すると、ユニットテストではエラーを生成してアクションをログに記録することにより、プロセスがこのようなケースを処理することを検証します。この場合、プロセスインスタンスは最終的に中止されます。
図12.2 メールプロセスの例

public void testProcess2() {
createRuntimeManager("sample-process.bpmn");
RuntimeEngine runtimeEngine = getRuntimeEngine();
KieSession ksession = runtimeEngine.getKieSession();
TestWorkItemHandler testHandler = getTestWorkItemHandler();
ksession.getWorkItemManager().registerWorkItemHandler("Email", testHandler);
ProcessInstance processInstance = ksession.startProcess("com.sample.bpmn.hello2");
assertProcessInstanceActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "StartProcess", "Email");
WorkItem workItem = testHandler.getWorkItem();
assertNotNull(workItem);
assertEquals("Email", workItem.getName());
assertEquals("me@mail.com", workItem.getParameter("From"));
assertEquals("you@mail.com", workItem.getParameter("To"));
ksession.getWorkItemManager().abortWorkItem(workItem.getId());
assertProcessInstanceNotActive(processInstance.getId(), ksession);
assertNodeTriggered(processInstance.getId(), "Gateway", "Failed", "Error");
}