본문 바로가기

테스트 실행 제어

cargo test와 테스트 바이너리의 인수 경계를 구분하고, 실행 범위·출력·동시성을 조절해 실패를 재현합니다.

cargo run이 코드를 컴파일해 실행 파일을 실행하듯이, cargo test는 코드를 테스트 모드로 컴파일해 테스트 실행 파일을 실행합니다. 이 실행 파일은 기본으로 모든 테스트를 병렬로 실행하고, 테스트가 실행되는 동안 출력을 가로채 화면에 보이지 않게 해서 결과를 읽기 쉽게 합니다. 명령줄 옵션으로 이 기본 동작을 바꿀 수 있습니다.

옵션 가운데 일부는 cargo test에, 일부는 만들어진 테스트 실행 파일에 넘깁니다. 두 종류를 나누려면 cargo test에 줄 인수를 먼저 적고, 구분자 -- 뒤에 테스트 실행 파일에 줄 인수를 적습니다. cargo test --help는 cargo test에 쓸 수 있는 옵션을, cargo test -- --help는 구분자 뒤에 쓸 수 있는 옵션을 보여 줍니다. 아래 표는 --를 기준으로 어느 쪽이 무엇을 해석하는지 정리한 것입니다.

cargo test 명령에서 Cargo가 해석하는 선택 옵션과 한 개의 TESTNAME 위치, 구분자, 테스트 실행 파일이 해석하는 범위, 출력, 동시성 옵션을 구분하는 표와 모바일 카드

Rust · Cargo / libtest · semantic table

cargo test 인수는 -- 경계에서 해석 주체가 갈린다

--는 옵션 자체가 아니라 전달 경계입니다. 앞에서는 Cargo가 패키지와 대상을 고르고, 선택적인 [TESTNAME] 하나를 테스트 실행 파일에 넘깁니다. 뒤에서는 테스트 하네스가 범위, 출력, 동시성 옵션을 해석합니다.

명령줄 위치 × 구문 × 해석 주체 × 실행 의미
명령줄 위치대표 구문해석 주체실행 의미
-- 앞 선택 옵션 -p app, --lib, --release Cargo 패키지, 테스트 대상, 빌드 프로필을 고릅니다.
[TESTNAME] cargo test one_hundred Cargo가 한 위치만 받고 하네스에 전달 하네스가 전체 테스트 경로의 부분 문자열로 일치시킵니다. 정확히 하나를 뜻하지 않습니다.
전달 경계 -- Cargo 이 뒤의 인수를 해석하지 않고 테스트 실행 파일에 전달합니다.
-- 뒤 실행 옵션 --exact, --show-output, --test-threads=1 테스트 하네스 이름 일치, 캡처 출력 표시, 하네스 작업 스레드 수를 조절합니다.
-- 뒤 무시 옵션 --ignored, --include-ignored 테스트 하네스 컴파일된 #[ignore] 테스트만 실행하거나 일반 테스트와 함께 실행합니다.

Cargo selection

-- 앞 선택 옵션

-p app, --lib, --release는 Cargo가 패키지, 테스트 대상, 빌드 프로필을 고르는 데 사용합니다.

one positional slot

[TESTNAME]

Cargo가 한 위치만 받아 테스트 실행 파일에 전달합니다. 하네스는 전체 테스트 경로의 부분 문자열로 일치시키므로 정확히 하나를 뜻하지 않습니다.

routing boundary

--

Cargo는 이 뒤의 인수를 해석하지 않고 테스트 실행 파일로 전달합니다.

harness behavior

범위, 출력, 동시성

--exact, --show-output, --test-threads=1은 테스트 하네스가 해석합니다.

ignored tests

무시된 테스트 선택

#[ignore] 테스트도 컴파일됩니다. --ignored는 이 테스트만, --include-ignored는 일반 테스트와 함께 실행합니다.

도움말도 같은 경계를 따릅니다. cargo test --help는 Cargo 도움말을, cargo test -- --help는 현재 테스트 하네스 도움말을 표시합니다. 명령 전체는 토큰 사이에서 줄바꿈할 수 있고 각 옵션 토큰은 한 덩어리로 읽습니다.

