Skip Headers
Oracle® Fusion Middleware User's Guide for Oracle Business Rules
11g Release 1 (11.1.1.7)

Part Number E10228-12
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
PDF · Mobi · ePub

8 Testing Business Rules

This chapter describes how to test rules from Rules Designer of Oracle JDeveloper by using the Rules Test Framework provided by Oracle Business Rules. It also discusses how to test rules and Decision Tables by creating an Oracle Business Rules Function. In addition, it covers at runtime, how to test a SOA Application that uses Oracle Business Rules through a decision service by using Oracle Enterprise Manager Fusion Middleware Control Console.

The chapter includes the following sections:

8.1 Testing Oracle Business Rules at Design Time

Oracle Business Rules provides a test framework that allows you to test rules with complex input parameters. This framework enables you to test rules at the time of designing so that you can validate or refine the rules as per your requirement.

Another way of testing rules is by defining a test function, where you can construct the input, execute rules, and validate the output. Because inputs are constructed and outputs are validated programmatically, test functions are typically used for simple tests, and the test framework is used for comprehensive tests. In addition, this test function is active only for functions that do not take any parameters and only return boolean values.

8.1.1 How to Test Rules Using the Rules Test Framework

Oracle Business Rules provides an 'out-of-the-box' functionality that enables you to test whether the rules you are defining works fine with a given set of inputs at the time of designing. The granularity of testing provided is at the level of decision functions. When you define decision functions in a dictionary, you can define test suites and execute those test suites for each of the decision functions.

Oracle Business Rules supports multiple types of facts, such as Java facts, XML facts, RL facts, and ADFBC facts. The test framework currently only supports XML facts. So, if the decision function, which you have defined, have inputs or outputs referring to non-XML facts, the test framework cannot be used to test the decision function. If you use non-XML facts, a warning or error message is displayed indicating that you cannot use the test feature for that decision function.

To test rules, you need to create a decision function as the prerequisite.

8.1.1.1 Creating a Decision Function

  1. Open Oracle JDeveloper.

  2. From the Application Navigator, open the project file containing the dictionary whose rules you want to test, say BaseDictionary.rules under Business Rules.

  3. In the dictionary section, click Decision Functions to open the list of decision functions.

  4. In the decision functions section, click the Create icon (the plus sign) to display the Edit Decision Function dialog box.

  5. Enter the name of the decision function in the Name field, say TestDF.

  6. In the Input tab, enter the input name under Name and press Enter. In this example, enter songs.

  7. Select the fact type from the Fact Type list. Ensure that you select XML facts. In this example, select Song as the fact type. Similarly, another input variable with the name as artists and fact type as Artist has been added.

  8. Select Tree or List as required. See Section 6.2.1, "How to Add or Edit a Decision Function" for more information on tree or list mode rules.

  9. In the Output tab, enter an output name under Name and press Enter. In this example, enter songs.

  10. Select the fact type from the Fact Type list. Ensure that you select XML facts. In this example, select Song.

  11. Under Rulesets & Decision Functions, select the ruleset that you want to invoke from the Available box, and use the shutter (>) icon to move it to the Selected box. In this example, SongArtistRules has been selected.

    Note:

    This example uses sample schema and corresponding facts.

  12. Click OK to create the decision function. Figure 8-1 displays the Edit Decision Function dialog box.

    Figure 8-1 The Edit Decision Function Dialog

    Description of Figure 8-1 follows
    Description of "Figure 8-1 The Edit Decision Function Dialog"

When you create a decision function, two XML schemas (xsd files) get automatically generated to help in testing the decision function. These schemas have suffixes _TestSuite and _Types respectively. Further, these schemas are stored in an xsd folder under the testsuites folder, which can be seen in the Application Navigator as shown in Figure 8-2.

You need to define the test suites, which are created for the decision function, based on the schema with the suffix _TestSuite.

Figure 8-2 Application Navigator Displaying XSDs

