Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Тестування документації

Основний спосіб документування проєкту Rust — це анотування вихідного коду. Коментарі документації пишуться за специфікацією CommonMark Markdown і підтримують у собі блоки коду. Rust дбає про коректність, тож ці блоки коду компілюються і використовуються як тести документації.

/// Перший рядок — це короткий підсумок, який описує функцію.
///
/// Наступні рядки містять докладну документацію. Блоки коду починаються з
/// потрійних зворотних лапок і мають неявний `fn main()` всередині
/// та `extern crate <cratename>`. Припустімо, що ми тестуємо крейт `playground`
/// або використовуємо дію Test у Playground:
///
/// ```
/// let result = playground::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Зазвичай doc-коментарі можуть містити розділи "Examples", "Panics" і "Failures".
///
/// Наступна функція ділить два числа.
///
/// # Examples
///
/// ```
/// let result = playground::div(10, 2);
/// assert_eq!(result, 5);
/// ```
///
/// # Panics
///
/// Функція panic, якщо другий аргумент дорівнює нулю.
///
/// ```rust,should_panic
/// // panic при діленні на нуль
/// playground::div(10, 0);
/// ```
pub fn div(a: i32, b: i32) -> i32 {
    if b == 0 {
        panic!("Divide-by-zero error");
    }

    a / b
}

Блоки коду в документації автоматично тестуються під час запуску звичайної команди cargo test:

$ cargo test
running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests playground

running 3 tests
test src/lib.rs - add (line 7) ... ok
test src/lib.rs - div (line 21) ... ok
test src/lib.rs - div (line 31) ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Мотивація, що стоїть за тестами документації

Основна мета тестів документації — слугувати прикладами, які перевіряють функціональність, що є одним із найважливіших настанов. Це дає змогу використовувати приклади з документації як повноцінні фрагменти коду. Але використання ? призводить до помилки компіляції, оскільки main повертає unit. Тут у пригоді стає можливість приховувати деякі рядки вихідного коду від документації: можна написати fn try_main() -> Result<(), ErrorType>, приховати його і unwrap-нути в прихованому main. Звучить складно? Ось приклад:

/// Використання прихованого `try_main` у doc-тестах.
///
/// ```
/// # // приховані рядки починаються зі символу `#`, але вони все одно компілюються!
/// # fn try_main() -> Result<(), String> { // рядок, що обгортає тіло, показане в doc
/// let res = playground::try_div(10, 2)?;
/// # Ok(()) // повернення з try_main
/// # }
/// # fn main() { // початок main, який буде робити unwrap()
/// #    try_main().unwrap(); // виклик try_main і розгортання
/// #                         // так, щоб тест panic у разі помилки
/// # }
/// ```
pub fn try_div(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err(String::from("Divide-by-zero"))
    } else {
        Ok(a / b)
    }
}

Див. також

  • RFC505 щодо стилю документації
  • API Guidelines щодо настанов з документації