본문 바로가기
카테고리 없음

Rust에서 테스트 코드 작성하기 | #[test] 실전 활용

by mystory55801 2025. 6. 5.

Rust에서 테스트는 어떻게 작성할까요?

Rust는 안전성과 신뢰성을 중시하는 언어인 만큼, 테스트 기능이 표준 라이브러리에 내장되어 있습니다. 별도의 라이브러리 없이도 단위 테스트(Unit Test)를 쉽게 작성하고 실행할 수 있으며, 이는 실무 프로젝트에서 매우 중요한 요소입니다.

Rust의 테스트는 #[test] 어노테이션을 통해 정의되며, cargo test 명령어로 실행됩니다.


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

#[test] 어노테이션의 역할

#[test]는 해당 함수가 테스트 함수임을 컴파일러에 알려줍니다. 이 함수는 반환값이 없고, 인자를 받지 않으며, 실패 시 panic을 일으키는 방식으로 테스트 결과를 판단합니다.

Rust에서는 실패 조건을 assert!, assert_eq!, assert_ne! 등의 매크로로 체크합니다.


#[test]
fn test_addition() {
    assert_eq!(1 + 2, 3);
}

assert! 매크로의 종류와 활용

  • assert!(조건): 조건이 false이면 실패
  • assert_eq!(a, b): a와 b가 같지 않으면 실패
  • assert_ne!(a, b): a와 b가 같으면 실패

#[test]
fn test_comparisons() {
    let a = 5;
    let b = 10;
    assert!(b > a);
    assert_eq!(a + b, 15);
    assert_ne!(a, b);
}

이러한 매크로를 통해 다양한 비교 조건을 설정하고, 예상된 동작 여부를 검증할 수 있습니다.

#[should_panic]으로 실패 테스트 작성

#[should_panic] 어노테이션은 일부러 실패를 기대하는 테스트에 사용됩니다. 예외 상황을 확인하거나, 경계 조건 테스트에 유용합니다.


#[test]
#[should_panic]
fn test_panic() {
    panic!("의도된 실패입니다");
}

특정 메시지를 포함해야 할 경우에는 expected 속성도 사용할 수 있습니다:


#[test]
#[should_panic(expected = "divide by zero")]
fn test_divide_by_zero() {
    let _ = 1 / 0;
}

테스트 모듈 구성: #[cfg(test)]의 의미

테스트 코드 블록은 일반적으로 #[cfg(test)]와 함께 사용됩니다. 이 속성은 테스트 빌드 시에만 해당 모듈을 포함하라는 의미입니다.


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

    #[test]
    fn example() {
        assert_eq!(add(2, 3), 5);
    }
}

이런 구조를 사용하면 테스트 코드를 본 코드와 깔끔하게 분리할 수 있고, 컴파일 타임에 불필요한 코드가 포함되지 않도록 할 수 있습니다.

테스트 함수에서 실제 함수 호출하기

실제로 테스트는 모듈 외부의 함수를 검증하는 데 사용됩니다. 예를 들어, 라이브러리의 add 함수가 예상대로 동작하는지를 검증할 수 있습니다.


// 라이브러리 코드
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

// 테스트 코드
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_add() {
        assert_eq!(add(10, 5), 15);
    }
}

cargo test로 테스트 실행하기

테스트는 cargo test 명령어로 실행할 수 있으며, 모든 테스트 함수가 자동으로 실행됩니다. 실패한 테스트는 상세한 메시지와 함께 출력되므로, 디버깅에 큰 도움이 됩니다.


$ cargo test

running 1 test
test tests::test_add ... ok

test result: ok. 1 passed; 0 failed

테스트 필터링과 개별 실행

특정 테스트만 실행하려면 테스트 함수 이름을 부분 문자열로 지정하여 실행할 수 있습니다.


$ cargo test test_add

또한, #[ignore] 어노테이션을 사용하면 기본 테스트 실행에서 제외할 수도 있습니다.


#[test]
#[ignore]
fn slow_test() {
    // 느린 테스트
}

결론: Rust 테스트는 필수, 어렵지 않다

Rust의 #[test] 기능은 간단하면서도 강력한 테스트 시스템을 제공합니다. assert 계열 매크로와 함께 #[should_panic], #[ignore] 등의 속성을 활용하면, 복잡한 로직에 대해서도 신뢰성 있는 테스트를 작성할 수 있습니다.

cargo test로 간편하게 실행하고, 함수 단위 테스트 → 모듈 테스트 → 통합 테스트까지 확장 가능하므로, 프로젝트 초기부터 테스트 습관을 들이는 것이 좋습니다.

테스트는 버그를 막는 최선의 방법이자, 안전하고 유지 보수 가능한 Rust 코드를 위한 필수 도구입니다.