-- 앞에서는 Cargo가 패키지와 테스트 대상을 고르고, 테스트 이름을 거르는 문자열 하나를 테스트 실행 파일에 넘깁니다. -- 뒤의 --test-threads나 --show-output, --ignored 같은 옵션은 테스트 실행 파일이 해석해, 무엇을 실행하고 출력을 어떻게 보여 주며 몇 개를 동시에 실행할지 정합니다. 이 옵션들은 cargo test 문서의 테스트 부분에 설명되어 있습니다.

테스트를 병렬 혹은 순차적으로 실행하기

테스트가 여러 개면 기본으로 스레드를 써서 병렬로 실행하므로 더 빨리 끝나고 결과를 빨리 받을 수 있습니다. 대신 테스트가 동시에 실행되므로, 테스트끼리 서로 기대거나 지금 작업 폴더나 환경 변수 같은 공유 상태를 함께 쓰지 않게 해야 합니다.

예를 들어 테스트마다 test-output.txt 파일을 만들어 데이터를 쓰고, 그 파일을 읽어 특정 값이 들어 있는지 확인하는데, 그 값이 테스트마다 다르다고 합시다. 테스트가 동시에 실행되므로, 한 테스트가 파일에 쓰고 읽는 사이에 다른 테스트가 그 파일을 덮어쓸 수 있습니다. 그러면 코드가 틀려서가 아니라 병렬로 실행되며 서로 방해해서 둘째 테스트가 실패합니다. 테스트마다 다른 파일에 쓰게 하는 방법도 있고, 테스트를 하나씩 실행하는 방법도 있습니다.

테스트를 병렬로 실행하고 싶지 않거나, 쓸 스레드의 수를 더 세밀하게 정하고 싶다면 --test-threads 옵션에 쓸 스레드의 수를 줍니다.

cargo test -- --test-threads=1

스레드를 1로 정하면 병렬을 쓰지 않으므로 테스트가 더 오래 걸리지만, 테스트끼리 상태를 나누어 쓸 때 서로 방해하지 않습니다. 다만 이 옵션은 테스트 실행 파일이 테스트 함수를 하나씩 시작하게 할 뿐이므로, 테스트 코드가 직접 만드는 스레드나 다른 프로세스까지 막지는 않습니다. 그래서 공유 상태는 먼저 테스트마다 따로 두도록 고치고, --test-threads=1은 동시 실행이 실패의 원인인지 확인하는 데 씁니다.

더 깊이: 모든 테스트는 한 프로세스 안에서 실행됩니다

rustc 문서의 테스트 설명에 따르면, 한 테스트 실행 파일 안의 테스트는 모두 같은 프로세스에서 실행되며, 기본으로는 std::thread::available_parallelism이 알려 주는 하드웨어의 동시 실행 수만큼 스레드를 써서 병렬로 실행됩니다. 그래서 테스트끼리 나누어 쓰게 되는 것은 파일만이 아닙니다. 지금 작업 폴더, 환경 변수, 전역 static 값처럼 프로세스 전체에 하나뿐인 상태는 모두 함께 쓰이므로, 한 테스트가 바꾼 값을 동시에 실행되는 다른 테스트가 읽을 수 있습니다. 환경 변수에 기대는 기능을 테스트할 때 환경 변수 활용에서처럼 자식 프로세스를 따로 실행하는 편이 안전한 것도 이 때문입니다.

같은 문서는 테스트가 실패하는 경우를 패닉을 내거나, Result처럼 Termination을 구현한 타입으로 실패를 돌려준 경우로 정합니다. 테스트 실행기는 테스트의 패닉을 잡아 실패로 기록하고 다음 테스트를 이어 가야 하므로, 테스트는 되감기(unwind) 패닉 전략으로 빌드해야 합니다. 그래서 Cargo는 테스트를 빌드할 때 프로필의 panic 설정을 따르지 않으며, 프로필에 panic = 'abort'를 적어 두어도 테스트는 되감기 전략으로 빌드됩니다.

함수 출력 표시하기

