How to do Automated Testing for IBM BPM (Part III) - Process Flow Testing
Let’s talk about Process Flow Testing..
A general rule of thumb for automated testing is that tests should be as explicit as possible. Implicit process flow testing (e.g. using Selenium) is not a good idea (primarily because of performance and stability reasons).
Your process flow tests should be simple atomic checks that all follow this basic pattern…
- Given a process instance in a given state
- When something happens
- Then the process instance is in a new state
You should think of process flow testing as testing individual transitions in your business process, ensuring that they behave as you expect them to.
Here's an example (using the process from here):
Given an instance of the "Request Something" process at the "Review Request" step called "$testIdentifier"
When the "Review Request" task matching "$testIdentifier" is completed with decision “Approve" by a “Manager"
Then a “Provision Request" task matching "$testIdentifier" is ready for an “Operator"
This looks (and is) pretty simple. The supporting glue code uses the REST API to do all the hard work. Let’s expand on the example…
1. Given an instance of the "Request Something" process at the "Review Request" step called "$testIdentifier"
There are a few ways that you can approach this one, the end result should be an instance in the desired state. One way to do it is as follows:
- Prepare the data (as JSON) using a loaded test fixture that is customised as necessary (e.g. do something with the $testIdentifier and make sure that the data is correct for the step).
- Start the process (with the data) by calling a Service via the REST API.
- Use the Move Token REST API to jump to the desired step.
I have mentioned before that sometimes a little development is necessary to facilitate automated testing. This is a good example of this. My top level process contains something like this:
The post-script on the start event is just to create a log entry. The timer lasts for 10 minutes (in case something goes wrong I want the instance to end) but I expect the token to be moved before the timer fires.
There are other approaches (I once used conditional activities throughout my process to support automated testing) but I think that moving the token is probably the best approach.
2. When the "Review Request" task matching "$testIdentifier" is completed with decision “Approve" by a “Manager"
This one’s pretty simple:
- Prepare the data (as JSON) using a loaded test fixture that is customised as necessary (e.g. inject the decision).
- Complete the task (with the data) via the REST API (link).
3. Then a “Provision Request" task matching "$testIdentifier" is ready for an “Operator"
This one’s equally straight-forward:
- Search for a task matching the $testIdentifier for the specified user/team using the REST API.
I’m currently using this REST API for my searching. It’s deprecated though so I will have to change things soon…
I haven’t included any Java code (please let me know if you need to know how to do any of this stuff in Java) but it’s all pretty simple. It’s important to make things robust so, for example, I have a function called waitForTaskToBeAvailable(…) that wraps my search for a task and then uses a fluent-wait pattern to keep checking (up to a specified time limit) for the expected task. One of the biggest challenges I faced in all of this work was creating glue code that is robust and reliable. It is worth the effort.
I found the following libraries extremely helpful (they significantly reduced the amount of code I had to write):
Rest Assured (http://rest-assured.io)
JSON Path (https://github.com/json-path/JsonPath)
Tracking Test Coverage
People always ask about test coverage, it’s not easy in IBM BPM. Here’s what I have so far...
I use the following Tags…
@testable
@tested
…and the following Smart Folders…
Tested
Needs Tests (e.g. @testable && ! @tested)
I encourage developers to clear the @tested Tag when they are working on a component and ensure that the tests are updated before it is put back. It would be awesome if there was a way to clear the @tested Tag whenever a @testable Tag component is modified.
This approach applies equally to all components (not just Processes) in IBM BPM. I just thought now was a good time to mention it.