Languages/RUST

[RUST] TRPL : Chapter 11 - Test

odaebum 2024. 12. 1. 19:42
728x90

Chapter 11 - TDD

테스트는 코드가 예상대로 기능하는지 확인하는 Rust 함수.

  • 필요한 데이터나 상태를 설정
  • 테스트하려는 코드를 실행
  • 결과가 기대한 대로인지 확인

#[test]

  • 함수를 테스트 함수로 변경함.
    • assert_eq! 메크로를 사용하여 기대 결과를 저장함.
    • cargo test 를 통해서 테스트를 컴파일하고 실행

매크로 결과 확인하기

  • assert! 를 활용하여 테스트의 결과를 확인할 수 있다. (bool)
  • true → ok
  • false → panic!
#[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
    }
}

#[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)); //true가 나와야 정상
    }

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

        assert!(!smaller.can_hold(&larger)); //false가 나와야 정상
    }
}
  • FAILED 의 오류 메시지는 , 를 활용하여 추가할 수 있다.

동등성 테스트

  1. assert_eq! : 코드의 결과와 코드 반환 예상 값 사이의 동등성을 테스트함. (left == right) → true;
  2. assert_ne! : 두 값이 절대 일치하지 않아야할 때 사용함. (left ≠ right) → false;

패닉 확인

should_panic : 코드가 예상대로 오류조건을 처리하는지 확인하는 지 판단함.

  • #[test] 밑에 #[should_panic( ~ )] 과 같이 사용됨.
// --snip--

impl Guess {
    pub fn new(value: i32) -> Guess {
        if value < 1 {
            panic!(
                "Guess value must be greater than or equal to 1, got {value}."
            );
        } else if value > 100 {
            panic!(
                "Guess value must be less than or equal to 100, got {value}."
            );
        }

        Guess { value }
    }
}

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

    #[test]
    #[should_panic(expected = "less than or equal to 100")]
    fn greater_than_100() {
        Guess::new(200);
    }
}

Result<T, E> 테스트에서 사용

  • 기존 panic!을 반환하는 것이 아닌, Result를 반환함
    #[test]
    fn it_works() -> Result<(), String> {
        let result = add(2, 2);

        if result == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }
  • #[should_panic] 에 이용될 수 없다. 따라서 result의 물음표 연산자를 사용한다면, assert! 가 더욱 효과적이다.

테스트 실행 방법 제어

병렬 또는 연속적으로 테스트 실행

  • 여러 테스트를 진행할 때 기본적으로 스레드를 사용하여 병렬로 실행됨.

  • 테스트가 동시에 실행되므로 테스트가 서로 또는 공유된 상태에 의존하지 않도록 해야한다.

    • 병렬을 원하지 않거나 세부적인 제어를 원하는 경우

      $ cargo test -- --test-threads=1
  • 기본적으로 테스트가 통과되면, println!의 출력은 하지 않고, 실패할 때만 출력한다.

    • 그러나 성공할 때도 출력하고싶은 경우

      $ cargo test -- --show-output

테스트 실행

  • 인수를 전달하지 않으면 테스트가 병렬로 실행된다.
  • 인수를 전달하면 해당 인수를 이름으로 가진 테스트들이 실행된다.
  • #[ignore] 을 통해서 무시할 수 있다.
    • cargo test — —ignored.를 통해 무시된 테스트들만 실행할 수 있다.

테스트 조직

단위 테스트

  • 목적 : 나머지 코드와 분리된 각 코드 단위를 테스트하여 코드가 어디에 있고 예상대로 작동하지 않는지 빠르게 파악.
  • #[cfg(test)] : 테스트를 실행할 때만 테스트 코드를 컴파일하고 실행함.

개인 함수 테스트 (private)

  • Rust는 private의 코드도 테스트 가능하다

테스트 디렉토리

adder
├── Cargo.lock
├── Cargo.toml
├── src
│   └── lib.rs
└── tests
    └── integration_test.rs

//tests 디렉토리 안에 있어야 한다.
  • 특정 테스트 함수 실행 : cargo test --test filename_test
728x90