기본으로 테스트가 통과하면 러스트의 테스트 라이브러리는 표준 출력에 출력된 내용을 모두 가로챕니다. 예를 들어 테스트에서 println!을 부르고 테스트가 통과하면, 터미널에 그 println!의 출력은 보이지 않고 테스트가 통과했다는 줄만 보입니다. 테스트가 실패하면 실패 메시지와 함께 표준 출력에 출력된 내용이 나옵니다. 다음은 매개변수의 값을 출력하고 10을 돌려주는 엉성한 함수와, 통과하는 테스트와 실패하는 테스트입니다.

src/lib.rs
fn prints_and_returns_10(a: i32) -> i32 {
    println!("I got the value {a}");
    10
}

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

    #[test]
    fn this_test_will_pass() {
        let value = prints_and_returns_10(4);
        assert_eq!(value, 10);
    }

    #[test]
    fn this_test_will_fail() {
        let value = prints_and_returns_10(8);
        assert_eq!(value, 5);
    }
}
running 2 tests
test tests::this_test_will_fail ... FAILED
test tests::this_test_will_pass ... ok

failures:

---- tests::this_test_will_fail stdout ----
I got the value 8

thread 'tests::this_test_will_fail' (6017887) panicked at src/lib.rs:19:9:
assertion `left == right` failed
  left: 10
 right: 5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    tests::this_test_will_fail

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

통과한 테스트가 출력한 I got the value 4는 어디에도 보이지 않으며, 가로채졌기 때문입니다. 실패한 테스트의 출력 I got the value 8은 실패 까닭과 함께 테스트 요약의 그 부분에 나옵니다. 테스트가 병렬로 실행되므로 앞의 두 결과 줄의 순서는 실행할 때마다 다를 수 있습니다. 통과한 테스트의 출력도 보고 싶다면 --show-output을 줍니다.

cargo test -- --show-output
successes:

---- tests::this_test_will_pass stdout ----
I got the value 4


successes:
    tests::this_test_will_pass

이번에는 결과에 통과한 테스트의 출력을 모은 successes 부분이 더해집니다. 실패한 테스트의 부분은 앞과 같으므로 생략했습니다.

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

테스트를 모두 실행하면 오래 걸릴 수 있습니다. 코드의 특정 부분을 고치고 있다면 그 부분의 테스트만 실행하고 싶을 것입니다. cargo test에 실행할 테스트의 이름을 인수로 주면 실행할 테스트를 고를 수 있습니다. 일부 테스트만 실행하는 방법을 보기 위해, add_two 함수에 이름이 다른 테스트 세 개를 둡니다.

src/lib.rs
pub fn add_two(a: u64) -> u64 {
    a + 2
}

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

    #[test]
    fn add_two_and_two() {
        let result = add_two(2);
        assert_eq!(result, 4);
    }

    #[test]
    fn add_three_and_two() {
        let result = add_two(3);
        assert_eq!(result, 5);
    }

    #[test]
    fn one_hundred() {
        let result = add_two(100);
        assert_eq!(result, 102);
    }
}

인수 없이 테스트를 실행하면 앞에서 본 것처럼 세 테스트가 모두 병렬로 실행됩니다.

이름으로 실행 범위 좁히기

테스트 함수의 이름을 cargo test에 주면 그 테스트만 실행합니다. 앞에서 만든 세 테스트 가운데 하나의 이름을 주면, 결과의 요약 줄에서 실행하지 않은 테스트의 수도 함께 볼 수 있습니다.

cargo test one_hundred
running 1 test
test tests::one_hundred ... ok

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

one_hundred라는 이름의 테스트만 실행되었고, 다른 두 테스트는 이름이 맞지 않았습니다. 결과의 끝에 2 filtered out이 나와, 실행하지 않은 테스트가 있다는 것을 알려 줍니다. 이 방법으로는 cargo test 바로 뒤에 테스트 이름을 하나만 줄 수 있으며, cargo test one_hundred add_two_and_two처럼 둘 이상 적으면 Cargo가 인수 오류를 내고 테스트를 실행하지 않습니다. 여러 이름으로 고르려면 cargo test -- one_hundred add_two_and_two처럼 구분자 -- 뒤에 적으며, 그러면 테스트 실행 파일이 그 가운데 하나라도 이름에 들어 있는 테스트를 실행합니다.

