Rust by Example — страница 63 из 66

#[should_panic(expected = "Divide result is zero")]

fn test_specific_panic() {

divide_non_zero_result(1, 10);

}

}

Running these tests gives us:

$ cargo test


running 3 tests

test tests::test_any_panic ... ok

test tests::test_divide ... ok

test tests::test_specific_panic ... ok


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


Doc-tests tmp-test-should-panic


running 0 tests


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

Running specific tests

To run specific tests one may specify the test name to cargo test command.

$ cargo test test_any_panic

running 1 test

test tests::test_any_panic ... ok


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


Doc-tests tmp-test-should-panic


running 0 tests


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

To run multiple tests one may specify part of a test name that matches all the tests that should be run.

$ cargo test panic

running 2 tests

test tests::test_any_panic ... ok

test tests::test_specific_panic ... ok


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


Doc-tests tmp-test-should-panic


running 0 tests


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

Ignoring tests

Tests can be marked with the #[ignore] attribute to exclude some tests. Or to run them with command cargo test -- --ignored


#![allow(unused)]

fn main() {

pub fn add(a: i32, b: i32) -> i32 {

a + b

}


#[cfg(test)]

mod tests {

use super::*;


#[test]

fn test_add() {

assert_eq!(add(2, 2), 4);

}


#[test]

fn test_add_hundred() {

assert_eq!(add(100, 2), 102);

assert_eq!(add(2, 100), 102);

}


#[test]

#[ignore]

fn ignored_test() {

assert_eq!(add(0, 0), 0);

}

}

}

$ cargo test

running 3 tests

test tests::ignored_test ... ignored

test tests::test_add ... ok

test tests::test_add_hundred ... ok


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


Doc-tests tmp-ignore


running 0 tests


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


$ cargo test -- --ignored

running 1 test

test tests::ignored_test ... ok


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


Doc-tests tmp-ignore


running 0 tests


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

Documentation testing

The primary way of documenting a Rust project is through annotating the source code. Documentation comments are written in markdown and support code blocks in them. Rust takes care about correctness, so these code blocks are compiled and used as tests.

/// First line is a short summary describing function.

///

/// The next lines present detailed documentation. Code blocks start with

/// triple backquotes and have implicit `fn main()` inside

/// and `extern crate `. Assume we're testing `doccomments` crate:

///

/// ```

/// let result = doccomments::add(2, 3);

/// assert_eq!(result, 5);

/// ```

pub fn add(a: i32, b: i32) -> i32 {

a + b

}


/// Usually doc comments may include sections "Examples", "Panics" and "Failures".

///

/// The next function divides two numbers.

///

/// # Examples

///

/// ```

/// let result = doccomments::div(10, 2);

/// assert_eq!(result, 5);

/// ```

///

/// # Panics

///

/// The function panics if the second argument is zero.

///

/// ```rust,should_panic

/// // panics on division by zero

/// doccomments::div(10, 0);

/// ```

pub fn div(a: i32, b: i32) -> i32 {

if b == 0 {

panic!("Divide-by-zero error");

}


a / b

}

Tests can be run with cargo test:

$ cargo test

running 0 tests


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


Doc-tests doccomments


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

Motivation behind documentation tests

The main purpose of documentation tests is to serve as examples that exercise the functionality, which is one of the most important guidelines. It allows using examples from docs as complete code snippets. But using ? makes compilation fail since main returns unit. The ability to hide some source lines from documentation comes to the rescue: one may write fn try_main() -> Result<(), ErrorType>, hide it and unwrap it in hidden main. Sounds complicated? Here's an example:

/// Using hidden `try_main` in doc tests.

///

/// ```