-
Notifications
You must be signed in to change notification settings - Fork 10
Assertions
Assertions within qspec all take the form of “must*”. This is for two reasons: it reads well and names that follow the “must*” pattern are unlikely to conflict with any variables in a given project.
The majority of the standard assertions provided match existing q operators. We will only briefly cover those here
The basic assertion is simply must
. It takes two arguments, a boolean atom or boolean list and a character list describing what condition should be fulfilled. For the assertions provided, this usually takes the form of “Expected such and such a thing”.
mustdelta
takes three arguments: a tolerance, an actual value, and an expected value. If the actual value is not within the tolerance from the expected value, the test failes. The test is implemented with the following code:
{[tol;l;r] l within (r - abs tol;r + abs tol)}
mustthrow
takes two arguments. The first argument is an empty list, a character list of the error that is expected to be thrown (such as “type”), or a list of character lists of the errors that could be thrown. The second argument is a function or function literal taking one argument, a list whose first element is a function and the remaining elements are the arguments to the function, or a string to evaluate. If no error is thrown, or the error thrown does not match one of the provided errors, the assertions fails.
mustnotthrow
takes two arguments. The first argument is an empty list, a character list of the error that is expected to be thrown (such as “type”), or a list of character lists of the errors that could be thrown. The second argument is a function or function literal taking one argument, a list whose first element is a function and the remaining elements are the arguments to the function, or a string to evaluate. If an error is thrown, or the error thrown matches one of the provided errors, the assertion fails.
For these assertions, the string returned in case of failure works best when the value under test is given as the left hand operator, and the expected value is on the right hand side.
Name | Corresponding Operator | Example | Example Failure Output |
musteq |
= |
x musteq y |
Expected x to be equal t y |
mustne |
not = |
x mustne y |
Expected x to not be equal t y |
mustmatch |
~ |
x mustmatch y |
Expected x to match y |
mustnmatch |
not ~ |
x mustnmatch y |
Expected x to not match y |
mustlt |
< |
x mustlt y |
Expected x to be less than y |
mustgt |
> |
x mustgt y |
Expected x to be greater than y |
mustlike |
like |
x mustlike y |
Expected x to be like y |
mustin |
in |
x mustin y |
Expected x to be in y |
mustnin |
not in |
x mustnin y |
Expected x to not be in y |
mustwithin |
within |
x mustwithin y |
Expected x to be within y |
Adding a custom assertion is very easy. Create a function that performs a test on a provided value. The function should call .tst.asserts.must
with the result of the test as the first argument and a descriptive explanation of the test as the second argument. Remember to string representations of any values passed in as part of the message.
Then, simply add an entry to the dictionary .tst.asserts
with your new assertions before your tests are loaded (this is important as a special step is used to make sure the names resolve properly). Your methods will then be added into the .q
namespace when your tests are run (and only when your tests are run) so you will be able to use them within your tests as you would any other in-fix function.