Description of Figure 8-2 follows
Description of "Figure 8-2 Application Navigator Displaying XSDs"

The generated schema files follows the following naming convention:

  • <DictionaryName>_<DecisionFunctionName>_TestSuite.xsd: This file contains the test suite schema for the decision function. Test Suites created for this decision function should conform to this schema. The following is a sample of the TestSuite.xsd file:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://xmlns.oracle.com/rules/test"
    targetNamespace="http://xmlns.oracle.com/rules/test"
    elementFormDefault="qualified" attributeFormDefault="unqualified"
    xmlns:df="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF">
        <annotation>
          <documentation>
              Decision Function Test Suite Schema
          </documentation>
        </annotation>
       <import namespace="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF" 
        schemaLocation="BaseDictionary_BaseDF_Types.xsd"/>
        <element name="testSuite">
            <complexType>
                <sequence>
                    <element name="decisionFunction" type="string" minOccurs="1"    
                     maxOccurs="1"/>
                    <element name="testCase" type="tns:testCaseType" minOccurs="1" 
                     maxOccurs="unbounded"/>
                </sequence>
            </complexType>
        </element>
    
        <complexType name="testCaseType">
            <sequence>
                <element name="testInput" type="df:parameterList" minOccurs="0"   
                  maxOccurs="1"/>
                <element name="expectedOutput" type="df:resultList" minOccurs="0" 
                  maxOccurs="1"/>
            </sequence>
            <attribute name="name" type="string" use="required"/>
        </complexType>
    </schema>
    

    As you can see in the preceding sample, the schema contains a master testSuite element, which in turn contains an element called decisionFunction that defines to which decision function does this test suite corresponds.The testSuite element also contains one or more testCase elements. Each testCase contains a testInput and expectedOutput elements and a name. The testInput values are the ones that are used as inputs to the test cases and expectedOutput values are the ones against which the actual outputs are matched. The types of testInput and expectedOutput (parameterList and resultList respectively) have been defined in the subsequent XSD.

  • <DictionaryName>_<DecisionFunctionName>_Types.xsd: This schema contains two complexTypes elements, parameterList and resultList. These two types are used in the TestSuite schema but are defined here. The parameterList type corresponds to the decision function input and the resultList type corresponds to the decision function output. This is because a decision function has specific inputs and outputs. When you write a test case for a decision function, then the test case input need to correspond to the inputs accepted by the decision function and the expected output need to correspond to the decision function outputs. paramaterList and the resultList are single complexTypes. For example, a decision function requires 10 inputs and 5 outputs, then the parameterList type will be a single ComplexType that collectively defines 10 different elements that need to be provided as the decision function input.

    The following is a sample of the Types.xsd:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    
    <schema xmlns="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
    attributeFormDefault="unqualified" elementFormDefault="qualified"
    xmlns:tns="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:rules="http://xmlns.oracle.com/bpel/rules"
    xmlns:ns1="http://xmlns.oracle.com/rulestest/datamodel">
    <import namespace="http://xmlns.oracle.com/rulestest/datamodel"
    schemaLocation="../../xsd/XMLFactTypes2.xsd"/>
    <import namespace="http://xmlns.oracle.com/bpel/rules"
    schemaLocation="DecisionFunctionPrimitiveTypes.xsd"/>
       <complexType name="parameterList">
          <sequence>
             <element name="tSongElement" type="ns1:tSong"/>
             <element ref="ns1:Artist"/>
          </sequence>
       </complexType>
       <complexType name="resultList">
          <sequence>
             <element name="tSongElement" type="ns1:tSong"/>
          </sequence>
       </complexType>
    </schema>
    

Every time there is an update to the decision function, the corresponding two schemas get updated. For example, if you change the name of the decision function, then the names of the associated schemas are changed. If you delete the decision functions, the corresponding schemas get deleted.Even changes to the inputs and outputs of the decision function results in the associated schemas getting changed. So a decision function and its corresponding test schemas are always in sync.

