Stardust/Knowledge Base/Testing/How to test Stardust
Whatever your favorite framework for testing may be, JUnit or TestNG or anything similar, you should not have a problem unit testing your individual pieces of code that are invoked throughout your business process. That means that whatever you're using as 'applications' in a Stardust process, it can most likely be unit tested. This could be a Pojo that performs some calculations, a business rule, or a web service. Even UIs can be unit tested given the appropriate tools, e.g. Selenium.
This article discusses the usage of a testing framework to test the 'big picture' once all the above mentioned pieces have been integrated into an end-to-end business process.
Testing business processes
First of all the question arises how to perform tests against a complete Stardust runtime environment. Test suites generally should be self-contained: they should be able to set up their own environment reproducibly and clean up after themselves. But that is not always possible. In case you're running Stardust in EJB mode on a J2EE application server, the effort to control the environment through your test cases might be too great and when running tests, the answer might simply be to manually set up an environment for the tests by making sure that the server is started up and the Stardust runtime is deployed and configured correctly. With Stardust deployed in Spring mode it becomes easier to create your Stardust runtime environment specifically for the test runs. The downloadable Stardust Process Driver project contains this JUnit4 test case which demonstrates this approach. It performs the following steps:
- The global startup phase of the test is executed only once and it takes care of the following tasks:
- It checks for a Derby database instance to be used and it creates one automatically if needed.
- After booting the database it tries to query a table from the Stardust AuditTrail schema. If unsuccessful, the AuditTrail schema is created.
- It then boots a Spring-based Stardust runtime environment.
- Finally a process model is deployed into this environment.
- Then, all individual tests are executed.
Afterwards, the process model which was deployed during the startup is removed which results in all created processes being deleted as well, effectively leaving no traces of the test runs.
For the individual tests the question is 'What assumptions about your processes do you want to test'? Here are some typical examples:
If I run a XYZ process with an amount greater than $100,000 dollars, I need it to go through the review step.
When the initial automatic validation checks and message parsing of my process are completed, I expect to find a 'Select Contract' work item in the workbasket of role 'ABC'
After completing the AddressChange process, the client record in my database should be up-to-date with the new address.
In order to automate this testing, you sometimes need to 'drive' the process forward, e.g. to simulate a user completing a work item. Furthermore, the state of a process and its data needs to be queried to verify test assumptions. All of this can be accomplished using the Stardust API.
Completing an activity
When a process instance arrives at an activity that does not complete automatically, e.g. a manual activity, you can use the WorkflowService to simulate the user's interaction. The Map argument that is passed into the following method contains the IDs and data of the OUT-Data-Mappings for that activity as specified in the process model to pass data back to the process.
workflowService.activateAndComplete(long activityInstanceOID, String context, Map outData)
Manipulating process data
The following API calls can be used to read and write process data. The data you want to access this way must be declared as IN- or OUT-Data-Path in the properties of the process definition in the process model with IN corresponding to read access and OUT specifying write privileges.
workflowService.getInDataPath(long processInstanceOID, String id) workflowService.getInDataPaths(long processInstanceOID, Set ids) workflowService.setOutDataPath(long processInstanceOID, String id, Object object) workflowService.setOutDataPaths(long processInstanceOID, Map values)
Querying process and activity state
The Stardust Query Framework can be used to retrieve process instances as well as activity instances while applying a wide range of filter criteria. Following are merely a few examples. For the full depth of the Query Framework's functionalities please refer to IPP's documentation.
ProcessInstanceQuery piQuery = ProcessInstanceQuery.findForProcess("AccountOpening"); piQuery.where( DataFilter.isEqual("Customer", "lastname", "Smith"); int resultCount = queryService.getProcessInstancesCount( piQuery );
The above code snippet queries for the number of instances of the Account Opening process for a customer with lastname 'Smith'. Here's another example using an ActivityInstanceQuery.
ActivityInstanceQuery aiQuery = ActivityInstanceQuery.findInState( ActivityInstanceState.Hibernated ); aiQuery.where( ActivityFilter.forProcess("AccountOpening", "WaitingForSignedContract") ); Calendar cal = Calendar.getInstance(); cal.add( Calendar.DAY_OF_MONTH, -1 ); cal.set( Calendar.HOUR_OF_DAY, 8 ); aiQuery.where( ActivityInstanceQuery.START_TIME.lessThan(cal.getTimeInMillis()) ); ActivityInstances instances = queryService.getAllActivityInstances( aiQuery );
In this example the query would retrieve all instances of the WaitingForSignedContract activity belonging to the Account Opening process which are currently in a hibernated state. An additional filter is applied to find only those instances that were created before 8:00 AM yesterday. This kind of query could be interesting in a test scenario where you would not expect to find any instances, because an escalation timer had been created for this activity in the process model. This query returning any instances would then indicate that the escalation did not work.
Every business process is unique in a way and even though testing all of its aspects could be automated, the efforts needed to do so vary greatly and in practice it's not always worth it. Therefore, how to use the approaches and API calls presented in this article needs to be discussed differently from project to project. A lot of times it may even be cheaper to rely on a larger number of people to cover testing the fully integrated system than to invest into writing automated test cases.