หลังจากยุ่งกับงานประจำนานเลย ตอนนี้เริ่มกลับมาทำงาน Thesis แล้วครับ ถ้าใครสร้าง BPMN ด้วย Camunda ไปแล้วนั่น หาจะทดสอบมีได้หลายวิธีครับ เช่น
- Deploy Process เข้าไปที่ตัว BPMN Engine แล้วกด Test เลย
- Deploy Process แล้วใช้ REST API ของ BPMN Engine เพื่อส่งค่าเข้าไป
แต่ถ้ามาดูที่ตัว Camunda มีตัวช่วยสำหรับ Test เหมือนกันครับ โดยมีตัวช่วย ดังนี้
สร้าง BPMN ก่อนครับ
- มาดูที่ BPMN ที่ต้องการทดสอบก่อนครับ เป็น Flow การกู้เงินอย่างง่าย simpleLoan.bpmn

- ผมตั้ง Id และ Name ว่า "simpleLoan" ครับ

- ส่วน Task นั้นผมได้กำหนด id และ Name ให้ชื่อเหมือนกันครับ แต่ Id มีข้อจำกัด เรื่องของ space ผมเลยใช้ underscore (_) แทนครับ โดยที่ต้องการตั้งชื่อให้มันสื่อ เพราะจะได้เอาไปใช้ใน Unit Test ครับ

- จาก BPMN ที่ได้มา ผมสามารถกำหนด Test Path ได้ 3 เส้นทางครับ ดังนี้

