How to use inline documentation for tests in rust
Asked Answered
C

2

5

I am trying to get rust to test an example from my inline documentation. I wrote the following code:

#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
enum Color {
    Black = 1,
    Empty = 0,
    White = -1
}
/// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// assert_eq!(flip(&Color::White),Color::Black);
///```

// Invariant Color must represent Black as 1, Empty as 0 and White as -1!
fn flip(player: &Color)->Color{
    let intrepresentation :i8 = (player.clone() as i8) * (-1);
    unsafe{
        std::mem::transmute(intrepresentation)
    }
}
fn  main() {
    assert_eq!(flip(&Color::White),Color::Black);
}
  

Then I run

rustdoc --test src/main.rs 

Which gave me:

running 1 test
test src/main.rs - flip (line 16) ... FAILED

failures:

---- src/main.rs - flip (line 16) stdout ----
error[E0433]: failed to resolve: use of undeclared type or module `Color`
 --> src/main.rs:17:18
  |
3 | assert_eq!(flip(&Color::White),Color::Black);
  |                  ^^^^^ use of undeclared type or module `Color`

error[E0433]: failed to resolve: use of undeclared type or module `Color`
 --> src/main.rs:17:32
  |
3 | assert_eq!(flip(&Color::White),Color::Black);
  |                                ^^^^^ use of undeclared type or module `Color`

error[E0425]: cannot find function `flip` in this scope
 --> src/main.rs:17:12
  |
3 | assert_eq!(flip(&Color::White),Color::Black);
  |            ^^^^ not found in this scope

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0425, E0433.
For more information about an error, try `rustc --explain E0425`.
Couldn't compile the test.

failures:
    src/main.rs - flip (line 16)

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

How can I get rustc to find flip and Color. The test runs fine in the main function. I have also tried the command:

cargo test

but that did not run any tests.

I have tried add the following line to the example:

   /// use crate::{flip, Color};

making:

// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// use crate::{flip, Color};
/// assert_eq!(flip(&Color::White),Color::Black);
///``` 

but that gives an error

martin@martin-laptop:~/test_code$ rustdoc --test src/main.rs 

running 1 test
test src/main.rs - main (line 23) ... FAILED

failures:

---- src/main.rs - main (line 23) stdout ----
error[E0432]: unresolved import `crate::Color`
 --> src/main.rs:24:14
  |
3 | use crate::{ Color};
  |              ^^^^^ no `Color` in the root

error[E0425]: cannot find function `flip` in this scope
 --> src/main.rs:25:12
  |
4 | assert_eq!(flip(&Color::White),Color::Black);
  |            ^^^^ not found in this scope

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0425, E0432.
For more information about an error, try `rustc --explain E0425`.
Couldn't compile the test.

failures:
    src/main.rs - main (line 23)

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

I have also tried to Color and flip as public:

#[derive(Clone)]
#[derive(PartialEq)]
#[derive(Debug)]
pub enum Color {
    Black = 1,
    Empty = 0,
    White = -1
}

/// Chages Color to the next player
///
/// Returns: White if player is Black, Black if player is White and Empty if
/// player is Empty.
///
/// Examlple
/// ```
/// use crate::{flip, Color};
/// use std::env;
/// assert_eq!(flip(&Color::White),Color::Black);
///```

// Invariant Color must represent Black as 1, Empty as 0 and White as -1!

pub fn flip(player: &Color)->Color{
    let intrepresentation :i8 = (player.clone() as i8) * (-1);
    unsafe{
        std::mem::transmute(intrepresentation)
    }
}
fn  main() {
    assert_eq!(flip(&Color::White),Color::Black);
}

but that gave the same error.

Camarena answered 12/11, 2020 at 3:12 Comment(5)
why don't you add use lines ? use crate::{flip, Color};Heat
What are use lines?Camarena
somehow like import in pythonHeat
need to add pub to Color and flip I guess sorry I'm not very used to write doc in rust and there is not much doc doc.rust-lang.org/rustdoc/how-to-write-documentation.htmlHeat
Note that doc tests only work for library crates (which can be linked with the test executable), not for program crates.Chirurgeon
M
10

Doc tests (tests inside /// ```) are compiled separately as tiny programs of their own. Therefore:

  • They can only access public items: pub mod, pub fn, pub struct, ...
  • They can only access library crates that export items to be used by other crates — if your program is in main.rs then it's a binary crate.
  • You have to fully qualify or use the names, like use my_library::Color;.

If you want to test things that don't fit this, then you should use #[test] tests instead:

#[test]
fn flip_test() {
    assert_eq!(flip(&Color::White), Color::Black);
}

Any function located anywhere in your program with the attribute #[test] will be run as a test. So, they can access private items since they're in the same module (or a submodule; it's common to put them inside a module named tests in the same file, with mod tests { ... }).

You can find more information about how to write test functions and organize your tests at The Rust Programming Language: How to Write Tests.


I have also tried to Color and flip as public:

/// use crate::{flip, Color};

This doesn't work because crate refers to the current crate, which for a doc test is the test program, not your main crate.

Merciless answered 12/11, 2020 at 16:27 Comment(0)
S
0

Based in part on information in @kevin-reid's answer, I created a library with cargo new --lib player_color and adapted src/lib.rs from the OP's code like so. The following works with both cargo test and cargo docs.

//! Represents player color and flipping thereof
//!
//! - `Color` is an enum
//!
//! - `flip` is used to flip players
//!
//! | `c: Color` | `flip(c)` |
//! |------------|-----------|
//! | `Black`    | `White`   |
//! | `Empty`    | `Empty`   |
//! | `White`    | `Black`   |

/// Represent the player color

#[derive(Clone, PartialEq, Debug)]
pub enum Color {
    Black = 1,
    Empty = 0,
    White = -1,
}

/// Flip the player color
///
/// # Examples
///
/// Example with absolute paths
/// ```
/// assert_eq!(player_color::flip(&player_color::Color::White), player_color::Color::Black);
/// ```
///
/// Example with `use player_color::{flip, Color}`
/// ```
/// use player_color::{flip, Color};
/// assert_eq!(flip(&Color::White), Color::Black);
/// ```
///
/// Example with hidden `use crate::player_color::*`
/// ```
/// # use crate::player_color::*;
/// assert_eq!(flip(&Color::White), Color::Black);
/// ```

pub fn flip(player: &Color) -> Color {
    let intrepresentation: i8 = (player.clone() as i8) * (-1);
    unsafe { std::mem::transmute(intrepresentation) }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn internal() {
        assert_eq!(flip(&Color::White), Color::Black);
    }
}
Seleucid answered 6/4 at 0:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.