Defining Custom Assertions - dicksonlaw583/gmassert2 GitHub Wiki
Defining Custom Assertions
Sometimes it is useful to define your own assertions to suit specific testing needs. To do this:
- Define a kernel function that takes 2 arguments (
got
andexpected
), and returns a Boolean value. - (Optional) Define a debug-value function that turns received and/or expected values into a human-readable string.
- Create a developer-facing assertion function that calls
assert_operation()
.
assert_operation()
assert_operation()
takes up to 7 arguments, which can be adjusted to suit the display needs of your custom assertion:
got
: The value received by the assertion.expected
: The reference value to check thegot
value against. Can be stubbed out withundefined
if not used.op
: The ID of a kernel function that takesgot
andexpected
as arguments.invert
:true
for failing whenop(got, expected)
returnsfalse
,false
for failing whenop(got, expected)
returnstrue
.msg
: (Optional) The message to display when the assertion fails. Default:"Assertion Failed!"
debug_got
: (Optional) Can beundefined
or__gma_debug_value__
to display thegot
value in debug format, or a function that takes thegot
value and returns a human-readable string. Default:__gma_debug_value__
debug_expected
: (Optional) Can beundefined
or__gma_debug_value__
to display theexpected
value in debug format, a string explaining what is expected, or a function that takes theexpected
value and returns a human-readable string. Default:__gma_debug_value__
__gma_debug_value__()
Sometimes it is useful to revert to the default debug format for received and/or expected values that are completely unexpected (e.g. undefined
when a data structure ID is expected). For that, you can call the hidden function __gma_debug_value__()
in the debug-value function(s).
Example with only a received value
Objective: You wish to create an assertion to check if a map is empty.
Start with the kernel function __assert_map_empty__
:
///@func __assert_map_empty__(map)
///@arg {Id.DsMap} map The ID of the map to check
///@return {Bool}
///@ignore
function __assert_map_empty__(map) {
return ds_exists(map, ds_type_map) && ds_map_empty(map);
}
Since map IDs are virtually useless on their own, you can create a debug-value function that renders the map in JSON form. You should also handle cases where a completely unwanted value is received or the map ID does not exist:
///@func __debug_map_value__(val)
///@arg {Any} val The value to derive a debug value from
///@return {String}
///@ignore
function __debug_map_value__(val) {
// Can't possibly be a map ID?
if (typeof(val) != "number") {
return __gma_debug_value__(val);
}
// Map doesn't exist?
if (!ds_exists(val, ds_type_map)) {
return "(Map " + string(val) + ")\nDOES NOT EXIST";
}
// Show in JSON form
return "(Map " + string(val) + ")\n" + json_encode(val);
}
Now finish with the main developer-facing assertion function:
///@function assert_map_empty(got, [msg])
///@param {Id.DsMap} got The received value (should be a map ID).
///@param {String} [msg] (optional) The message to display if the assertion fails.
///@desc Assert that the given map is empty.
function assert_map_empty(got, msg="Map doesn't exist or isn't empty!") {
// Run assert_operation (debug_got overridden, debug_expected is a fixed message)
assert_operation(got, undefined, __assert_map_empty__, false, msg, __debug_map_value__, "An empty map");
}
Example with a received and expected value
Objective: You wish to create an assertion to check if a priority queue contains a given value.
Start with the kernel function __assert_pq_exists__
:
///@func __assert_pq_exists__(pq, val)
///@param {Id.DsPriority} pq The priority queue to check
///@param {Any} val The value to look for
///@return {Bool}
function __assert_pq_exists__(pq, val) {
return ds_exists(pq, ds_type_priority) && ds_priority_find_priority(pq, val);
}
Since priority queue IDs are virtually useless on their own, you can create a debug-value function that describes its size, minimum, and maximum values. You should also handle cases where a completely unwanted value is received or the priority queue ID does not exist:
///@func __debug_pq_value__(val)
///@param {Any} val
///@return {String}
///@ignore
function __debug_pq_value__(val) {
// Can't possibly be a priority queue ID?
if (typeof(val) != "number") {
return __gma_debug_value__(val);
}
// Priority queue doesn't exist?
if (!ds_exists(val, ds_type_priority)) {
return "(Priority Queue " + string(val) + ")\nDOES NOT EXIST";
}
// Debug size, lowest, highest
var result = "(Priority Queue " + string(val) + ")\nSize: " + string(ds_priority_size(val));
if (!ds_priority_empty(val)) {
result += "\nMin: " + __gma_debug_value__(ds_priority_find_min(val), true)
+ "\nMax: " + __gma_debug_value__(ds_priority_find_max(val), true);
}
return result;
}
Let's add a quick description before the expected value's debug value as well:
///@func __debug_pq_exists_expected_value__(val)
///@param {Any} val
///@return {String}
///@ignore
function __debug_pq_exists_expected_value__(val) {
return "A priority queue that contains: " + __gma_debug_value__(val);
}
Now finish with the main developer-facing assertion function:
///@func assert_pq_exists(got, val, msg)
///@param {Id.DsPriority} got The actual received value for the assertion
///@param {Any} val The value to look for
///@param {String} msg (optional) A custom message to display when the assertion fails
///@desc Assert that the given priority queue contains a given value.
function assert_pq_exists(got, val, msg="Priority queue is inexistent or doesn't contain the value!") {
// Run assert_operation (expected value provided, debug_got and debug_expected overridden)
assert_operation(got, val, __assert_pq_exists__, false, msg, __debug_pq_value__, __debug_pq_exists_expected_value__);
}