YS Testing Part 2
Yesterday we talked about writing tests in YS.
We also introduced the ys::taptest
library, but we didn't really cover how it
works.
Let's take a closer look...
The ys::taptest
Library🔗
The ys::taptest
library is a tool for writing tests in YS.
It implements the TAP
protocol, which started as a
test framework for Perl, but has since been adopted by many other languages.
We use Perl's
prove
test runner/harness to run our tests.
One very cool thing about prove
is that it honors the shebang line of the test
file that it is running.
This means that it can be used to run tests for any language as long as the test
files are outputting TAP.
Looking at our test file from yesterday:
#!/usr/bin/env ys-0
use rot-13: :all
use ys::taptest: :all
test::
- code: rot-13('Hello, world!')
want: Uryyb, jbeyq!
- code: rot-13('Uryyb, jbeyq!')
want: Hello, world!
- code: rot-13('I like pie')
want: V yvxr cvr
done: 3
We start with a YS shebang line, which tells prove
to run our tests with YS.
Then we load the library we want to test (the rot-13
library) and the
ys::taptest
library.
In both cases we use the :all
flag that tells use
to export all the
library's public functions.
For rot-13
we export the rot-13
function and for ys::taptest
we export the
test
and done
functions.
The test
function takes a sequence of tests (which are just data) and
evaluates each test in turn, outputting the results as TAP to stdout
.
The done
function tells the harness that we're done running all the tests for
this test file.
This is important because if we have 20 tests and the first 10 pass and then
the program crashes, prove
will know that we didn't run all the tests.
The done
function takes an optional number that needs to be the number of
tests we expected to run.
How a test works🔗
Each test in the sequence is a map that must contain certain keys.
A test can have a name
key that is used to identify the test.
It's a string and it will be printed for that test in the TAP output.
To see all the test names, you can run prove
with the -v
flag.
If you don't provide a name
key, the test will be identified by the code that
is being tested.
Next a test must have either a code
key or a cmnd
key.
A code
key is a string that is YS code that will be evaluated.
A cmnd
key is a string that is a shell command that will be run.
Then a test can have a want
key that is a string that is the expected result
of the test.
For code
tests, the want
value is the expected stringified result of the
evaluated code.
For cmnd
tests, the want
value is the expected stdout of the command.
Want can also be the expected error message of the test.
In that case, the test needs to define a pair of what: error
.
By doing that, the test is declaring that it expects an error to be thrown.
The want
value implies an exact match.
Instead of want
, you can use like: <regex>
to match the result, or you can
use have: <substring>
to supply a substring that must be present in the
result.
Other test keys🔗
Sometimes you just want to concentrate on a single test.
For that you can specify a ONLY: true
pair.
Similarly, if you want to skip a test for now, you can specify a SKIP: true
pair.
See the ys::taptest documentation for more details.