มาลุย Code กันดีกว่าครับ
สำหรับ Tools ที่ผมใช้ IntelliJ กับ Camunda Test Project Template ครับ
เมื่อ Generate Project มาแล้วจะพบตัว InmemoryH2Test กับ process.bpmn ไม่ต้องสนใจครับ เราสร้างใหม่อยู่แล้ว
- นำไฟล์ simpleLoan.bpmn ไปวางไว้ในโพลเดอร์ Resource ของ Project ครับ
- จากนั้น สร้าง UnitTest Class ขึ้นมาใหม่ โดยใช้ชื่อว่า simpleLoanTest ครับ
เมื่อได้ Unit Test เปล่าๆขึ้นมาแล้วให้ใส่คำสั่งลงไปใน Class simpleLoanTest ครับ
- สร้าง Instance ของ ProcessEngine
@ClassRule @Rule public static ProcessEngineRule rule = TestCoverageProcessEngineRuleBuilder.create().build();
- กำหนดชื่อ Process ที่จะ Test ครับ
private static final String PROCESS_DEFINITION_KEY = "simpleLoan";
สร้าง Test initial @Before เพื่อบอกว่าก่อน Test ต้องมีการดึง BPMN Engine ออกมา เพื่อใช้งานก่อนครับ
@Before
public void setup() {
init(rule.getProcessEngine());
}จากนั้นลุยสร้าง Test ตามเส้นทางที่กำหนดเลยครับ โดย @Test เพื่อบอกว่าเป็น Test Case ครับ และ @Deployment สำหรับบอกว่าเราจะทดสอบ BPM์N อันไหนครับ ในที่นี้เป็นไฟล์ simpleLoan.bpmn ครับ
- เส้นทางที่ 1 - รายละเอียดไล้ตามใน Comment เลยครับ
@Test
@Deployment(resources = "simpleLoan.bpmn")
public void testWhenLoanAmountNotNeedToMakeCollateral() {
//Start Process
ProcessInstance processInstance = processEngine().getRuntimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY);
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Enter_Loan_Amount ?
assertThat(processInstance).task("Enter_Loan_Amount");
//ใส่ค่าให้ Task Enter_Loan_Amount
complete(task(processInstance), withVariables("name", "PingkungA"
, "loanAmt", 40000));
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Loan_Request_Complete ?
assertThat(processInstance).task("Loan_Request_Complete");
//ไปต่อ
complete(task());
//ตรวจสอบลำดับของ Task โดยเริ่มจาก Enter_Loan_Amount >> Loan_Request_Complete
assertThat(processInstance).hasPassedInOrder("Enter_Loan_Amount", "Loan_Request_Complete");
assertThat(processInstance).isEnded();
}- เส้นทางที่ 2 - รายละเอียดไล้ตามใน Comment เลยครับ
@Test
@Deployment(resources = "simpleLoan.bpmn")
public void testWhenLoanAmountNeedToMakeCollateralAndLoanRequestComplete() {
//Start Process
ProcessInstance processInstance = processEngine().getRuntimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY);
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Enter_Loan_Amount ?
assertThat(processInstance).task("Enter_Loan_Amount");
//ใส่ค่าให้ Task Enter_Loan_Amount
complete(task(processInstance), withVariables("name", "PingkungA"
, "loanAmt", 100000));
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Update_Collateral ?
assertThat(processInstance).task("Update_Collateral");
//ใส่ค่าให้ Task Update_Collateral
complete(task(processInstance), withVariables("collateralAmt", 71000
, "collaternalInfo", "นาฟิกา"));
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Loan_Request_Complete
assertThat(processInstance).task("Loan_Request_Complete");
//ไปต่อ
complete(task());
//ตรวจสอบลำดับของ Task โดยเริ่มจาก Enter_Loan_Amount >> Update_Collateral >> Loan_Request_Complete
assertThat(processInstance).hasPassedInOrder("Enter_Loan_Amount", "Update_Collateral", "Loan_Request_Complete");
assertThat(processInstance).isEnded();
}- เส้นทางที่ 3 - รายละเอียดไล้ตามใน Comment เลยครับ
@Test
@Deployment(resources = "simpleLoan.bpmn")
public void testWhenLoanAmountNeedToMakeCollateralAndLoanRequestReject() {
//Start Process
ProcessInstance processInstance = processEngine().getRuntimeService().startProcessInstanceByKey(PROCESS_DEFINITION_KEY);
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Enter_Loan_Amount ?
assertThat(processInstance).task("Enter_Loan_Amount");
//ใส่ค่าให้ Task Enter_Loan_Amount
complete(task(processInstance), withVariables("name", "PingkungA"
, "loanAmt", 100000));
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Update_Collateral ?
assertThat(processInstance).task("Update_Collateral");
//ใส่ค่าให้ Task Update_Collateral
complete(task(processInstance), withVariables("collateralAmt", 2500
, "collaternalInfo", "นาฟิกา"));
//ตรวจสอบว่า Task ตอนนี้อยู่ที่ไหนแล้ว ใช่ Reject_Loan_Request
assertThat(processInstance).task("Reject_Loan_Request");
//ไปต่อ
complete(task());
//ตรวจสอบลำดับของ Task โดยเริ่มจาก Enter_Loan_Amount >> Update_Collateral >> Reject_Loan_Request
assertThat(processInstance).hasPassedInOrder("Enter_Loan_Amount", "Update_Collateral", "Reject_Loan_Request");
assertThat(processInstance).isEnded();
}ทดสอบ Run Unit Test ดูครับ

หมายเหตุ : ผมยังเล่นกับแต่ User Task นะครับ แต่ส่วนอื่นๆ ยังไม่ได้ทดสอบนะครับ
ERROR ที่พบ
ถ้าพบ Error ENGINE-16004 Exception while closing command context: Can't find scripting engine for 'groovy': scriptEngine is null ให้ใส่ dependency ลงไปในไฟล์ pom.xml ดังนี้
หมายเหตุ ให้เลือกเวอร์ชันของ Lib ให้เหมาะสมกับตัว Engine ด้วย
<!-- https://mvnrepository.com/artifact/org.codehaus.groovy/groovy-all --> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.5.2</version> <type>pom</type> </dependency>
Discover more from naiwaen@DebuggingSoft
Subscribe to get the latest posts sent to your email.



