Testing Your Rules as Code
One of the major advantages of Rules as Code is the opportunity to test your encoded rules against fact scenarios.
The fine people at the Service Innovation Lab in New Zealand have created a GitHub repository for demonstrating different technological approaches to Rules as Code. This post details the Blawx implementation of those rules, and demonstrates how to do testing of your encoded rules in Blawx.
The rules being encoded are very simple:
In this Act, beard means any facial hair no shorter than 5 millimetres in length that: a. occurs on or below the chin, or b. exists in an uninterrupted line from the front of one ear to the front of the other ear below the nose.
As always, the first step in encoding rules in Blawx is to set out the ontology that you will be working with. Here, the Ontology is very simple. We have one category, “Person”, with four attributes indicating whether they have a beard, the length in millimeters of their facial hair, whether it is below the chin, and whether it goes from ear to ear uninterrupted under the nose.
Then, we are able to encode the rules. Note how similar the encoding of the rule is to the way the rule is written above:
For the purposes of this experiment, we want to be able to determine when a person is not bearded, too. So we can make a rule saying that if we can’t prove they are bearded, then they aren’t.
That’s all the code required for the rules!
Testing the Rules
The example rules as code repository sets out a set of 10 fact scenarios in JSON and other formats. Blawx will accept JSON input over it’s API, but I wanted this demo to be more visual and interactive, and let people see the data inside the Workspace. So I used Blawx’s data features to recreate the data inside the code. The first couple of tests (there are 10), look like this:
Now, whenever you are dealing with a Blawx encoding of a set of rules, and then data from some other source, you need to write code that puts the outside data into the ontology that you used to create the rules.
But beyond people, we want to be able to talk about test cases, about the expected result of those test cases, and about whether those tests passed. So we need to create a new ontology in Blawx for tests that looks like this:
Now we can talk about test objects in our rules and queries. Note that we have said that a Test is a Person, so that rules that refer to Person will still work if the object is in the category Test.
Importantly, the test data from the example repository includes some tests in which certain pieces of information are missing. We are going to assume that every test comes with an ID, to make it distinguishable inside Blawx, and also that every test comes with an expected result.
The other three values, the length of the facial hair, whether it is on the chin, and whether it goes from ear to ear under the nose, may or may not exist for any given test. So we will have one rule that will create test objects from data, and three more rules to add the individual values to those objects if they exist. Here’s the main rule for creating a test case.
Here we are using some advanced features of Blawx that are required for creating objects with unique names when using test data.
Once the object exists, we can add values to its properties if those properties are set out in the data, using rules like this:
Once we have those rules for all of the different values in the data, we have transferred the external data to the ontology of the rules, and the ontology we have created for testing.
Now we need to write a rule for what constitutes a “passed” test. We will say that a Test object has a passed value of true if the bearded value and the expected value are the same.
Now, because we want to get results for tests that do not pass, we need to calculate which tests failed, and set the same value to false. We could use a rule that says if it didn’t pass it failed. But for variety, we can do it by saying a test fails if it has a calculated value and a expected value that are not the same.
You’ll notice this rule is one block longer than the “passed” rule, because in the “passed” rule we were able to say that both values were equal to the same variable, which eliminated the need to check for equality of the value. Here, we are dealing with two variables that may or may not be identical, and we want to filter for only the non-identical variables, so we can’t use the same approach.
Running the Tests
That’s it for the code. Now we just need to run the tests by asking Blawx to determine whether or not each test object passed. We do that with the following query:
And if you “Run Blawx Code,” you get the following feedback:
The answer is: Yes test: test(1), passed: true test: test(2), passed: true test: test(3), passed: true test: test(4), passed: true test: test(5), passed: true test: test(6), passed: true test: test(7), passed: true test: test(8), passed: true test: test(9), passed: true test: test(10), passed: true
The “passed” value for all the tests is “true”, meaning that the code gave the expected result.