gleedoc

Package VersionHex Docs

A doc test library for Gleam, inspired by Rust and Elixir's doctest tooling.

Doc tests let you write executable examples in your documentation comments (///). These examples are extracted, compiled, and run as part of your test suite, ensuring your documentation never goes out of date.

Disclaimer: This project contains many LLM-generated code, and I used LLMs to do research and design. But I (as a Gleam amateur) have tried my best to review line by line, adjust and refactor.

How it works

  1. Extract/// doc comments from your .gleam source files.
  2. Find fenced code blocks tagged with gleam inside those comments.
  3. Generate test modules in your test/ directory.
  4. Run the generated tests with gleam test.

How other languages do it

Language Approach Key Difference from Gleam
Rustcargo test compiles ```rust blocks from /// comments. No REPL needed. Gleam follows this model closely.
Elixirdoctest Module parses iex> prompts from @doc strings. Elixir has a REPL; Gleam does not.
Pythondoctest parses >>> prompts from docstrings. Python is interpreted; Gleam is compiled.

Because Gleam is a compiled language with no built-in REPL, gleedoc adopts Rust's approach: doc blocks are treated as standalone Gleam code that gets compiled and executed. If a block panics, the test fails.

Installation

gleam add gleedoc --dev

Usage

Write doc comments with gleam code blocks in your source files:

// src/math.gleam

/// Adds two numbers together.
///
/// ```gleam
/// let result = add(1, 2)
/// assert result == 3
/// ```
pub fn add(a: Int, b: Int) -> Int {
  a + b
}

Then run gleedoc to generate tests:

gleam run -m gleedoc

This creates test/gleedoc/math_gleedoc_test.gleam containing:

// Generated by gleedoc - do not edit manually

import math.{add}

// From: src/math.gleam:4
pub fn add_1_test() {
  let result = add(1, 2)
  assert result == 3
}

Now run your tests as usual:

gleam test

API

You can also use gleedoc programmatically from your test suite:

// test/gleedoc_setup.gleam
import gleedoc

pub fn main() {
  let config = gleedoc.GleedocConfig(
    output_dir: "test",
    source_dir: "src",
  )

  case gleedoc.run(config) {
    Ok(Nil) -> Nil
    Error(snag) -> panic as snag.issue
  }
}

Architecture

src/
  gleedoc.gleam           # Main entry point and CLI
  gleedoc/
    extract.gleam         # Line-based doc comment extraction
    parse.gleam           # Markdown code block parsing
    generate.gleam        # Test file generation
    scan.gleam            # Public names and imports extraction with glance

Key dependencies

Package Role
glance Gleam source parser
simplifile Cross-target file I/O
snag Lightweight error handling

Development

rm -rf test/integration/ && gleam test  # Run the test suite

Contributing

Please kindly create an issue in your human voice, describe the feature request or bug clearly with reproduction steps, and ideally with a proposed solution before creating any PR.

Roadmap

Implemented

Missing Features (compared to Rust, Elixir, and Python)

Feature Rust Elixir Python gleedoc
ignore / skip attribute
no_run (compile only)
should_panic
Hidden setup lines (#)
Output assertions (// ->) ✅ (iex>) ✅ (>>>)
Module-level doc tests ✅ (//!)
compile_fail
Multi-target (erlang / javascript) ✅ (cfg)
Incremental / cached generation
Source-mapped error reporting

Know Issues