9 min read

When we start writing ‘real’ business rules, there is very little space to make mistakes as the mistakes made can cause a lot of wastage of money. How much money would a company lose if a rule that you wrote gave double the intended discount to a customer? Or, what if your airline ticket pricing rule started giving away first class transatlantic flights for one cent?

Of course, mistakes happen. This article makes sure that these costly mistakes don’t happen to you. If you’re going through the trouble of writing business rules, you will want to make sure that they do what you intend them to, and keep on doing what you intend, even when you or other people make changes, both now and in the future. But first of all, we will see how testing is not a standalone activity, but part of an ongoing cycle.

Testing when building rules

It’s a slightly morbid thought, but there’s every chance that some of the business rules that you write will last longer than you do. Remember the millennium bug caused by programmers in the 1960’s, assuming that nobody would be using their work in 40 years’ time, and then being surprised when the year 2000 actually came along?

Rather than ‘play and throw away’, we’re more likely to create production business rules in the following cycle:

  1. Write your rules (or modify an existing one) based on a specification, or feedback from end users.
  2. Test your rules to make sure that your new rules do what you want them to do, and ensure that you haven’t inadvertently broken any existing rules.
  3. Deploy your rules to somewhere other than your local machine, where end users (perhaps via a web page or an enterprise system) can interact with them.

You can repeat steps 1, 2, and 3 as often as required. That means, repeat as many times as it takes you to get the first version into production. Or, deploy now and modify it anytime later –in 1, 2, or 10 years time.

Making testing interesting

Normal testing, where you inspect everything manually, is booooooooring! You might check everything the first time, but after the hundredth deployment you’ll be tempted to skip your tests—and you’ll probably get away with it without any problems. You’ll then be tempted to skip your tests on the 101st deployment—still no problems. So, not testing becomes a bad habit either because you’re bored, or because your boss fails to see the value of the tests.

The problem, then comes one Friday afternoon, or just when you’re about to go on vacation, or some other worst possible time. The whole world will see any mistakes in the rules that are in production. Therefore, fixing them is a lot more time and money consuming than if you catch the error at the very start on your own PC.

What’s the solution? Automate the testing. All of your manual checks are very repetitive—exactly the sort of thing that computers are good at. The sort of checks for our chocolate shipment example would be ‘every time we have an order of 2000 candy bars, we should have 10 shipments of 210 bars and one shipment of 110 bars’.

Testing using Guvnor

There is one very important  advantage of testing—we can instantly see whether our tests are correct, without having to wait for our rules to be deployed into the target system.

At a high level, Guvnor has two main screens that deal with testing:

  • An individual test screen: Here you can edit your test by specifying the values that you want to input, and the values that you expect once your rules have fired
  • A package or multiple tests screen (below): This allows you to run (later on) all of the tests in your package, to catch any rules that you may have inadvertently broken

Another way of saying this is: You write your tests for selfish reasons because you need them to ensure that your rules do what you want them to do. By keeping your tests for later, they automatically become a free safety net that catches bugs as soon as you make a change.

JBoss Drools Business Rules

Testing using FIT

Guvnor testing is great. But, often, a lot of what you are testing for is already specified in the requirements documents for the system. With a bit of thought in specifying various scenarios in your requirements documents, FIT allows you to automatically compare these requirements against your rules. These requirements documents can be written in Microsoft Word, or similar format, and they will highlight if the outputs aren’t what is specified. Like Drools, FIT is an open source project, so there is no charge for either using it, or for customizing it to fit your needs.

Before you get too excited about this, your requirements documents do have some compromises. The tests must specify the values to be input to the rules, and the expected result—similar to the examples, or scenarios, that many specifications already contain. These scenarios have to follow a FIT-specific format. Specification documents should follow a standard format anyway—the FIT scenario piece is often less than 10% of it, and it is still highly human-readable! Even better, the document can be written in anything that generates HTML, which includes Microsoft Word, Excel, OpenOffice, Google documents, and most of the myriad of editors that are available today.

Like the Guvnor testing, we can use FIT to test whether our individual requirements are being met when writing our rules. It is possible to run FIT automatically over multiple requirement documents to ensure that nothing has ‘accidentally’ broken as we update other rules.