테스트를 필터링하여 여러 테스트 실행하기

테스트 이름의 일부만 적으면, 그 문자열이 이름에 들어 있는 테스트가 모두 실행됩니다. 예를 들어 두 테스트의 이름에 add가 들어 있으므로 cargo test add로 두 테스트를 실행할 수 있습니다.

cargo test add
running 2 tests
test tests::add_three_and_two ... ok
test tests::add_two_and_two ... ok

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

이 명령은 이름에 add가 든 테스트를 모두 실행하고 one_hundred를 걸러 냈습니다. 테스트가 속한 모듈의 이름도 테스트 이름의 일부가 되므로, 모듈 이름으로 거르면 그 모듈의 테스트를 모두 실행할 수 있습니다. 이름은 정확히 같은지가 아니라 그 문자열을 포함하는지로 고르므로, 하나만 정확히 고르려면 cargo test tests::one_hundred -- --exact처럼 --exact를 함께 줍니다.

특별 요청이 없다면 일부 테스트 무시하기

특정 테스트가 실행하는 데 아주 오래 걸려서, cargo test를 실행할 때 대부분은 빼고 싶을 수 있습니다. 실행하고 싶은 테스트를 모두 인수로 나열하는 대신, 오래 걸리는 테스트에 ignore 속성을 붙여 뺄 수 있습니다.

src/lib.rs
pub fn add(left: u64, right: u64) -> u64 {
    left + right
}

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

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }

    #[test]
    #[ignore]
    fn expensive_test() {
        // 한 시간쯤 걸리는 코드
    }
}

빼고 싶은 테스트의 #[test] 다음 줄에 #[ignore]를 붙였습니다. 이제 테스트를 실행하면 it_works는 실행되지만 expensive_test는 실행되지 않습니다.

running 2 tests
test tests::expensive_test ... ignored
test tests::it_works ... ok

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

expensive_test는 ignored로 표시됩니다. 무시한 테스트만 실행하고 싶다면 cargo test -- --ignored를, 무시했든 안 했든 모든 테스트를 실행하고 싶다면 cargo test -- --include-ignored를 씁니다. 어떤 테스트를 실행할지 정해 두면 cargo test의 결과를 빨리 받을 수 있으며, 무시한 테스트의 결과를 확인할 시간이 있을 때 cargo test -- --ignored를 실행하면 됩니다.

테스트 실행 범위 조절 기준

테스트가 실패하면 먼저 기본 cargo test로 무엇이 실패했고 무엇이 출력되었는지 기록해 둡니다. 그다음 아래 그림처럼 실행 범위, 가로챈 출력, 동시 실행 가운데 지금 필요한 것 하나만 골라 바꿔 다시 실행합니다.

Rust 테스트 실패 진단 흐름

기본 실패 관측→필요한 범위/출력/동시성 축 하나 선택→재실행 비교로 진단 상태가 바뀐다. 세 옵션을 필수 순차 단계로 만들지 않는다.

기본 cargo test로 현상을 확인한 뒤 실행 범위, 캡처 출력, 하네스 동시성 가운데 필요한 축을 골라 각각 이름과 ignore 옵션, show-output, test-threads 옵션을 적용하고 다시 조합해 재실행하는 여섯 노드 흐름

Rust · test diagnostics · flowchart

실패를 보면 범위, 출력, 동시성을 독립적으로 조절한다

먼저 기본 실행으로 증거를 남긴 뒤 필요한 축만 바꿉니다. 이름과 ignore는 실행 범위, --show-output은 캡처된 출력, --test-threads=1은 해당 하네스의 작업 스레드 수만 조절합니다.

