After reading Rust book chapter 11

rust


How to Write Tests


The Anatomy of a Test Function

// (1) success
#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}
// (2) Fail
#[cfg(test)]
mod tests {
    #[test]
    fn exploration() {
        assert_eq!(2 + 2, 4);
    }

    #[test]
    fn another() {
        panic!("Make this test fail");
    }
}


Checking Results with the assert! Macro

// (1)
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width > other.width && self.height > other.height
    }
}
// (1-1)
impl Rectangle {
    fn can_hold(&self, other: &Rectangle) -> bool {
        self.width < other.width && self.height > other.height
    }
}
// (2)
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn larger_can_hold_smaller() {
        let larger = Rectangle {
            width: 8,
            height: 7,
        };
        let smaller = Rectangle {
            width: 5,
            height: 1,
        };

        assert!(larger.can_hold(&smaller));
    }
}


Testing Equality with the assert_eq! and assert_ne! Macros


Adding Custom Failure Messages

pub fn greeting(name: &str) -> String {
    String::from("안녕하세요!")
}

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

    #[test]
    fn greeting_contains_name() {
        let result = greeting("캐롤");
        assert!(
					result.contains("캐롤"),
					"Greeting 함수의 결과에 이름이 포함되어 있지 않음. 결과값: '{}'", result
				);
    }

}
running 1 test
test tests::greeting_contains_name ... FAILED

failures:

---- tests::greeting_contains_name stdout ----
thread 'tests::greeting_contains_name' panicked at 'Greeting 함수의 결과에 이름이 포함되어 있지 않음. 결과값: '안녕하세요!'', src/lib.rs:12:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::greeting_contains_name

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


Checking for Panics with should_panic

pub struct Guess {
    value: u32
}

impl Guess {
    pub fn new(value: u32) -> Guess {
        if value < 1 {
            panic!("반드시 100보다 작거나 같은 값을 사용해야 합니다. 지정된 값: {}", value)
        } else if value > 100 {
            panic!("반드시 1보다 크거나 같은 값을 사용해야 합니다. 지정된 값: {}", value);
        }

        Guess {
            value
        }
    }
}

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

    #[test]
    #[should_panic(expected="반드시 100보다 작거나 같은 값을 사용해야 합니다.")]
    fn greater_than_100() {
        Guess::new(200);
    }
}
running 1 test
test tests::greater_than_100 - should panic ... FAILED

failures:

---- tests::greater_than_100 stdout ----
thread 'tests::greater_than_100' panicked at '반드시 1보다 크거나 같은 값을 사용해야 합니다. 지정된 : 200', src/lib.rs:10:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: panic did not contain expected string
      panic message: `"반드시 1보다 크거나 같은 값을 사용해야 합니다. 지정된 값: 200"`,
 expected substring: `"반드시 100보다 작거나 같은 값을 사용해야 합니다."`

failures:
    tests::greater_than_100

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


Using Result<T, E> in Tests

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }
}



Controlling How Tests Are Run


테스트를 병렬/직렬로 실행하기


함수의 결과 보여주기


이름을 이용해 테스트 일부만 실행하기


명시적으로 요청하지 않은 테스트 제외하기



Test Organization


단위 테스트 (unit test)

통합 테스트 (integration test)