Unit Testing Business Processes in Oracle BPM Suite

One of the fundamental challenges that every individual/team experiences when implementing business processes using Oracle BPM Suite 11g is the ability to run unit tests. Managers and testers direly want unit testing from developers to ensure code quality and stability. Another important requirement around testing is around coverage i.e how to ensure that all possible scenarios represented by the business processes are properly unit tested. Having a stringent methodology towards unit testing and a framework of executing them every time a  functionality is changed or when the business processes are deployed is a much desired and essential feature. Unfortunately there is a dearth of information available for developers to be able to create a complete and comprehensive framework of unit testing. As such, a lack of this knowledge is a big deterrent and this blog will, in details, cover the soup to nuts of planning, creating and executing a unit testing methodology that provides an almost cent precent coverage of all scenarios in a business process.

The Problem Statement

The credibility of a business process lies not only in the way it has been implemented but also in it being diligently tested for all outcomes and scenarios. Business processes implemented with BPMN 2.0 posses a greater challenge as processes tend to be fairly unstructured and involve a lot of components like decision functions, workflow tasks, events and services to name a few. As such it is very challenging to ensure that the processes being implemented are fully tested and hundred per cent compliant with how they are intended to function. It is no surprise that without a concrete unit testing the QA phase of the project is marred with several issues and this is when you start to feel that a lot of bugs could have been spotted and fixed during the development phase if there had been some sort of mechanism to test various routes of a process map. To add to the woes, I have seen many projects either performing these tests manually as a series of steps per test case or trying desperately to create a complex framework of using API’s to initiate a process instance, obtain and complete task items, stub service components etc.  The problem with both these approaches are that they are time consuming and relatively prone to errors. Because every project is usually always on a tight schedule, these tests are not executed and the issues are not spotted during the development cycle. Another option is to use various off the shelf testing suites available in the market but they tend to be expensive, have a steep learning curve and may not always fit the the bill.

This article take a unique approach that employs the existing unit testing framework available with Oracle BPM Suite 11g together with proven scientific software testing techniques to achieve an almost full coverage of unit tests for business processes.

The Sample Business Process

In order to demonstrate the philosophies expressed earlier and the testing techniques to follow , this article considers a simple employee expense approval process that has primarily all the ingredients that any complex business process has i.e it is fairly unstructured, have business rules, human workflow components, arbitrary cycles, gateways and events.

The process is fairly easy to understand. There are two actors in this process viz. Expense Approver (typically a manager) and a Finance Approver. An expense approval request event is evaluated against a business rule to determine whether it can be automatically approved. If so, it is sent to a finance admin to review and disburse payment if everything is right and green. If the expenses over-reach the auto approval limits and/or if the finance admin rejects them, they then go to the manager who then have to approve or reject them. Only manager can reject an expense for it to be recorded as rejected. The finance approver can only refer it back to the manager if he finds it to be incorrect. Well, this may not be the ideal and most comprehensive expense management process, but for the purpose of this demonstration, this variation is fairly suitable considering the commonalities.

ExpenseApproval

With the problem statement laid out and the sample business process being considered, the challenge is how can we guarantee that the different routes in this process can be thoroughly unit tested. 

Prerequisite(s)

The modelling workspace and the version of Oracle BPM Suite used in this demonstration is 11gR1PS5 i.e 11.1.1.6 although the concepts discussed are generic and applicable to all versions. I have also used MS-Visio for the simplified block diagrams but any diagramming tool can be used instead.

Testing Methodology

The testing methodology being discussed here is holistically categorized into five different steps, with each steps being characterized by a distinct set of functions and objectives.

Structuring