In case you make any changes to the decision function, for example delete the decision function, typically the schemas get deleted. When you click the Undo icon on the dictionary toolbar, the decision function is retrieved. However, the corresponding schemas remain deleted. You need to manually regenerate the schemas for the decision function in this case. So the sync between the decision function and its corresponding test schemas is not supported in undo and redo operations.

To manually regenerate the schemas:

Click the Generate test suite schemas for all decision functions icon on the dictionary toolbar as shown in Figure 8-3.

Figure 8-3 Manually Regenerating Test Suite Schemas

Surrounding text describes Figure 8-3 .

When you click the icon to regenerate the test suite schemas, a bulk regeneration activity takes place, and all the test suite schemas pertaining to all the available decision functions in the dictionary gets regenerated. If the schemas already exist, those are overwritten.

This activity is particularly used in the following cases:

  • When you have deleted or modified the decision function and have undone the changes: This results in the decision function and the associated schemas getting out of sync. To get them in sync, you use this option so that the schemas are regenerated to correspond to the decision function.

  • When you migrate old dictionaries: Consider a situation when you already have dictionaries from earlier releases with a number of decision functions defined and you want to use the rules testing feature for defining test suites for those decision functions to test them. In this case, either you have to open each decision function in the editor window after migrating, and then click the OK button. This would generate the corresponding test suite schemas. However, this is time-consuming when you have hundreds of decision functions. In this case, you can use the option of regenerating the schemas at one go.

    Note:

    You need to ensure that the migrated decision functions have XML facts as inputs and outputs, else the inputs and outputs defined in the test suite schema files will be empty.

8.1.1.2 Testing the Rules

Once you have created the decision function for testing the rules, you can test rules.

To test rules:

  1. Select the decision function name, say TestDF in this case, in the dictionary page and then click the Test button to display the Decision Function Test dialog box.

  2. Click the Create icon (the plus sign) to display the Create Test Suite dialog box.

  3. Enter the name for the test suite, say TestDFTestSuite1 and click OK as displayed in Figure 8-4.

    Figure 8-4 Creating a Test Suite

    Description of Figure 8-4 follows
    Description of "Figure 8-4 Creating a Test Suite"

  4. Click Close in the Decision Function test dialog box.

    When you create a test suite, a <test suite name>.xml file gets automatically generated and gets stored in the <base dictionary name> folder under the rules folder inside the testsuites folder. You can view the file in the Application Navigator window. For every test suite that you create, a corresponding XML file gets generated.

    However, the newly created test suite file is empty, which does not contain any test case, input definitions, or output definitions.

  5. Open the <test suite name>.XML and write the required test cases that conform to the test suite XSD file, in this case the TestDF XSDs corresponding to the decision function under test.

    The following is a sample test suite file containing test cases:

    <?xml version = '1.0' encoding = 'UTF-8'?>
    <testSuite xmlns="http://xmlns.oracle.com/rules/test"
               xmlns:ns1="http://xmlns.oracle.com/bpel/rules"
               xmlns:ns2="http://xmlns.oracle.com/rules/BaseDictionary/BaseDF"
               xmlns:ns3="http://xmlns.oracle.com/rulestest/datamodel">
       <decisionFunction>G}-733d3b8f:12f76ddad3a:-7c02</decisionFunction>
       <testCase name="TestDFTestSuite1_TestCase1">
           <testInput>
             <ns2:tSongElement>
                <ns3:Title>Come What May</ns3:Title>
                <ns3:Composer>Artist</ns3:Composer>
                <ns3:Length>PT3M2S</ns3:Length>
                <ns3:Year>2010</ns3:Year>
                <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
                </ns3:Artist>
             </ns2:tSongElement>
             <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
             </ns3:Artist>
          </testInput>
          <expectedOutput>
             <ns2:tSongElement>
                <ns3:Title>Come What May</ns3:Title>
                <ns3:Composer>MJ</ns3:Composer>
                <ns3:Publisher>BMG Music</ns3:Publisher>
                <ns3:Length>PT3M2S</ns3:Length>
                <ns3:Year>2010</ns3:Year>
                <ns3:Artist>
                    <ns3:name>MJ</ns3:name>
                    <ns3:age>20</ns3:age>
                    <ns3:recordLabel>BMG Music</ns3:recordLabel>
                </ns3:Artist>         
             </ns2:tSongElement>
          </expectedOutput>  
       </testCase>
    </testSuite>
    
  6. Save the test suite file.

  7. Open the dictionary page, select the decision function name (say TestDF), and click the Test button to display the Decision Function test dialog box.

  8. Select TestDFTestSuite1 from the Test Suite list and click Run Test as shown in Figure 8-5.

    Figure 8-5 Running the Test

    Description of Figure 8-5 follows
    Description of "Figure 8-5 Running the Test"

    This executes all the test cases in the test suite file.

