Skip to content

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 External link 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.

Comments