실행 범위·출력·하네스 동시성의 독립된 진단 축기본 실행 뒤 독립적인 세 축을 선택한다. 실행 범위·캡처된 출력·하네스 작업 스레드 수를 조절하고 필요한 옵션을 조합해 재실행한다.기본 실행으로 현상 확인cargo test지금 무엇을 확인할까?범위 · 출력 · 동시성실행 범위출력동시성실행 범위 조절FILTER / --exact--ignored--include-ignored캡처된 출력 표시--show-output성공 출력도 종료 뒤실시간 캡처 해제 아님하네스 동시성 제한--test-threads=1하네스 작업 스레드만자체 스레드·외부는 별도필요한 옵션을 조합해 재실행재현 · 비교 · 증거 보존
독립된 세 진단 축의 선택과 합류기본실행에서선택노드로간뒤 범위/출력/하네스동시성3개독립대안에분기하고 재실행노드에합류한다. 총6노드7관계이며 세축이위아래로배치되어도 범위→출력→동시성을모두순서대로수행하라는흐름이아니다. 왼쪽각레일은선택에서각축으로가는관계, 오른쪽레일은각축에서재실행으로합류하는관계다. show-output은종료뒤성공출력표시,threads1은하네스만제한한다.기본 실행cargo test확인할 축 선택범위·출력·동시성실행 범위FILTER / --exact--ignored--include-ignored캡처 출력--show-output성공 출력도 종료 뒤실시간 해제 아님하네스 동시성--test-threads=1자체 스레드·외부는별도로 격리필요 옵션 조합재실행·비교바꾼 축과 증거 기록세 축은 독립: 순차 3단계 아님

baseline

1. 기본 실행으로 현상 확인

먼저 cargo test 결과를 남깁니다. 테스트 순서, 경로, 바이너리 해시, 시간과 출력 문구는 도구 체인과 환경에 따라 달라질 수 있습니다.

choose one axis

2. 지금 무엇을 확인할까?

실행 범위, 캡처된 출력, 하네스 동시성은 독립된 축입니다. 증거에 필요한 축부터 고릅니다.

range

3. 실행 범위 좁히기

부분 문자열 필터와 --exact로 이름 범위를 조절합니다. 컴파일된 무시 테스트는 --ignored 또는 --include-ignored로 고릅니다.

output

4. 캡처된 출력 함께 보기

--show-output은 성공한 테스트의 캡처된 표준 출력과 표준 오류를 종료 뒤에 표시합니다. 실시간 캡처 해제가 아닙니다.

concurrency

5. 하네스 동시성 제한

--test-threads=1은 해당 실행 파일의 하네스 작업 스레드만 제한합니다. 테스트 자체의 스레드나 외부 경쟁까지 제거하지 않습니다.

fan-in

6. 필요한 옵션을 조합해 재실행

바꾼 축과 관찰 결과를 기록하고, 필요하면 독립 옵션을 조합해 같은 실패가 재현되는지 비교합니다.

여러 일반 테스트 대상은 별도 실행 파일로 Cargo가 차례로 실행하고, 각 실행 파일 안에서는 테스트 하네스가 기본적으로 병렬 실행합니다. 직렬 진단은 공유 상태 격리를 대신하지 않습니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명기본 실행에서 선택 노드로 간 뒤 범위/출력/하네스 동시성 3개 독립 대안으로 분기하고 재실행 노드로 합류한다. 총 6노드 7관계이며 세 축이 위아래로 배치되어도 범위→출력→동시성을 모두 순서대로 수행하라는 흐름이 아니다. 왼쪽 각 레일은 선택에서 각 축으로 가는 관계, 오른쪽 레일은 각 축에서 재실행으로 합류하는 관계다. show-output은 종료 뒤 성공 출력 표시이고, threads 1은 하네스만 제한한다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
실패 관측

기본 실행의 실패와 출력 범위를 기록한다.

  • 명령: cargo test
  • 근거: 관측한 실패
  • 출력이 보이지 않는 문제와 테스트 범위 문제를 먼저 구분한다.
한 진단 축

필터·출력·동시성 중 필요한 옵션 하나를 고른다.

  • 선택: 진단 축 한 가지
  • 범위: 현재 실패에 필요한 범위
  • 세 옵션을 필수 순차 절차로 적용하지 않는다.
결과 대조

변경한 실행 조건과 새로운 근거를 비교한다.

  • 기준: 기본 실행
  • 재실행: 선택 옵션 적용
  • 조건 차이를 기록해야 관측 차이를 코드 변화로 오인하지 않는다.

