Skip to content

Testing

tim-hardcastle edited this page Jun 5, 2026 · 2 revisions

Pipefish has a couple of features for making testing ergonomic.

Test blocks

A test block is a control structure. Here we demonstrate it in the REPL.

image

It returns OK or an error, and so is imperative code: it can be used in the REPL, or in commands.

The point of it being a control structure is that it can be embedded in other imperative code. (This code and the remainder below can be found in the examples/wiki/testing.pf folder of the Pipefish distribution.)

image

The example about shows it embedded in an ordinary command, but it is useful to put them in test commands, which we discuss next.

Test commands

A test command is a normal command which has test as the first word of its name and which has no parameters. They don't have to contain test blocks, being ordinary commands, but it's what they're for.

The use of them is that the built-in command test will call all of the test commands in the module. (Hence if we import foo, then foo.test will test all the modules in foo.) Tests can be put anywhere you like in the module, without affecting or being affected by headwords.

image

While actively working on a module, you might want to keep the relevant tests near the code you're working on, moving them to another file altogether when the code becomes stable.

Recall that in Pipefish, like Go, each module can have a parameterless init command which is executed immediately on compilation of the module. So during active development you might want to put calls to test commands, or to test, at the end of a module's init command to run all the tests you think relevant.

Tests are run in order of declaration (unless you make dependencies between them that would make this impossible). You could for example have the first test command set up state and the last one tear it down; or temporarily move a test to the top to ensure it runs first, while you work on the bit of code it tests.

🧿 Pipefish

Clone this wiki locally