🦀
모던 Rust
모던 · 선수: 19강
20. 단위 테스트·통합 테스트·doctest
Rust 는 테스트 러너가 cargo 에 내장돼 있습니다. #[test] 어트리뷰트를 함수에 붙이면 cargo test 가 자동으로 모아 실행. 단위 테스트(같은 파일의 mod tests), 통합 테스트(tests/ 폴더), 그리고 문서 안의 코드 블록을 자동 실행하는 doctest 까지 한 번에 정리합니다.
Rusttestcargo testdoctestassert_eqTDD
소요 시간
⏱ 약 1.5시간
난이도
📊 중급
선수 조건
🎯 19강
결과물
Rust 는 테스트 러너가 cargo 에 내장돼 있습니다. #[test] 어트리뷰트를 함수에 붙이면 cargo test 가 자동으로 모아 실행. 단위 테스트(같은 파일의 mod tests), 통합 테스트(tests/ 폴더), 그리고 문서 안의 코드 블록을 자동 실행하는 doctest 까지 한 번에 정리합니다.
이 강의에서 배우는 것
- 1#[test] 함수를 작성하고 cargo test 로 실행한다
- 2단위 테스트의 mod tests 관례를 따른다
- 3통합 테스트를 tests/ 폴더에 분리해 작성한다
- 4#[should_panic] 으로 패닉 검증 테스트를 작성한다
- 5/// 주석 안의 예제 코드를 doctest 로 실행한다
소개
테스트가 별도 도구 없이 cargo 안에 들어 있다는 것은 큰 이점입니다. "테스트 프레임워크 뭘 쓰지" 같은 결정을 할 필요가 없고, 새 프로젝트도 처음부터 테스트를 자연스럽게 작성할 수 있습니다.
핵심 개념
1) 단위 테스트 — 같은 파일 안 mod tests
rust
pub fn add(a: i32, b: i32) -> i32 { a + b }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn add_works() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn add_negative() {
assert_eq!(add(-1, 1), 0);
}
}- `#[cfg(test)]` — 테스트 빌드에서만 컴파일
- `use super::*` — 부모 모듈의 private 항목까지 접근 가능
- `#[test]` 가 붙은 fn 만 cargo test 가 실행
2) 통합 테스트 — tests/ 폴더
라이브러리의 공개 API 만 사용해 전체 동작을 검증. 외부 사용자가 쓰는 것과 같은 경로.
rust
// tests/api.rs
use my_crate::add;
#[test]
fn integration_add() {
assert_eq!(add(10, 20), 30);
}3) 자주 쓰는 assert 매크로
| 매크로 | 용도 |
|---|---|
| assert!(expr) | expr 이 true 여야 |
| assert_eq!(a, b) | a == b |
| assert_ne!(a, b) | a != b |
| #[should_panic] | 테스트 함수가 panic 해야 통과 |
| #[ignore] | 기본 실행에서 제외 (cargo test -- --ignored) |
4) doctest — /// 안의 예제 코드 실행
rust
/// 두 수를 더합니다.
///
/// # 예제
///
/// ```
/// assert_eq!(my_crate::add(2, 3), 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 { a + b }핵심 예제
Result 반환 테스트와 should_panic:
rust
pub fn divide(a: i32, b: i32) -> i32 {
if b == 0 { panic!("div by zero"); }
a / b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ok_case() -> Result<(), String> {
if divide(10, 2) == 5 { Ok(()) } else { Err("expected 5".into()) }
}
#[test]
#[should_panic(expected = "div by zero")]
fn panic_case() { divide(10, 0); }
}실행 명령:
bash
cargo test # 전체
cargo test add_ # 이름에 add_ 가 포함된 것만
cargo test -- --nocapture # println! 출력 보기
cargo test --doc # doctest 만
cargo test -- --ignored # ignore 된 것 실행자주 하는 실수
Q. cargo test 출력에 println! 이 안 보입니다
A. 기본 동작입니다 — 성공한 테스트의 출력은 가려집니다. `cargo test -- --nocapture` 로 켤 수 있습니다.
Q. tests/ 폴더와 mod tests 의 차이는?
A. **mod tests** = 같은 crate 내부 private 까지 접근 가능. **tests/** = 외부 사용자 시점에서 public API 만 호출. 둘을 함께 쓰는 것이 일반적.
Q. 테스트가 너무 느립니다
A. cargo test 는 기본적으로 병렬 실행합니다. 직렬이 필요하면 `cargo test -- --test-threads=1`. 특정 테스트만 `--ignored` 로 분리해 평소 실행에서 빼는 것도 방법.
정리
- cargo test 가 #[test] 함수를 자동 수집·실행
- mod tests + #[cfg(test)] = 단위 테스트 관례
- tests/ 폴더 = 통합 테스트 (public API 만)
- /// 안 코드 블록 = doctest 자동 실행
- should_panic·ignore·assert_eq 매크로 활용
과제
- 기존 라이브러리 함수에 mod tests 를 붙이고 3개 이상 단위 테스트 작성
- tests/api.rs 에 통합 테스트 하나 추가
- /// 주석 예제 코드를 추가하고 cargo test --doc 으로 통과 확인