Rust 테스트 실패 진단 흐름

기본 실패 관측→필요한 범위/출력/동시성 축 하나 선택→재실행 비교로 진단 상태가 바뀐다. 세 옵션을 필수 순차 단계로 만들지 않는다.

기본 cargo test로 현상을 확인한 뒤 실행 범위, 캡처 출력, 하네스 동시성 가운데 필요한 축을 골라 각각 이름과 ignore 옵션, show-output, test-threads 옵션을 적용하고 다시 조합해 재실행하는 여섯 노드 흐름

Rust · test diagnostics · flowchart

실패를 보면 범위, 출력, 동시성을 독립적으로 조절한다

먼저 기본 실행으로 증거를 남긴 뒤 필요한 축만 바꿉니다. 이름과 ignore는 실행 범위, --show-output은 캡처된 출력, --test-threads=1은 해당 하네스의 작업 스레드 수만 조절합니다.

실행 범위·출력·하네스 동시성의 독립된 진단 축기본 실행 뒤 독립적인 세 축을 선택한다. 실행 범위·캡처된 출력·하네스 작업 스레드 수를 조절하고 필요한 옵션을 조합해 재실행한다.기본 실행으로 현상 확인cargo test지금 무엇을 확인할까?범위 · 출력 · 동시성실행 범위출력동시성실행 범위 조절FILTER / --exact--ignored--include-ignored캡처된 출력 표시--show-output성공 출력도 종료 뒤실시간 캡처 해제 아님하네스 동시성 제한--test-threads=1하네스 작업 스레드만자체 스레드·외부는 별도필요한 옵션을 조합해 재실행재현 · 비교 · 증거 보존
독립된 세 진단 축의 선택과 합류기본실행에서선택노드로간뒤 범위/출력/하네스동시성3개독립대안에분기하고 재실행노드에합류한다. 총6노드7관계이며 세축이위아래로배치되어도 범위→출력→동시성을모두순서대로수행하라는흐름이아니다. 왼쪽각레일은선택에서각축으로가는관계, 오른쪽레일은각축에서재실행으로합류하는관계다. show-output은종료뒤성공출력표시,threads1은하네스만제한한다.기본 실행cargo test확인할 축 선택범위·출력·동시성실행 범위FILTER / --exact--ignored--include-ignored캡처 출력--show-output성공 출력도 종료 뒤실시간 해제 아님하네스 동시성--test-threads=1자체 스레드·외부는별도로 격리필요 옵션 조합재실행·비교바꾼 축과 증거 기록세 축은 독립: 순차 3단계 아님

baseline

1. 기본 실행으로 현상 확인

먼저 cargo test 결과를 남깁니다. 테스트 순서, 경로, 바이너리 해시, 시간과 출력 문구는 도구 체인과 환경에 따라 달라질 수 있습니다.

choose one axis

2. 지금 무엇을 확인할까?

실행 범위, 캡처된 출력, 하네스 동시성은 독립된 축입니다. 증거에 필요한 축부터 고릅니다.

range

3. 실행 범위 좁히기

부분 문자열 필터와 --exact로 이름 범위를 조절합니다. 컴파일된 무시 테스트는 --ignored 또는 --include-ignored로 고릅니다.

output

4. 캡처된 출력 함께 보기

--show-output은 성공한 테스트의 캡처된 표준 출력과 표준 오류를 종료 뒤에 표시합니다. 실시간 캡처 해제가 아닙니다.

concurrency

5. 하네스 동시성 제한

--test-threads=1은 해당 실행 파일의 하네스 작업 스레드만 제한합니다. 테스트 자체의 스레드나 외부 경쟁까지 제거하지 않습니다.

fan-in

6. 필요한 옵션을 조합해 재실행

바꾼 축과 관찰 결과를 기록하고, 필요하면 독립 옵션을 조합해 같은 실패가 재현되는지 비교합니다.

