Yeda AI Tips · #088

English

Haz tus docs ejecutables: doc tests

¿Y si la documentación incorrecta rompiera tu build? Los docs se pudren: el ejemplo de tu README se aleja del API real y nadie lo nota hasta que un usuario lo copia y abre un bug report confundido. Los doc tests invierten el incentivo: los ejemplos de tus comentarios y de tu README se compilan y se ejecutan como parte de la suite de tests, así que la documentación obsoleta rompe el CI en lugar de fallarle a tus usuarios. Tus docs no pueden mentir, porque tienen que ejecutarse.

Cómo funcionan los doc tests de Rust

Cada bloque de código dentro de un comentario de documentación /// es un test. cargo test los ejecuta junto con tus tests unitarios; cargo test --doc ejecuta solo los doc tests.

/// Adds two numbers.
///
/// ```
/// let sum = mycrate::add(2, 3);
/// assert_eq!(sum, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 { a + b }

Rustdoc preprocesa cada bloque para que los ejemplos cortos sigan siendo cortos: envuelve el código en fn main() si no lo escribiste e inyecta extern crate mycrate; por ti. Renombra add más tarde y este bloque deja de compilar — el build se pone en rojo antes de que los docs queden mal.

Las líneas que empiezan con # se compilan pero no se muestran, así el lector ve 2 líneas de señal mientras el compilador ve toda la preparación:

/// ```
/// # fn setup() -> mycrate::Client { mycrate::Client::new() }
/// let client = setup();
/// client.ping();
/// ```

No todos los ejemplos deben ejecutarse igual

Algunos ejemplos tocan la red, otros están rotos a propósito, otros deben fallar. Rustdoc le da a cada bloque un atributo en lugar de una excusa:

AtributoQué haceCuándo usarlo
(ninguno)Compila y ejecutaEl default — prefiérelo
no_runCompila, no ejecutaLlamadas de red, efectos secundarios
should_panicDebe hacer panic para pasarDocumentar modos de falla
compile_failDebe fallar al compilarMostrar lo que el sistema de tipos rechaza
ignoreSe omite por completoÚltimo recurso — no prueba nada

compile_fail es el subestimado: te permite documentar "este mal uso no compila" y que el CI verifique que ese mal uso sigue sin compilar.

Testea también el README

El README es el doc que se desactualiza más rápido, porque vive fuera de la vista del compilador. Tráelo adentro:

#[doc = include_str!("../README.md")]
#[cfg(doctest)]
pub struct ReadmeDoctests;

Cada bloque de código Rust de tu README ahora es un doc test. La condición #[cfg(doctest)] mantiene el struct fuera de tu API pública y de los docs renderizados.

La misma idea fuera de Rust

El principio no depende del lenguaje — los ejemplos ejecutables son décadas anteriores a Rust:

Movidas de usuario avanzado

Recursos

¿Construyendo una funcionalidad con IA? Yeda AI diseña, audita y lleva a producción sistemas LLM.

Habla con nosotros · Lee el blog · Read in English