The first step is the structuring step wherein the process map needs to have a finalized structure with all scenarios being identified and modeled including the exception paths. The structuring step may begin with the definition of the highest level business process diagrams such as process choreographies or collaboration diagrams, etc. (https://beatechnologies.wordpress.com/2011/10/17/choreography-collaboration-and-oracle-bpm-11g/) but it is to be considered complete when the BPMN models are finalized and approved.

Reconstruction

This step is generally required if the business process is not straight forward and a plain vanilla type which is unusual in most cases. A reconstruction of the BPMN model is necessary to be able to evaluate the possible number of routes in the process map. The processes are simplified to be represented as block diagrams to uniquely identify all actors, events and sequence flows only with each of them marked generically. A couple of guidelines to reconstruct are:

  1. Represent each activity, event and sequence flow with a distinct name to convey the process flow (RULE for decision activity, SERVICE for sync/async communications with external systems, initial trigger and final outcome for events, approval actions for sequences etc.). You may use alphabets as suffixes if there are more than one similar activities.
  2. Optionally use colour coding for sequence flows to represent happy and alternative paths in a business process.
  3. Use markers in sequence flow to indicate its execution ability (parallel, conditional, inclusive etc.) with respect to other sequence flow from the same activity.

The following diagram represents a simplified skeleton for the expense approval business process with bare minimum semantics. As you can see that the model generalizes the name of each activity/event/sequence in the business process. A default and a conditional marker is also used to represent the execution flow path from a given node. 

SimplifiedExpenseApprovalV1

There is just one more step to reconstruct the diagram further. For as much as possible, try to group the likely marked activities together to make the diagram look simpler.  The final reconstructed diagram should ensure that each activity has uniquely different sequence flow originating out of it. If there are more than one similar sequence flow that originates from an activity then group them as one. For instance there are two default sequence flow originating out of the FINANCE activity and leading to the service activities SERVICE C and SERVICE D. These activities have to be combined/grouped to represent a single activity and there should just be one default sequence flow leading out of the FINANCE activity into it. The simplified and final reconstructed model would look like the one shown below.

SimplifiedExpenseApprovalV2

Evaluation

Having a simplified and reconstructed model is a significant milestone as it is required to measure the number of linearly independent routes in a business process. This is a very essential piece of information to derive at the minimum number of test cases required to unit test the business process to ensure it has a full coverage. To determine the minimum number of test cases required to cover all possible process routes for the expense approval business process, McCabe’s Cyclomatic Complexity algorithm can be applied.  Cyclomatic complexity can be computed using the reconstructed control flow diagram of the business processes. The Basis Path Testing by McCabe who first proposed it, is to test each linearly independent path in the business process; in this case, the number of test cases will equal the computed cyclomatic complexity.

The cyclomatic complexity, M, is evaluated as:

M = S – A + 2E

where

 S = the total number of sequences (edges) in the restructured process diagram
A = the number of events and activities (nodes) in the process
E = the number of end events in a business processes (connected components)

Looking at the restructured process map for expense approval will reveal that there are 10 sequences and 9 nodes (6 activities, 3 events) and 2 end events. Hence the maximum number of test cases required for full test coverage can be determined as:

M = 10-9+2*2 = 5

It is now easy to determine the test cases to be executed by a casual inspection of the reconstructed process graph. The following test cases shows the various routes a process can take from the conditional nodes.

Test Case 1: Submit, Auto Approve, Finance Approve, Approve
Test Case 2: Submit, Auto Approve, Finance Reject, Refer
Test Case 3: Submit, Refer, Manager Approve, Finance Approve, Approve
Test Case 4: Submit, Refer, Manager Approve, Finance Reject, Refer
Test Case 5: Submit, Refer, Manager Reject, Reject

Another important use of McCabe’s number (cyclomatic complexity calculation) is to understand and limit the complexity of a business process. It is recommended that the complexity of a business process should not exceed the figure of 10. If it does then it is advisable to split it into multiple processes.

Process Implementation

The expense approval business process implementation is not covered in this blog but readers are free to create an expense business object, define the conditional logic, auto generate UI for the task forms and so forth. If you want to spare yourself from that effort then an implemented process can be downloaded from here. The implemented process looks like below in the studio canvass.

image

Test Suite Creation

From a unit testing perspective, there are two things that should be predominantly tested. One is the business process itself and all its possible paths. This has been explained already and a strategy defined. Another thing that is important to test is the business rule component.  Well the approach to be taken depends upon the nature of the rules and their effect on the business processes. If the business rule is merely to dynamically determine a condition that defines the process path (followed by an exclusive gateway) then testing the business process should cover it. However, if the business rules executes conditions to create dynamic process data, then testing the business processes is not sufficient. A more thorough unit testing of the business rule must also be carried out.

The below three blog posts cover testing of business rules extensively by a wide variety of means.

https://beatechnologies.wordpress.com/2011/04/19/using-and-testing-complex-business-rules-in-oracle-soasuite-11g/

https://beatechnologies.wordpress.com/2011/07/07/testing-oracle-business-rules-using-java/

https://beatechnologies.wordpress.com/2012/03/09/automating-business-rules-testing-in-oracle-soa-suite-11g/

This blog intends to build upon the strategies covered in the above posts but also refine it further to create automated tests that can be executed using Ant or Maven and a detailed JUnit type report published for them.

Unit Testing the Business Process

There may be many strategies to test the business process in an end to end manner but this post focuses primarily on unit testing. This is more appropriate is scenarios where a testing has to be carried out by possibly stubbing out behaviours of external systems that the business process is dealing with. A readily available and out of the box tool to test a business process is the composite test framework. But the interesting challenge is how this framework can be used to test a business process with complex human tasks, events, business rules, etc. and this is something that is aimed here.

  • Begin by creating a test suite by right clicking on the testsuites folder under SOA Content in JDeveloper. Name this test suite as ExpenseApprovalTest. This will create a folder by this name and some auto generated contents within them.

image

  • Next right click on the generated test suite and click Create Test to create a unit test case for the composite. It is advisable to put an apt name and description for the test case so that it explains the scenario being tested. This will generate an .xml file by the test case name in the tests sub-directory.

image

  • Double click the .xml file to open it in JDeveloper. The editor opens the test view of the composite with all the services, components and references. This test view allows to create pretty sophisticated unit tests by providing the following options.
    • Define Initiate Messages to start the business process if it is based on a message based start. Else initiate events or the Initiate task can be used to invoke a manually triggered business process.
    • Each wire leading from the service, component and reference can be configured with Wire Actions. The wire actions can emulate the response from the target component if the component is not implemented. The wire action can also assert expected response(s) with the actual response or the emulated response from the output message of target components. Multiple assertions can also be configured on the same wire actions.

image

  • Double click on the binding element at the ApproveEmployeeExpense service. This launches the Initiate Messages wizard. Generate a sample message that conforms to the request type that this service expects.

image

  • The generated sample has dummy values which can be replaced with actual test values. In this case, use the following sample request.  This message is used to invoke the submit expense application start event message in the business process.

Initiate Message

<submitExpenseApplication xmlns="http://www.rubiconred.com/ApproveEmployeeExpense">
<Expense xmlns="http://www.rubiconred.com/bpmtest/empl">
<Employee>
<EmployeeID>1312331</EmployeeID>
<FirstName>Arrun</FirstName>
<LastName>Pareek</LastName>
<Email>arun.pareek@rubiconred.com</Email>
<PhoneNumber>0424987673</PhoneNumber>
<ManagerID>6312313</ManagerID>
<DepartmentID>132313</DepartmentID>
<BusinessUnit>1</BusinessUnit>
</Employee>
<ExpenseList>
<Amount>5500</Amount>
<Type>Travel</Type>
<Date>2013-02-06</Date>
<Justification>Travel on Business</Justification>
<Authoriser>Matt</Authoriser>
</ExpenseList>
<ExpenseList>
<Amount>4000</Amount>
<Type>Meals</Type>
<Date>2013-02-06</Date>
<Justification>Meals</Justification>
<Authoriser>John</Authoriser>
</ExpenseList>
</Expense>
</submitExpenseApplication>

  • As the message arrives in the business process, an expense record is created in the database with an initial status. The operation to insert a message in the database is one-way and hence from the testing perspective, it is good enough to assert what is going in. A valid assertion for unit testing for this test case is to validate the expenseTotal element in the input request and match it to the sum of all expenses in the expense list.

image

  • The next step in the business process is the business rule task and the response (output) from the business rule can be asserted by modifying the wire action between the business process and the business rule. At the moment the business rule is configured to respond back with a status of pre-approval i.e whether an approval from the manager is required or not. This test case assumes that the manager approval is not required as the values in the expense item list determine the rule output. This can be asserted against the expected response. The business rule is configured to auto approve expenses less than 10k for employees in the Sales business unit Sales (determined by the integer value of 1).
  • At this point the business rule component can be opened to see how it processes the employee expense fact and what is the response action.

    image

  • As mentioned before, it is recommended to have a detailed unit testing suite created solely for business rules as they may or may not determine the process path. Also the business process testing should be based on the rule outcome which is either Approved or Referred. But the business rule outcome can depend upon a lot of factors. For the example considered here, the business rule vets the outcome differently for different business units i.e the auto approval threshold is different depending upon the business unit the employee belongs too. Hence it is advisable to test the rules separately. A quick approach to do so will be discussed here shortly.

  • The next activity that will be executed in this test case is the Administer Expense Payment human task assigned to the Finance admin. Till this point all the activities being asserted against will automatically produce a result/outcome. But a human task is a manual step in the business process that is performed by a process participant. Hence the way to emulate a human task response in a test case is tricky. Fortunately the test composite allows emulating call-backs for human tasks that can mock task execution.

  • Begin by double clicking on the wire between the business process and FinanceApproval human task component. This, as usual, launches the wire action wizard. Select initiateTask from the list of operation to emulate its call-back. The call-back should be emulated when the task has been completed and hence the callback operation to be chosen is onTaskCompleted.

Generating a sample for the call-back operation creates a workflow task request based on the task schema. It is complicated to create values based on this schema initially so it is advisable to get a generated one and then use it while creating the test case. All values in the task xml are unimportant except for the values within the payload element under the root and outcome element under systemAttributes. The payload content corresponds to the data object (s) defined for the human tasks and is used for passing the values to the process variables. Whereas the outcome is used to determine the business process flow beyond the human task.

image

  • Repeat the exact above steps for the updateTaskOutcome operation too. Behind the scenes when a human actor logs into the task workspace the following things happen.
    • Depending upon the workspace preference and role a list of tasks are displayed to the user. The queryTasks operation is used with the proper predicate for this purpose.
    • When a task item is selected the getTaskDetailsById function is executed to retrieve the details specific to the selected task.
    • All updates, captures and saves to the task in the workspace are persisted in the dehydration store via the updateTask operation.
    • When the task is finally actioned its outcome and state is updated via the updateTaskOutcome operation which sends a callback to the waiting business process instance about task completion.
  • The operations discussed here were just a high level overview of what happens to a human task in the general scenario. There are infinite other possibilities of what stages the human task may go through in terms of assignments, renewals, expiries etc. However the business process does not care about all that. It simply waits for a callback from the human task which happens either when the task is actioned or when it expires.
  • Emulating the callback for the updateTaskOutcome will pass the control back to the business process and it will then process ahead depending upon the task outcome. The task outcome for this test case is set to Approved.

RuleAssert2

  • The following request can be used to emulate the task responses for this project. The outcome determines what is the action performed on the task where as the payload corresponds to what the user sees in the screen and conforms to.

Task Response Payload

<task xmlns="http://xmlns.oracle.com/bpel/workflow/task">
<title>Approve Expenses for Arun Pareek</title>
<payload>
<ExpenseApproval xmlns="http://www.rubiconred.com/bpmtest/empl">
<Expense>
<ns2:Employee xmlns:ns2="http://www.rubiconred.com/bpmtest/empl">
<ns2:EmployeeID>1312331</ns2:EmployeeID>
<ns2:FirstName>Arrun</ns2:FirstName>
<ns2:LastName>Pareek</ns2:LastName>
<ns2:Email>arun.pareek@rubiconred.com</ns2:Email>
<ns2:PhoneNumber>0424987673</ns2:PhoneNumber>
<ns2:ManagerID>6312313</ns2:ManagerID>
<ns2:DepartmentID>132313</ns2:DepartmentID>
<ns2:BusinessUnit>1</ns2:BusinessUnit>
</ns2:Employee>
<ns2:ExpenseList xmlns:ns2="http://www.rubiconred.com/bpmtest/empl">
<ns2:Amount>2500</ns2:Amount>
<ns2:Type>Travel</ns2:Type>
<ns2:Date>2013-02-06</ns2:Date>
<ns2:Justification>Meals</ns2:Justification>
<ns2:Authoriser>Matt</ns2:Authoriser>
</ns2:ExpenseList>
<ns2:ExpenseList xmlns:ns2="http://www.rubiconred.com/bpmtest/empl">
<ns2:Amount>4000</ns2:Amount>
<ns2:Type>Meals</ns2:Type>
<ns2:Date>2013-02-06</ns2:Date>
<ns2:Justification>Meals</ns2:Justification>
<ns2:Authoriser>John</ns2:Authoriser>
</ns2:ExpenseList>
</Expense>
<ApprovalStatus xmlns:ApprovalStatus="http://www.rubiconred.com/bpmtest/empl">
<ApprovalStatus>Approved</ApprovalStatus>
<Comments>Expenses Approved</Comments>
</ApprovalStatus>
</ExpenseApproval>
</payload>
<taskDefinitionURI>default/ExpenseApprovalComposite!4.0/FinanceApproval</taskDefinitionURI>
<ownerRole>ExpenseApprovalProject.ProcessOwner</ownerRole>
<priority>2</priority>
<identityContext>jazn.com</identityContext>
<processInfo>
<instanceId>290011</instanceId>
<processId>ApproveEmployeeExpense</processId>
<processName>ApproveEmployeeExpense</processName>
</processInfo>
<systemAttributes>
<acquiredBy>weblogic</acquiredBy>
<approvalDuration>31958</approvalDuration>
<approvers>weblogic</approvers>
<assignedDate>2013-02-01T01:24:03+11:00</assignedDate>
<createdDate>2013-02-01T01:24:03+11:00</createdDate>
<customActions>
<action>APPROVE</action>
<displayName>Approve</displayName>
</customActions>
<customActions>
<action>REJECT</action>
<displayName>Reject</displayName>
</customActions>
<digitalSignatureRequired>false</digitalSignatureRequired>
<displayInfo>
<applicationName>worklist</applicationName>
<hostname>RubiconRed-PC</hostname>
<httpPort>7001</httpPort>
<httpsPort>0</httpsPort>
<uri>/workflow/FinanceApproval/faces/adf.task-flow?_id=FinanceApproval_TaskFlow&amp;_document=WEB-INF/FinanceApproval_TaskFlow.xml</uri>
</displayInfo>
<endDate>2013-02-01T01:24:34.958+11:00</endDate>
<hasSubTasks>false</hasSubTasks>
<inShortHistory>true</inShortHistory>
<isGroup>true</isGroup>
<numberOfTimesModified>4</numberOfTimesModified>
<outcome>APPROVE</outcome>
<passwordRequiredOnUpdate>false</passwordRequiredOnUpdate>
<pushbackSequence>INITIAL_ASSIGNEES;1-4</pushbackSequence>
<secureNotifications>false</secureNotifications>
<shortHistory>
<task>
<state>ASSIGNED</state>
<updatedBy>
<id>workflowsystem</id>
<type>user</type>
</updatedBy>
<updatedDate>2013-02-01T01:24:03+11:00</updatedDate>
<version>1</version>
<versionReason>TASK_VERSION_REASON_INITIATED</versionReason>
</task>
</shortHistory>
<state>COMPLETED</state>
<systemActions>
<action>UPDATE_COMMENT</action>
</systemActions>
<systemActions>
<action>SKIP_CURRENT_ASSIGNMENT</action>
</systemActions>
<systemActions>
<action>VIEW_SUB_TASKS</action>
</systemActions>
<systemActions>
<action>DELEGATE</action>
</systemActions>
<systemActions>
<action>SUSPEND</action>
</systemActions>
<systemActions>
<action>UPDATE</action>
</systemActions>
<systemActions>
<action>UPDATE_ATTACHMENT</action>
</systemActions>
<systemActions>
<action>SUSPEND_TIMERS</action>
</systemActions>
<systemActions>
<action>ESCALATE</action>
</systemActions>
<systemActions>
<action>VIEW_PROCESS_HISTORY</action>
</systemActions>
<systemActions>
<action>REASSIGN</action>
</systemActions>
<systemActions>
<action>VIEW_TASK</action>
</systemActions>
<systemActions>
<action>CUSTOM</action>
</systemActions>
<systemActions>
<action>OVERRIDE_ROUTING_SLIP</action>
</systemActions>
<systemActions>
<action>INFO_REQUEST</action>
</systemActions>
<systemActions>
<action>WITHDRAW</action>
</systemActions>
<systemActions>
<action>ACQUIRE</action>
</systemActions>
<systemActions>
<action>VIEW_TASK_HISTORY</action>
</systemActions>
<taskId>f17ceabd-7c23-431d-b538-3697fed9d421</taskId>
<taskNumber>200507</taskNumber>
<updatedBy>
<id>weblogic</id>
<displayName>weblogic</displayName>
<type>user</type>
</updatedBy>
<updatedDate>2013-02-01T01:24:34+11:00</updatedDate>
<version>4</version>
<versionReason>TASK_VERSION_REASON_COMPLETED</versionReason>
<taskDefinitionId>default/ExpenseApprovalComposite!4.0/FinanceApproval</taskDefinitionId>
<taskDefinitionName>FinanceApproval</taskDefinitionName>
<workflowPattern>Participant</workflowPattern>
<isTestTask>false</isTestTask>
<participantName>default.DefaultPerformer</participantName>
<assignees>
<id>FinanceApprover</id>
<displayName>FinanceApprover</displayName>
<type>application_role</type>
</assignees>
<rootTaskId>f17ceabd-7c23-431d-b538-3697fed9d421</rootTaskId>
<systemStringActions>PUSH_BACK,sharePayload</systemStringActions>
<isTemplateTask>false</isTemplateTask>
<taskViewContext>Action Required</taskViewContext>
<taskNamespace>http://xmlns.oracle.com/UnitTestingSample/ExpenseApprovalProject/FinanceApproval</taskNamespace>
<actionDisplayName>Assigned</actionDisplayName>
<timers/>
<componentType>Workflow</componentType>
<activityName>Administer Expense Payment</activityName>
<activityId>ABSTRACT_ACTIVITY580105091431</activityId>
<thread>0</thread>
<parentThread>-1</parentThread>
<swimlaneRole>FinanceApprover</swimlaneRole>
<timersSuspended>false</timersSuspended>
</systemAttributes>
<systemMessageAttributes/>
<callback>
<id>ApproveEmployeeExpense/HumanTasks.FinanceApproval.reference</id>
<converstationId>urn:DD2C56306BB111E28F475966BC8DFF84</converstationId>
</callback>
<isPublic>false</isPublic>
<percentageComplete>100.0</percentageComplete>
<sca>
<applicationName>default</applicationName>
<componentName>FinanceApproval</componentName>
<compositeDN>default/ExpenseApprovalComposite!4.0*soa_2673adb8-4e08-4734-a459-5715871259d6</compositeDN>
<compositeInstanceId>460011</compositeInstanceId>
<compositeName>ExpenseApprovalComposite</compositeName>
<compositeVersion>3.0</compositeVersion>
<ecId>1b7e5955c26b51de:3e996a9d:13c906f8522:-8000-00000000000044e4</ecId>
<parentComponentInstanceId>bpmn:290011</parentComponentInstanceId>
<parentComponentInstanceRefId>290011-ABSTRACT_ACTIVITY580105091431-ApproveEmployeeExpense_try.2-7</parentComponentInstanceRefId>
<compositeCreatedTime>2013-02-01T01:20:09.947+11:00</compositeCreatedTime>
</sca>
<applicationContext>OracleBPMProcessRolesApp</applicationContext>
<taskDefinitionId>default/ExpenseApprovalComposite!3.0/FinanceApproval</taskDefinitionId>
<correlationId>f17ceabd-7c23-431d-b538-3697fed9d421</correlationId>
<mdsLabel>soa_2673adb8-4e08-4734-a459-5715871259d6</mdsLabel>
<customAttributes/>
</task>

  • Post approval by the finance admin the last step in the process is saving the payment record in the database. This also being a one way operation, from the unit testing perspective add a test check to ensure that the payment amount being saved is equal to the sum of all amounts in the payment list.
  • This is done by adding an assertion in the wire between the RecordEmployeeExpense component and PaymentRegisterService reference in the test composite view.

image

  • Business processes ending with a message end event are asynchronous in nature (in most cases) where as the ones ending with an empty end events are one way. The ExpenseApprovalProcess is an asynchronous business process as it has an message based end event that sends the final status of the approval request. This status can also be asserted to test if the clients invoking the business process get a valid business response. The final assertion in the test case.
  • Response from the business process can be validated by asserting the payload of the call-back operation expensesPaid. The expected value of the approvalStatus should be FINANCE APPROVE for the given test case which can be entered in the assert value text field.

image

Apart from the unit testing steps covered, there is no harm in adding more test conditions. This has to be determined on use case basic and quality of unit testing to be produced. Also add as many test cases as derived according to McCabe’s number.

Similarly test cases have to be added to test each possible path in the business process as determined by the cyclomatic complexity algorithm. Alternatively download the composite to see all the test cases created for this exercise.

Unit Testing the Business Rule (s) Components

As explained earlier, it is recommended to not mix business rule testing and business process testing together. As you can see that there are only two possible approval statuses from the cascaded business rules below. The business process takes a due transition only based on the business rule outcome, i.e, the approval status. However the approval status could itself be derived in a lot of ways depending upon the business unit of the employee submitting the expense and also the sum of the expense amount.

image

To create using testing for business rules, I would recommend going through my previous blog that explains this in great details. The blog can be accessed here:

https://beatechnologies.wordpress.com/2012/03/09/automating-business-rules-testing-in-oracle-soa-suite-11g/

One missing piece to the puzzle however is to to plug the testing framework with ant or maven so that they can be run as part of the build and deployment cycle. This is briefly discussed in this blog too.

Test Execution

Using Enterprise Manager

The easiest way to invoke the unit test suite is by deploying the composite and then initiating the testing from the enterprise manager console.

  • Start the soa/bpm managed server and deploy to the composite to the default partition.
  • Login to the enterprise manager and then navigate to the ExpenseApprovalComposite under the deployed partition.
  • Clicking on the Unit Tests tab will show all the created test cases under the test suite. All or some of the test cases can be selected and then click the Execute button.
  • This will prompt for naming the test run. Provide a name and then click OK to start the testing.

image

  • Once the tests have finished executing the Test Runs displays the final status of the test run along with statuses of each test case. A detailed report is also available in the trail showing how each assertion fared. The Enterprise Manager offers a great view in terms of determining what the actual value of a given step was against its expected value. It also does a full XML compare to show the difference between expected and actual XML structures.
  • This is a great way to test/smoke test on-demand to determine if any changes made to the business process doesn’t effect its core flow and functionality.

image

Using JDeveloper Studio

Business rules created as part of the project have a great means to be unit tested using the out of the box test features. A test suite XML can be created for a given decision function that may contain multiple test cases. Each test case is comprised of an input structure to the business rule and an expected output structure which is ascertained with the actual output of the rule.

Running the test from the studio also creates an inline test report with all the details about each test case and the overall test suite.

image

These approaches are good and provides a mean to ensure that a proper checks and balances are executed before deploying the project for any changes/incremental changes. However more rigorous quality checks can be implemented by automating the execution of these tests with each build and deployment cycle.

Test Automation

In order to industrialize the entire process of unit testing for it to be running with each deployment/release, it is essential that the test execution step be automated. It is highly desirable that with reach minor/major deployment, and ANT or a MAVEN task can be executed to test the business process and the business rules to produce a release specific test report. The composite test framework provides this capability out-of the box through a ANT file (ant-sca-test.xml in the MW_HOME/Oracle_SOA1/bin directory) and it is very convenient to use. However the problem with it is that it cannot test the business rules. This is a big limitation as far as a total test coverage is concerned.

However overcoming the limitation is easy and explained in the steps that follow. I managed to create a utility framework in Java using the business rules API’s and creating custom ANT tasks to test business rules, once they have been created by following the approach covered above and produce JUnit type reports. The composite test framework can also produce html reports with the test execution statues. However these reports can also be configured to be based on JUnit standards. Hence it makes sense to create all reports that are JUnit based particularly as tools such as Hudson can be configured to point to the report directories and automatically read test report files. It can do the rest in terms of embedding the test report per build/deployment.

  • Right click on the project in studio and create a new Ant build file from the project.
  • This generates two files (build.xml and build.properties) with all the class path and dependencies that the project is base on. This is a good starting point to modify and customize these files to add custom targets and properties execute both the composite and rule tests.

Ant

The customizations to the build.properties file are specific to the middleware installation folder. The property file also needs access to the BPM server to deploy and unit test the composites. A sample property file from my project is copied below.

Configuring build.properties

javac.debug=on

# Environment Homes
WL.HOME=C:/Oracle/PS5JDEV/wlserver_10.3
MW.HOME=C:/Oracle/PS5JDEV
JDEVELOPER.HOME=C:/Oracle/PS5JDEV/jdeveloper

# Output Directories
output.dir=SCA-INF/classes

# SCA Test Parameters
javac.deprecation=off
javac.nowarn=off
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
java.naming.provider.url=t3://rubiconred-pc:7001/soa-infra
java.naming.security.principal=weblogic
java.naming.security.credentials=welcome123
dedicated.connection=true
dedicated.rmicontext=true
scatest.format=junit
scatest.result=./SCA-INF/out/scatests
scatest.timeout=60
scatest.partition=default

The entire build.xml file can be downloaded from here. However the two targets of interest to execute and report the composite tests are scatest and scareport. The scatest Ant target is executed by specifying a bunch of properties that are sourced from the build.properties file. An important parameter is the xsl attribute. This determines the format of the report that is generated. The default property is overwritten with the value of junit to create JUnit type reports.

Creating and Configuring the ANT build/property files

<property name="scatest.tasks.class.path" refid="classpath"/>
<taskdef name="scatest" classname="oracle.integration.platform.testfwk.ant.ScaTestTask" >
<classpath>
<pathelement path="${scatest.tasks.class.path}"/>
</classpath>
</taskdef>

<target name="scatest" description="Run the unit test cases in the Business Process" depends="compile,copy">
<echo message="Classpath = ${classpath}"/>
<echo message="Middleware Home = ${MW.HOME}"/>
<echo message="Running scatest using ORACLE HOME = ${JDEVELOPER.HOME} ${WL.HOME}"></echo>
<echo message="Using context = build.properties"></echo>
<scatest compositedn="${scatest.partition}/${scatest.input}" timeout="${scatest.timeout}"
xsl="${scatest.format}" runname="${scatest.runName}" resultsdir="${scatest.result}" context="${jndi.properties.input}">
</scatest>
</target>

<target name="scareport" description="Generate JUNIT type report for composite Test Suites" depends= "scatest">
<echo message="Generate report to ${scatest.result}"/>
<junitreport todir="${scatest.result}">
<fileset dir="${scatest.result}">
<include name="*.xml" />
</fileset>
<report format="frames" todir="${scatest.result}/html" />
</junitreport>
<exec executable="cmd.exe">
<arg line="/C start ${scatest.result}/html/index.html" />
</exec>
</target>

These targets can, in the most basic way be invoked by right clicking on the build file and selecting Run Ant Target > scareport. The wider possibility in the greater scheme of things is to execute this targets from a build control tool such as Hudson. Now, instead of Ant these targets can even be maven-(ized).

image

The composite test report is currently generated in the SCA-INF/out/scatests directory and automatically launched when running the scatest target. It shows the execution status of each test case and detailed failure report.

image

Integrating the Rule Test Framework

In order to execute the testing of business rules from a continuous integration standpoint, I have developed a Rule test framework which is wrapped over by an Ant command to test as well as generate JUnit based reports. The test framework is generic. A business rule can specify any number of test suite’s. The framework can read any number of test suite XMLs, unit test the business rule component against them and generate a report.The business rules test framework is a set of utility classes that in turn leverages the business rule APIs.

Creating Rule test and report targets

<target name="ruletest" description="Execute unit tests for business rules" depends="compile,copy">
<echo message="Using path = ${classpath}"></echo>
<java classname ="com.rxr.ruletest.RuleTestRunner" classpathref="classpath" logerror="on" failonerror="true" />
</target>

<target name="rulereport" description="Generate JUNIT type report for business Rule Tests">
<echo message="Generate report to ${ruletest.result}"/>
<junitreport todir="${ruletest.result}">
<fileset dir="${ruletest.result}">
<include name="*.xml" />
</fileset>
<report format="frames" todir="${ruletest.result}/html" />
</junitreport>
<exec executable="cmd.exe">
<arg line="/C start ${ruletest.result}/html/index.html" />
</exec>
</target>

The utility classes take care of report generation as well thus allowing robust testing that can be included as part of the build automation.

image

Conclusion

In the end it will be unusual to explain the benefit of establishing automation practices for every component being developed as part of a business process. My colleague, Craig Barr, recently pointed out in his recent blog about SOA and BPM industrialization, the importance of unit testing in a software delivery cycle. Craig mentions:

“Unit test everything! It is a myth that vendor tools don’t cut it when it comes to testing. You just need to know how!”

All files, resources and projects used in this blog can be downloaded from this location. As always I would love to have any feedback so please don’t hesitate provide any suggestions.

.

10 thoughts on “Unit Testing Business Processes in Oracle BPM Suite

  1. Great post!!!

    I am working in a Oracle SOA/BPM/ECM project that our biggest challange is the performance test. We are using the JMeter.

    I belive that this technique can help us too.

    Thanks…

    Like

    • Please note, the test mentioned above are not very useful measure for performance test. They are meaningful only for logic validation and regression testing.

      Like

  2. Nice work!
    In our last project using BPEL and the SOA Suite 11.1.1.6, we faced two challenges with the unit testing framework:
    1. Oracles BPEL unit tests need a complete deployment of the entire composite to the before you can run the unit test. The round trips required for this are very slow for real projects under time constraints.
    2. We found a bug that will cause the whole unit test suite to timeout without giving you any report on why it failed. After analyzing the Weblogic log files, we found the cause to be wire assertions that no longer match any callback message. We filed a SR with Oracle about this.

    Like

  3. Pingback: Functional Testing Business Processes In Oracle BPM Suite 11g | Rubicon Red

  4. Thanks for the blogpost, it was really helpfull for us. We are using the unit test setup for our BPM project but ran into a small limitation of the framework. When you have a process(/SCA) which contains multiple calls to 1 external reference, the whole emulation part is pretty useless since you can’t seem to use some kind of select-critera/filter on the specific response you want for that specific callout.

    kind regards Jan

    Like

    • Hi Jan,

      I completely agree with you. This is a limitation but can be worked out with. Dont you think each call to an external reference should be a different unit test. Well, you may argue that this is pretty redundant but the basis of unit test is to create a uniqute test case. In most cases, a simple cloning of the test case will do, offcourse with the necessary change in the emulation part for the clones test case.

      In the meantime, hoping that the unit testing feature sees a considerable imporovement in the coming releases. If you have any suggestions here, a follow up blog at your website would be great.

      Cheers

      Like

  5. Hi Arun,

    Great Post! However I do have one concern with this methodology.We have a huge code base because of complex functionality.We cannot have so many test cases created and deployed with composite.This will increase the size of the jar.Is there a way to segregate these unit test cases from composite and is part of DEV and TEST environment,i.e the test cases are not part of deployables when deployed on PRE-PRODUCTION and PRODUCTION environment.I tried playing around with the configuration plans but did not help.

    Do you have any ideas on the above.

    Regards,
    Ritu

    Like

    • Hi Ritu,

      There are two things here.

      1. Size of Jar – I dont think how that would be a big problem in Dev and Test environment. A typical worklist project is even bulkier than what could these additional test cases would lead to.

      2. I agree that these test cases should not be part of the production deployment packaging. This can be managed by the way composite jar is bundled. Oracle SOA Suite allows you to specify Contributors and File Groups in deployments.

      Thanks

      Like

  6. Hi Arun,
    I am trying to implement Unit test case automation for my BPM process which includes Business Rules,Human Task,Webservices,other BPM process call.I was going through your blog and I found it very informative.I have downloaded the source code and have imported the jws file to my JDev.I am able to see the process properly but I am getting error while I am trying to build it I am getting some error(sample error mentioned below).

    Error(24,29): package oracle.rules.testfmwk does not exist
    Error(84,19): cannot find class IDFTestCaseResult

    So it’s basically not able to find these files and I checked it doesn’t exist in the source.
    Could you please let me know what mistake I am doing here.

    Like

  7. Pingback: Functional Testing Business Processes In Oracle BPM Suite | Oracle Technologies Primer

If you have any comments, suggestions or feedback about the post, please feel free to type it here and I will do my best to address them asap