You can see the test details for the decision function in a tabular form.

The details contain the test suite name, the overall result, and the test case details, such as:

  • The test case name

  • The result of the test case

  • The trace info such as which are the facts that were asserted, which are the rules that were activated, which are the rules that were fired and the resultant change in facts.

Figure 8-6 displays the test results.

Figure 8-6 The Results Page

Description of Figure 8-6 follows
Description of "Figure 8-6 The Results Page"

The Comments section in the Results page displays any error details in case a test case fails.

8.1.2 What You Need to Know About Validation of Test Suites

You may have a situation where your test suite XML file does not conform to the test suite XSD file. In that case when you open the Decision Function Test window, in the Test Suite list, adjacent to the test suite name, a yellow warning triangle appears as shown in Figure 8-7.

Figure 8-7 Invalid Test Suite

Description of Figure 8-7 follows
Description of "Figure 8-7 Invalid Test Suite"

If you try to run an erroneous test suite, you will get the following error message:

error message
Description of the illustration rules_test_error.gif

If the test suite XML file is malformed, then the test suite name does not appear in the list of test suites in the Decision Function Test window. In addition, for an invalid dictionary , when you test the Decision Function, the following error message is displayed:

Dictionary is invalid, fix validation errors and try again.

8.1.3 What You Need to Know About Testing Linked Dictionaries

Consider a situation, where you have a base dictionary and a custom dictionary. The custom dictionary has a link to the base dictionary.

Now, navigate to the Decision Functions section of the custom dictionary. Note that the list of decision functions in the custom dictionary includes the decision functions from the linked/base dictionary. You can test the decision functions of the base dictionary from the custom dictionary.

8.1.4 What You Need to Know About Failure of Test Suites

In case your test case fails, the Results page displays the probable reasons of failure in the Comments section.

A test case can fail due to the following reasons:

  • The expected output specified for the test case is different from the actual output as the following:

    unexpected output

    The Comments section clearly states that there is a mismatch between the expected output and the actual output.

  • The test case executes, but no output is generated as the following:

    no output

    You can see that the Comments section displays that the test generated no results and some more details on the probable cause.

  • The test case executes, but multiple outputs are generated as the following:

    multiple outputs

    The Comments section displays that multiple outputs were generated on test execution along with some details on the probable cause.

  • The test case does not fire any rule as the following:

    no rules fired

    This can be because the asserted fact failed to activate any rule resulting in no rules getting fired. So, the Comments section indicates that this may be due to a rule modelling error, because in all probabilities, the provided input failed to match any rule condition.

8.1.5 How to Test a Decision Function Using an Oracle Business Rules Function

You can test rulesets by creating a decision function and calling the decision function from Rules Designer with an Oracle Business Rules function. In the body of the Oracle Business Rules function you create input facts, call a decision function, and validate the facts output from the decision function. For more information, see Section 6.1, "Introduction to Decision Functions" and Section 2.5, "Working with Oracle Business Rules Functions".

