(Classic) Test-Driven Development and KRL
This page described a way to do TDD in the Classic pico-engine. It needs to be updated to work with pico-engine 1.X.
General Setup
The general setup for doing TDD with KRL on SquareTag is as follows:
Create an account for doing the testing.
Ensure it's CloudType is set to developer (See the (Classic) Quickstart for SquareTag for more information)
Install the Kynetx Developer Kit (KDK) and Test Module from the AppStore.
Install any other modules and rulesets necessary for the testing. These generally include the ruleset being tested and the ruleset that contains the tests. (note: more than one ruleset and testing ruleset can be installed in an account.)
Use the KDK to get an ECI for configuring the tests (see Test Harness below)
Tools
There are several tools that make TDD easier with KRL.
Test Module
The test module provides functions, actions, and rules for doing TDD in KRL. The code for the module is located on Github and is registered as ruleset b503129x0
on the Kynetx-hosted instance of KRE.
The module provides the following actions
diag()
- returns a directive withstatus
set to "diagnostic".
The module provides the following rules:
see_success
- selects ontest:succeeds
and returns a directive withstatus
set to "success" along with other information about the result.see_failure
- selects ontest:fails
and returns a directive withstatus
set to "failure" along with other information about the result.
Test Harness
The test harness is a perl program that raises appropriate events to a test account interprets directives from the test module. The code for the test harness is located on Github.
The test harness uses a test configuration file to know what tests to run. The
test config file looks like this:
# cloudos_test@kynetx.com/for_testing
eci: 07E6569E-6CE9-11E3-81D7-05AFD88E7806A
rules_engine: kibdev.kobj.net
rids:
- b16x44
test_1:
desc: "AWS Module Test"
domain: test
type: store_item
attributes:
foo: bar
rids:
- b22342x1.prod
The eci
is a channel to a pico where the test rulesets, the rulesets to be tested, and the test module ruleset have been installed. If no ECI is given, then the event is raised with the Blue event API, otherwise the Sky event API is used.
The rules engine will default to kibdev
if not specified.
The rids
array specifes a RID list for all the tests. Rid specifications in each test can override the general delcaration.
Each test is in a structure with a name that starts with test_
. And structure with a name with that prefix will be run. In this case, there’s just one that raises the event test:store_item. You can add attributes. If a rids
array is present the event will be raised for those rids rather than generally to all installed rulesets.
Writing Tests
Tests look like rulesets. In general, rules in the ruleset can be used to set up the test and check whether or not it succeeded. Here are a few hints for writing rules that act as tests:
Include the Test Module - The test ruleset should use the test module in its meta block. I give it the alias show_test
so that actions I use from it are easy to find.
use module b503129x0 alias show_test
Use the test domain so that test rules only fire during tests - the test
event domain can be used to namespace test events so that test rules don't fire for other reasons.
Include a test_desc variable in the prelude with a description of the test - the value of the variable can be easily included with the test response.
Write the test as a rule condition - the test itself is the rule condition. The prelude can be used to do any calculations necessary to perform the test.
Always use a diagnostic action in the rule - Rule actions don't have alternate. That is, there's no else. Therefore, make the rule action a diagnostic message with as much detail about the intermediate calculations as you find helpful.
Raise test:succeeds and test:fails events in the postlude of the rule - The fired { } else { }
postlude construct can be used to raise a test:succeeds
and test:fails
depending on the result of the test in the rule condition. The see_success
and see_failure
rules in the test module will respond to these events and issue the appropriate directives.
Like any testing exercise, you will find that the testing process goes easier if you write your code with testing in mind and build tests as you go. Sometimes, you will have to build functions, actions, or rules into your code just so that you can test certain features of your ruleset.
Example
The following two rules test the request token response in the Dropbox module. The first rule, get_request_token_test
is selected on test:get_request_token
. The first rule doesn't perform a test, but rather sets it up. The action dropbox:get_request_token
autoraises an http:post
event when the action is performed.
rule get_request_token_test {
select when test get_request_token
pre {
values = {'tokens' : my_tokens,
'header' : dropbox:return_header(my_tokens)
};
}
if(not authorized) then {
dropbox:get_request_token();
show_test:diag("test initiation", values);
}
}
The second rule, process_request_token
, responds to the http:post
event, processes the HTTP response by decoding the content to retrieve the tokens, and tests the tokens to ensure they aren't empty.
Note that this rule raises test:succeeds
or test:fails
events depending on whether the condition is true or not. These events trigger the rules in the test module so that the proper directives are returned to the test harness. At present, the details of raising test:succeeds
or test:fails
events cannot be hidden because the postlude doesn't support any abstraction mechanisms.
The test configuration file to run this test looks like this:
If the Test module, Dropbox module, and Dropbox Test ruleset are installed in the pico pointed to by the ECI in the test configuration file, then running the test harness produces the following output:
The test harness also supports the verbose (v) switch that prints our the success and failure messages:
With the detail (d) switch added to the verbose (v) switch, the detailed logging information is also printed out:
Note that the detail (d) switch combined with the operation of the diagnostic action in the Test module makes it relatively easy to see intermediate values to determine why things may not be working as planned.
Copyright Picolabs | Licensed under Creative Commons.