> For the complete documentation index, see [llms.txt](https://docs.urbit.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.urbit.org/build-on-urbit/userspace/unit-tests.md).

# Unit Tests

Unit testing framework using -test thread and /lib/test.hoon. Write test arms with +test-\* pattern that return $tang.

## Structure <a href="#structure" id="structure"></a>

The `%base` desk includes a `-test` thread which can run unit tests you've written. A test is a Hoon file which produces a core. The `-test` thread will look for any arms in the core whose name begin with `test-`, e.g:

```hoon
|%
++  test-foo
  ::  ...
++  test-bar
  ::  ...
++  test-foo-bar
  ::  ...
--
```

Any arms that don't begin with `test-` will be ignored. Each `+test-*` arm must produce a `$tang` (a `(list tank)`). If the `$tang` is empty (`~`), it indicates success. If the `$tang` is non-empty, it indicates failure, and the contents of the `$tang` is the error message.

To make test-writing easier, the `%base` desk includes the `/lib/test.hoon` library which you can import into your test file. The library contains the following functions, which all produce `$tang`s:

* `+expect-eq` - test whether an expression produces the expected value. This function takes `[expected=vase actual=vase]`, comparing `.expected` to `.actual`.
* `+expect` - test whether an expression produces `%.y`. This function takes a `$vase` containing the result to check.
* `+expect-fail` - tests whether the given `$trap` crashes, failing if it succeeds.
* `+expect-success` - the converse of `+expect-fail`: tests whether the given `$trap` succeeds, failing if it crashes.
* `+expect-fail-message` - takes `[msg=@t a=(trap)]`. Like `+expect-fail`, but also requires that `.msg` appear in the resulting error message, so you can assert on *why* something failed rather than just that it did.
* `+run-chain` - takes an `$a-test-chain` and runs a sequence of tests, stopping at the first failure. Note that arms in the chain should not begin with `test-`, so that `-test %/... ~` does not also run them individually.
* `+category` - this is a utility that prepends an error message to a failed test (non-null `$tang`), passing through an empty `$tang` (successful test) unchanged.

The most commonly used function is `+expect-eq`, which is used like:

```hoon
++  test-foo
  %+  expect-eq
  !>  'the result I expect'
  !>  (function-i-want-to-test 'some argument')
```

Of course, you'll want to test something else you've written rather than just expressions in the test file itself. To do that, you'd just import the file with `/=` or a similar Ford rune, and then call its functions in the test arms. You're free to do any compositions, import types, etc, as long as the file ultimately produces a `$core` with `+test-*` arms.

## Running <a href="#running" id="running"></a>

The `-test` thread takes a `(list path)` in the Dojo, where each path is a path to a test file. The path *must* include the full path prefix (`/[ship]/[desk]/[case]`). The path *may* omit the mark, since a `.hoon` file is assumed. The path *may* include the name of a test arm after the filename. In that case, only the specified test arm will be run.

The conventional location for tests is a `/tests` directory in the root of a desk.

The output of the `-test` thread will note which arms were tested and whether they succeeded. It will also include:

* The number of micro-seconds it took to execute each test arm.
* A `?` specifying whether all tests succeeded.
* A message confirming the file was built successfully.

Here's an example of running the tests for `/lib/naive.hoon`:

{% code title="Dojo" %}

```
> -test %/tests/lib/naive ~
built   /tests/lib/naive/hoon
>   test-zod-spawn-to-zero: took 81359µs
OK      /lib/naive/test-zod-spawn-to-zero
>   test-zod-spawn-proxy: took 128125µs
OK      /lib/naive/test-zod-spawn-proxy
.............................
....truncated for brevity....
.............................
>   test-approval-for-all: took 647403µs
OK      /lib/naive/test-approval-for-all
>   test-address-padding: took 75104µs
OK      /lib/naive/test-address-padding
ok=%.y
```

{% endcode %}

Here's an example of running just a single test for `/lib/naive.hoon`, the `+test-deposit` arm:

{% code title="Dojo" %}

```
> -test %/tests/lib/naive/test-deposit ~
built   /tests/lib/naive/hoon
>   test-deposit: took ms/45.542
OK      /lib/naive/test-deposit
ok=%.y
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.urbit.org/build-on-urbit/userspace/unit-tests.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