To test a decision function using an Oracle Business Rules function:

  1. Confirm that your dictionary is valid.

    For more information on dictionary validation, see Section 4.4.4, "How to Validate a Dictionary"

  2. In Rules Designer, select the Functions navigation tab.

  3. In the Functions area click the Create... icon.

  4. Enter the function name in the Name field, or use the default name.

  5. Select the return type from the Return Type list.

    For a test function, select boolean.

  6. In the Arguments table, confirm that there are no arguments. For a test function, you cannot specify any arguments.

  7. In the Body area, enter the test function body.

    In the body of the test function you can call a decision function using assign new to call and get the return value of the decision function (in the body of the test function you create input facts, call a decision function, and validate the facts output from the decision function).

    A decision function call returns a List. Thus, to test a decision function in a test function you do the following:

    • You create the input data as required for the decision function input arguments.

    • You call the decision function with the arguments you create in the test function.

    • You place results in a List, for example, in the following:

      assign new List resultsList = DecisionFunction_1(testScore)
      

    Figure 8-8 shows a test function that calls a decision function.

    Figure 8-8 Test Function to Call a Decision Function that Returns a List

    Description of Figure 8-8 follows
    Description of "Figure 8-8 Test Function to Call a Decision Function that Returns a List"

  8. Select the function and click the Test Function icon.

    The function is executed. The output is shown in a Function Test Result dialog, as Figure 8-9 shows.

    Figure 8-9 Test Function Results for Grade Test

    Description of Figure 8-9 follows
    Description of "Figure 8-9 Test Function Results for Grade Test"

  9. Click OK to dismiss the Function Test Result dialog.

8.1.6 What You Need to Know About Testing Decision Functions

You can use Oracle Business Rules Functions to test decision functions from within Rules Designer. Keep the following points in mind when using a test function:

  • The Test Function icon is gray if the dictionary associated with the test Oracle Business Rules Function contains any validation warnings. The Test Function icon is only shown when the dictionary validates without warnings.

  • To enable logging you can call RL.watch.all(). For more information on RL Language functions, see Oracle Fusion Middleware Language Reference Guide for Oracle Business Rules. In this guide, RL.watch.all() is an alias for the RL Language function watchAll().

  • As an alternative to the example shown in Figure 8-8, you can enter the function body that is shown in Example 8-1. This function runs and shows the RL.watch.all() output. The dialog shows "Test Passed" when the grade is in the B range as shown in Figure 8-10. The dialog shows "Test Failed" when the grade asserted is not in the B range, as shown in Figure 8-11.

    Example 8-1 Function Body with True or False Return Value

    call RL.watch.all()
    assign new TestScore testScore = new TestScore()
    modify (testScore, name: "Bill Reynolds", testName: "Math Test", testScore: 81)
    assign new TestGrade testGrade = (TestGrade)DecisionFunction_1(testScore).get(0)
    return testGrade.grade == Grade.B
    

    For the testScore value 81, this function returns "Test Passed" as shown in Figure 8-10. For the testScore value 91, this returns "Test Failed", as shown in Figure 8-11.

    Figure 8-10 Test Passed Test Function Output

    Description of Figure 8-10 follows
    Description of "Figure 8-10 Test Passed Test Function Output"

    Figure 8-11 Test Failed Test Function Output

    Description of Figure 8-11 follows
    Description of "Figure 8-11 Test Failed Test Function Output"

8.2 Testing Oracle Business Rules at Runtime

In a SOA application that uses Oracle Business Rules with a Decision Service you can test rules at runtime with Oracle Enterprise Manager Fusion Middleware Control Console Test function.

For more information on using the Test function, see Oracle Fusion Middleware Administrator's Guide for Oracle SOA Suite and Oracle Business Process Management Suite.