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.