Getting FIT

When you download the samples, you will probably notice three strange packages and folders.

  • fit-testcase: This folder resides just within the main project folder, and contains the FIT requirements documents that we’re going to test against.
  • chap7: This is a folder under src/main/java/net/firstpartners, and contains the startpoint (FitRulesExample.java) that we’ll use to kick-start our FIT Tests.
  • FIT: This folder is next to the chap7 folder. It folder contains some of the ‘magic plumbing’ that makes FIT work. Most business users won’t care how this works (you probably won’t need to change what you find here), but we will take a look at it in more detail in case we want to customize exactly how FIT works.

If you built the previous example using Maven, then all of the required FIT software will have been downloaded for you. (Isn’t Maven great?) So, we’re ready to go.

The FIT requirements document

Open the word document fit-testcase.doc using Word, or OpenOffice. Remember that it’s in the fit-testcase folder. fit-testcase.doc is a normal document, without any hidden code. The testing magic lies in the way the document is laid out. More specifically, it’s in the tables that you see in the document. All of the other text is optional. Let’s go through it.

Logo and the first paragraph

At the very top of the document is the Drools logo and a reference to where you can download FIT for rules code. It’s also worth reading the text here, as it’s another explanation of what the FIT project does and how it works.

JBoss Drools Business Rules

None of this text matters, or rather FIT ignores it as it contains no tables. We can safely replace this (or any other text in this document that isn’t in the table) with your company logo, or whatever you normally put at the top of your requirement documents.

FIT is a GPL (General Public License) open source software. This means you can modify it (as long as you publish your changes). In this sample we’ve modified it to accept global variables passed into the rules. (We will use this feature in step 3.)
The changes are published in the FIT plumbing directory, which is a part of the sample. Feel free to use it in your own projects.

First step—setup

The setup table prepares the ground for our test, and explains the objects that we want to use in our test. These objects are familiar as they are the Java facts that we’ve used in our rules. There’s a bit of text (worth reading as it also explains what the table does), but FIT ignores it. The bit that it reads is given in the following table:

net.firstpartners.fit.fixture.Setup

net.firstpartners.chap6.domain.CustomerOrder

AcmeOrder

net.firstpartners.chap6.domain.OoompaLoompaDate

nextAvailableShipmentDate

If you’re wondering what this does, try the following explanation in the same table format:

Use the piece of plumbing called ‘Setup’

 

Create CustomerOrder and call it

AcmeOrder

Create OoompaLoompaDate and call it

nextAvailableShipmentDate

There is nothing here that we haven’t seen before. Note that we will be passing nextShipmentDate as a global so that it matches the global of a same name in our rules file (the match includes the exact spelling, and the same lower-and uppercase).

Second step—values in

The second part also has the usual text explanation (ignored by FIT) and table (the important bit), which explains how to set the values.

net.firstpartners.fit.fixture.Populate

AcmeOrder

Set initial balance

2000

AcmeOrder

Set current balance

2000

It’s a little bit clearer than the first table, but we’ll explain it again anyway.

Use the piece of plumbing called Populate

AcmeOrder

Take the … we created earlier, and set it to have an initial balance of …

2000

AcmeOrder

Take the … we created earlier, and set it to have a current balance of …

2000

Third step—click on the Go button

Our next part starts the rules. Or rather, the table tells FIT to invoke the rules. The rest of the text (which is useful to explain what is going on to us humans) gets ignored.

net.firstpartners.fit.fixture.Engine

Ruleset

src/main/java/net/firstpartners/chap6/shipping-rules.drl

Assert

AcmeOrder

Global

nextAvailableShipmentDate

Execute

 

The following table is the same again, in English:

Use the piece of plumbing called ‘Engine’

Ruleset

Use the rules in shipping-rules.drl

Assert

Pass our AcmeOrder to the rule engine (as a fact)

Global

Pass our nextAvailableShipmentDate to the rule engine (as a global)

Execute

Click on the Go Button

LEAVE A REPLY

Please enter your comment!
Please enter your name here