Developer UI -- Testing tab
How to specify tests in the Testing tab
The tests in the Testing tab are generated by the compiler, based on the code in your ruleset. The information is bound to the name __testing
and that name is always shared by your ruleset. It is then used by the developer UI in the Testing tab.
For example, consider this annotated screenshot of a Testing tab. The pico has four rulesets installed. Only the ruleset whose RID is timing_tracker
has its checkbox checked, so only its tests are showing. We just clicked on the link "__testing" so the Results area is showing the __testing
map itself.
Notice that this ruleset has defined four tests:
- the query for
__testing
- the query for
entries
- the
timing/started
event with two event attributes, namednumber
andname
- the
timing/finished
event with one event attribute, namednumber
By following the green arrows you can see which part of the __testing
map specified each test.
The name __testing
is bound by the compiler to a map with two keys, "queries"
and "events"
, each of which is an array of maps.
Each query map has a key "name"
for the shared name bound to a function or value, and if needed, a key "args"
whose value is an array of argument names for a function.
An event map has keys "domain"
and "name"
for the domain and type of the event, and if needed, a key "attrs"
whose value is an array of attribute names.
Normally, you won't see a query for __testing
, but it will be there if you explicitly share it.
Using the Testing tab to experiment with KRL
When you have a question about KRL, you can often set up a quick experiment, using the Testing tab. For example, let's explore the difference between null
and the empty string (see also the page of KRL misconceptions and common errors).
To begin, we write a test ruleset (named test
), as follows (notice that in this ruleset, we replace completely the __testing
map created by the compiler):
ruleset test { meta { shares __testing, entry } global { __testing = { "queries": [ { "name": "__testing" } , { "name": "entry", "args": [ "key" ] } , { "name": "entry" } ] , "events": [ //{ "domain": "d1", "name": "t1" } //, { "domain": "d2", "name": "t2", "attrs": [ "a1", "a2" ] } ] } truthy = "truthy" falsy = "falsy" entry = function(key){ { "key": key, "key.isnull()": key.isnull(), "key => truthy | falsy": key => truthy | falsy } } } }
The function named entry
is shared (in line 3) and defined in the global block (lines 17-23). It computes a simple map showing the result of three simple computations on the input parameter named key
. First (line 19) is the value as received, second (line 20) whether the value received is null
, (using the general operator isnull()
) and finally (line 21) whether the value received is considered to be true
(and will produce one of these values: "truthy"
if so and "falsy"
otherwise).
In order to feed values into the function, we have instrumented the __testing
map (which is also shared in line 3) with a couple of queries. The first one (line 8) will exercise the entry
function passing it a user-supplied value for the key
parameter. The second (line 9) will invoke the function without providing a value for key
.
Setting up the experiment
We register this ruleset and install it in the root pico. Now, when selecting the Testing tab for the root pico and clicking the box beside our ruleset identifier, we'll see the simple testing mechanism specified by the __testing
map in the test
ruleset:
Invoking the function with an empty string
Without entering anything in the box with "key" as the placeholder, click on the the entry
link to invoke the function. We'll see the results, showing that the value passed in as key
is the empty string, which is not null
, nor is it "truthy":
Invoking the function with a null
Next, click on the second entry
link (which again invokes the function), and see the result, which is that the value passed in is null
(since there wasn't one), which is indeed null
, and also not "truthy":
More experiments
We can try passing different string values into the entry
function, and in all cases we'll see them echoed, that none of them are null
, and that they are all "truthy" (except for the empty string).
Note that the user-supplied values in the __testing
UI will be received as strings, unless JSON.parse()
can convert them into something else, so you can work with other data types (numbers, truth values, maps, arrays, etc.) using the Testing tab. It would be instructive to try entering "0"
(with quotes and without) to see the difference. Zero is falsy but any non-empty string is truthy.
Conclusion
It is very easy to stand up a simple ruleset to check out aspects of KRL which are not clear to you, or for which you cannot find documentation. Once you have learned what you need to know, you can simply discard the ruleset. Share what you have learned with others.
The Testing tab allows you to easily set up the UI needed to run your experiments.
General notes
In keeping with RESTful principles, each event in the Testing tab is represented by a form
using the POST method, while each query are represented by a form
using the GET method.
Copyright Picolabs | Licensed under Creative Commons.