# Testing

> Write and run tests in Langoost — test_ functions in _test.goost files, the assert module (eq, ne, ok, throws), and the langoost test runner.

# Testing

Langoost has a built-in test runner and an `assert` module — no external
framework needed.

## Writing tests

Put tests in files named `*_test.goost`. Each top-level function whose name
starts with `test_` is a test. A test **passes** if it returns normally and
**fails** if it throws — and the `assert` helpers throw on failure.

```goost
// math_test.goost
import assert

fn add(a, b) { return a + b }

fn test_add() {
    assert.eq(add(2, 2), 4)
}

fn test_add_negative() {
    assert.eq(add(-1, -1), -2, "negatives should add")
}

fn test_throws_on_bad_index() {
    assert.throws(fn() {
        let xs = [1, 2, 3]
        return xs[99]            // out of bounds → throws
    })
}
```

## The assert module

```goost
import assert
```

| Function | Signature | Description |
| --- | --- | --- |
| `ok` | `assert.ok(value [, msg])` | Fail if `value` is falsy |
| `eq` | `assert.eq(actual, expected [, msg])` | Fail unless equal (uses the VM's `==` semantics) |
| `ne` | `assert.ne(actual, expected [, msg])` | Fail if equal (the inverse of `eq`) |
| `throws` | `assert.throws(fn [, msg])` | Run `fn()` and fail unless it throws |

The optional `msg` is included in the failure output.

## Running tests

```
$ langoost test                      # discover *_test.goost under .
$ langoost test ./tests -v           # verbose: list every test
$ langoost test -run add             # only tests whose name contains "add"
```

The runner reports each pass/fail and exits non-zero if any test fails — so it
drops straight into CI:

```
math_test.goost
  ok    test_add
  ok    test_add_negative
  FAIL  test_throws_on_bad_index

2 passed, 1 failed
```

See the **[CLI reference](/docs/cli#test)** for all flags.