테스트 속성

테스트 속성

다음 속성들은 테스트를 수행할 함수를 지정할 때 쓰여요. 크레이트를 "테스트" 모드로 컴파일하면 테스트 함수들과, 테스트를 실행하기 위한 테스트 하니스(test harness)를 함께 빌드해요. 테스트 모드를 켜면 test 조건부 컴파일 옵션도 함께 활성화돼요.

출처: Rust Reference

본문

test 속성

test 속성은 함수를 테스트로 실행되도록 표시해요.

#![allow(unused)]
fn main() {
pub fn add(left: u64, right: u64) -> u64 { left + right }
#[test]
fn it_works() {
 let result = add(2, 2);
 assert_eq!(result, 4);
}
}

test 속성은 MetaWord 문법을 사용해요.

test 속성은 **단형(monomorphic)이고, 인자를 받지 않으며, 반환 타입이 Termination 트레이트를 구현하는 자유 함수(free function)**에만 적용할 수 있어요.

참고: Termination 트레이트를 구현하는 타입에는 ()와, T: Termination이고 E: DebugResult<T, E>가 포함돼요.

함수에 test처음 쓴 것만 효과가 있어요. 처음 이후의 사용은 rustc가 린트로 잡아요. (이것은 나중에 에러가 될 수도 있어요.)

test 속성은 표준 라이브러리 prelude에서 std::prelude::v1::test로 내보내져요. 그리고 이 함수들은 테스트 모드에서만 컴파일돼요.

참고: 테스트 모드는 rustc에 --test 인자를 넘기거나 cargo test를 써서 활성화할 수 있어요.

테스트 하니스는 반환된 값의 report 메서드를 호출해서, 결과 ExitCode가 성공적인 종료를 나타내는지에 따라 테스트를 passed 또는 failed로 분류해요. 구체적으로는 다음과 같아요.

  • ()를 반환하는 테스트는 종료하고 패닉만 하지 않으면 통과해요.
  • Result<(), E>를 반환하는 테스트는 Ok(())를 반환하면 통과해요.
  • ExitCode::SUCCESS를 반환하면 통과하고, ExitCode::FAILURE를 반환하면 실패해요.
  • 종료하지 않는 테스트는 통과도 실패도 아니에요.
#![allow(unused)]
fn main() {
use std::io;
fn setup_the_thing() -> io::Result<i32> { Ok(1) }
fn do_the_thing(s: &i32) -> io::Result<()> { Ok(()) }
#[test]
fn test_the_thing() -> io::Result<()> {
 let state = setup_the_thing()?; // expected to succeed
 do_the_thing(&state)?; // expected to succeed
 Ok(())
}
}

ignore 속성

ignore 속성은 test 속성과 함께 쓰여, 테스트 하니스에게 그 함수를 테스트로 실행하지 말라고 알려줘요.

#![allow(unused)]
fn main() {
#[test]
#[ignore]
fn check_thing() {
 // …
}
}

참고: rustc 테스트 하니스는 --include-ignored 플래그로 무시된 테스트를 강제로 실행할 수 있게 해줘요.

ignore 속성은 MetaWordMetaNameValueStr 문법을 사용해요. MetaNameValueStr 형태는 그 테스트를 왜 무시하는지 이유를 지정하는 방법을 제공해요.

#![allow(unused)]
fn main() {
#[test]
#[ignore = "not yet implemented"]
fn mytest() {
 // …
}
}

ignore 속성은 test 속성이 붙은 함수에만 적용할 수 있어요. 다른 위치에서 쓰면 rustc가 무시하지만 린트로 잡아요. (이것은 나중에 에러가 될 수도 있어요.) 그리고 ignore를 함수에 처음 쓴 것만 효과가 있어요.

무시된 테스트는 테스트 모드에서 여전히 컴파일되지만 실행되지는 않아요.

should_panic 속성

should_panic 속성은 그 속성이 붙은 테스트 함수가 패닉할 때만 테스트가 통과하도록 해요.

#![allow(unused)]
fn main() {
#[test]
#[should_panic(expected = "values don't match")]
fn mytest() {
 assert_eq!(1, 2, "values don't match");
}
}

should_panic 속성은 다음과 같은 형태가 있어요.

  • MetaWord — 패닉 여부만 확인해요.
#![allow(unused)]
fn main() {
#[test]
#[should_panic]
fn mytest() { panic!("error: some message, and more"); }
}
  • MetaNameValueStr — 주어진 문자열이 패닉 메시지 안에 나타나야 테스트가 통과해요.
#![allow(unused)]
fn main() {
#[test]
#[should_panic = "some message"]
fn mytest() { panic!("error: some message, and more"); }
}
  • MetaListNameValueStrMetaNameValueStr 문법처럼, 주어진 문자열이 패닉 메시지 안에 나타나야 해요.
#![allow(unused)]
fn main() {
#[test]
#[should_panic(expected = "some message")]
fn mytest() { panic!("error: some message, and more"); }
}

should_panic 속성은 test 속성이 붙은 함수에만 적용할 수 있어요. 다른 위치에서 쓰면 rustc가 무시하지만 린트로 잡아요. (이것은 나중에 에러가 될 수도 있어요.) 그리고 처음 쓴 것만 효과가 있어요.

MetaNameValueStr 형태나 expected 키가 있는 MetaListNameValueStr 형태를 쓰면, 주어진 문자열이 패닉 메시지 어딘가에 나타나야 테스트가 통과해요.

should_panic이 붙은 테스트 함수의 반환 타입은 **()**이어야 해요.

더 알아보기

  • Termination 트레이트와 ExitCode를 살펴보면 테스트의 성공/실패 분류가 어떻게 이뤄지는지 더 명확해져요.
  • #[test] 설정을 cargo test와 함께 쓰는 방식과 예외 케이스(--include-ignored)를 확인해 보세요.