여러 일반 테스트 대상은 별도 실행 파일로 Cargo가 차례로 실행하고, 각 실행 파일 안에서는 테스트 하네스가 기본적으로 병렬 실행합니다. 직렬 진단은 공유 상태 격리를 대신하지 않습니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명기본 실행에서 선택 노드로 간 뒤 범위/출력/하네스 동시성 3개 독립 대안으로 분기하고 재실행 노드로 합류한다. 총 6노드 7관계이며 세 축이 위아래로 배치되어도 범위→출력→동시성을 모두 순서대로 수행하라는 흐름이 아니다. 왼쪽 각 레일은 선택에서 각 축으로 가는 관계, 오른쪽 레일은 각 축에서 재실행으로 합류하는 관계다. show-output은 종료 뒤 성공 출력 표시이고, threads 1은 하네스만 제한한다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
실패 관측

기본 실행의 실패와 출력 범위를 기록한다.

  • 명령: cargo test
  • 근거: 관측한 실패
  • 출력이 보이지 않는 문제와 테스트 범위 문제를 먼저 구분한다.
한 진단 축

필터·출력·동시성 중 필요한 옵션 하나를 고른다.

  • 선택: 진단 축 한 가지
  • 범위: 현재 실패에 필요한 범위
  • 세 옵션을 필수 순차 절차로 적용하지 않는다.
결과 대조

변경한 실행 조건과 새로운 근거를 비교한다.

  • 기준: 기본 실행
  • 재실행: 선택 옵션 적용
  • 조건 차이를 기록해야 관측 차이를 코드 변화로 오인하지 않는다.

실패한 테스트만 다시 보려면 이름이나 --ignored로 범위를 줄이고, 그 테스트가 무엇을 출력했는지 보려면 --show-output을, 다른 테스트와 동시에 실행되어 실패하는 것인지 보려면 --test-threads=1을 줍니다. 한 번에 하나만 바꿔야 바꾼 조건과 달라진 결과를 짝지어 볼 수 있으며, 원인을 찾은 뒤에는 기본 실행으로 다시 확인합니다.

정리

  • cargo test의 인수는 -- 앞이면 Cargo가, 뒤면 테스트 실행 파일이 해석합니다.
  • 테스트는 기본으로 병렬 실행되므로 상태를 나누어 쓰지 않게 하고, --test-threads=1로 하나씩 실행할 수 있습니다.
  • 통과한 테스트의 출력은 가로채지므로, 보려면 --show-output을 줍니다.
  • cargo test 이름은 이름에 그 문자열이 든 테스트만 실행하며, 걸러 낸 수는 filtered out으로 나옵니다.
  • #[ignore]를 붙인 테스트는 기본으로 실행되지 않고, --ignored로 그것만, --include-ignored로 모두 실행합니다.

연습 문제

1. 몇 개가 실행될까

add_two의 세 테스트가 있을 때 (가) cargo test two, (나) cargo test hundred, (다) cargo test tests는 각각 몇 개를 실행하고 몇 개를 걸러 내나요?

해설 보기

(가)는 add_two_and_two와 add_three_and_two의 이름에 two가 들어 있으므로 둘을 실행하고 하나를 걸러 냅니다. (나)는 one_hundred만 실행하고 둘을 걸러 냅니다. (다)는 세 테스트가 모두 tests 모듈에 있어 전체 이름이 tests::...이므로 셋을 모두 실행하고 하나도 걸러 내지 않습니다.

2. 가끔만 실패하는 테스트

파일에 쓰고 읽는 테스트 두 개가 가끔만 실패합니다. 무엇을 의심하고, 어떻게 확인하고 고치나요?

해설 보기

두 테스트가 병렬로 실행되며 같은 파일을 함께 써서 서로 덮어쓰는 것을 의심합니다. cargo test -- --test-threads=1로 하나씩 실행했을 때 실패가 사라진다면 동시 실행이 원인일 가능성이 큽니다. 고칠 때는 스레드 수를 늘 1로 두기보다, 테스트마다 다른 파일 이름을 쓰는 식으로 테스트끼리 상태를 나누어 쓰지 않게 합니다.

다음 글 테스트 조직화에서는 코드 안에 두는 유닛 테스트와 tests 폴더에 두는 통합 테스트를 나누어 정리하는 방법을 살펴봅니다.