Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

테스트 실행하기

x를 사용하여 전체 테스트 모음을 실행할 수 있습니다. 하지만 전체 테스트 모음을 실행하면 시간이 매우 오래 걸리므로 로컬 개발 중에는 거의 필요하지 않다는 점에 유의하십시오. 로컬에서 개발할 때 테스트의 일부만 실행하는 방법은 뒤에 나오는 하위 절을 참고하십시오.

./x test만 실행하면 stage 1 컴파일러를 빌드한 다음 전체 테스트 스위트를 실행합니다. 여기에는 tests/뿐만 아니라 library/, compiler/, src/tools/ 패키지 테스트 등도 포함됩니다.

보통은 변경 사항을 검증할 것으로 예상되는 테스트 스위트의 일부(또는 그보다 더 작은 테스트 집합)만 실행하면 됩니다. PR CI는 테스트 모음의 일부를 실행하며, 병합 큐 CI는 테스트 모음 전체를 실행합니다.

./x test

테스트 결과는 캐시되며, 이전에 성공한 테스트는 테스트 중에 ignored 처리됩니다. 각 테스트의 stdout/stderr 내용과 타임스탬프 파일은 해당 <target-tuple>에 대한 build/<target-tuple>/test/ 아래에서 찾을 수 있습니다. 테스트를 강제로 다시 실행하려면(예: 테스트 러너가 변경 사항을 감지하지 못한 경우) --force-rerun CLI 옵션을 사용할 수 있습니다.

외부 의존성 요구 사항에 관한 참고 사항

일부 테스트 스위트는 외부 의존성이 필요할 수 있습니다. 특히 debuginfo 테스트가 그렇습니다. 일부 debuginfo 테스트에는 Python이 활성화된 gdb가 필요합니다. gdb 안에서 python 명령을 사용하면 설치된 gdb가 Python을 지원하는지 테스트할 수 있습니다. 명령을 실행한 뒤 Python 코드(예: print("hi"))를 입력하고 엔터 키를 누른 다음 CTRL+D를 누르면 코드가 실행됩니다. gdb를 소스에서 빌드하는 경우 --with-python=<path-to-python-binary> 옵션으로 구성해야 합니다.

테스트 스위트의 일부 실행하기

특정 PR 작업을 할 때는 보통 더 작은 테스트 집합을 실행하게 됩니다. 예를 들어 rustc를 수정한 뒤 전반적으로 올바르게 동작하는지 확인하는 데 쓸 수 있는 좋은 “스모크 테스트“는 ui 테스트 스위트(tests/ui)를 실행하는 것입니다:

./x test tests/ui

물론 테스트 스위트의 선택은 다소 임의적이며, 수행 중인 작업에 맞지 않을 수도 있습니다. 예를 들어 debuginfo 관련 작업을 하고 있다면 debuginfo 테스트 스위트를 사용하는 편이 더 나을 수 있습니다:

./x test tests/debuginfo

특정 테스트 스위트에서 테스트의 특정 하위 디렉터리만 테스트하면 되는 경우, 해당 디렉터리를 ./x test에 필터로 전달할 수 있습니다:

./x test tests/ui/const-generics

MSYS2 관련 참고 사항

MSYS2에서는 경로가 이상하게 처리되는 것으로 보이며, ./x test가 tests/ui/const-generics와 tests\ui\const-generics를 모두 인식하지 못합니다. 이 경우 ./x test ui --test-args="tests/ui/const-generics"와 같은 방식으로 우회할 수 있습니다.

마찬가지로 경로를 전달하여 단일 파일을 테스트할 수 있습니다:

./x test tests/ui/const-generics/const-test.rs

x는 아직 경로를 전달하여 단일 도구 테스트를 실행하는 기능을 지원하지 않습니다. 아래에서 설명하는 것처럼 --test-args 인자를 사용해야 합니다.

./x test src/tools/miri --test-args tests/fail/uninit/padding-enum.rs

tidy 스크립트만 실행하기

./x test tidy

표준 라이브러리 테스트 실행하기

./x test --stage 0 library/std

이 명령은 std에 대해서만 테스트를 실행한다는 점에 유의하십시오. core나 다른 크레이트를 테스트하려면 해당 크레이트를 명시적으로 지정해야 합니다.

표준 라이브러리에 대해 tidy 스크립트와 테스트를 실행합니다

./x test --stage 0 tidy library/std

stage 1 컴파일러를 사용하여 표준 라이브러리에 대한 테스트를 실행합니다

./x test --stage 1 library/std

실행할 테스트 스위트를 나열하면 전혀 변경하지 않은 구성 요소의 테스트까지 실행하지 않아도 됩니다.

bors는 전체 stage 2 빌드로만 테스트를 실행한다는 점에 유의하십시오. 따라서 테스트가 stage 1에서도 대개 잘 동작하기는 하지만 몇 가지 제약이 있습니다.

stage 2 컴파일러를 사용하여 모든 테스트를 실행합니다

./x test --stage 2
이 작업을 직접 해야 하는 경우는 거의 없습니다. CI가 이 테스트들을 대신 실행해 줍니다.

컴파일러/라이브러리에 대한 단위 테스트를 실행합니다

다음과 같이 특정 파일에 대해 단위 테스트를 실행하고 싶을 수도 있습니다:

./x test compiler/rustc_data_structures/src/thin_vec/tests.rs

하지만 안타깝게도 그렇게 할 수는 없습니다. 대신 다음을 실행하십시오:

./x test compiler/rustc_data_structures/ --test-args thin_vec

개별 테스트 실행하기

사람들이 흔히 하려는 또 다른 작업은 개별 테스트, 대개 자신이 고치려는 테스트를 실행하는 것입니다. 앞서 언급했듯이 이를 위해 전체 파일 경로를 전달할 수도 있고, --test-args 옵션과 함께 x를 실행할 수도 있습니다:

./x test tests/ui --test-args issue-1234

내부적으로 테스트 러너는 표준 Rust 테스트 러너(#[test]를 사용할 때와 같은 러너)를 호출하므로, 이 명령은 결국 이름에 “issue-1234“가 포함된 테스트만 걸러 내게 됩니다. 따라서 --test-args는 서로 관련된 여러 테스트를 한꺼번에 실행하기에 좋은 방법입니다.

테스트를 실행할 때 rustc에 인자 전달하기

RUSTFLAGS를 사용하지 않고 특정 컴파일러 인자로 일부 테스트를 실행하는 것이 유용할 때가 있습니다(예를 들어 불안정 기능을 개발하는 중에 -Z 플래그를 사용하는 경우).

이는 ./x test의 --compiletest-rustc-args 옵션으로 할 수 있으며, 이 옵션은 테스트를 빌드할 때 컴파일러에 추가 인자를 전달합니다.

참조 파일 편집 및 갱신하기

컴파일러의 출력을 의도적으로 변경했거나 새 테스트를 작성하는 중이라면 test 하위 명령에 --bless를 전달할 수 있습니다.

예를 들어 tests/ui의 일부 테스트가 실패한다면 다음 명령을 실행할 수 있습니다:

./x test tests/ui --bless

이 명령은 모든 test/ui 테스트의 .stderr, .stdout, .fixed 파일을 자동으로 조정합니다. 물론 --bless 플래그 없이 테스트를 실행할 때와 마찬가지로 --test-args your_test_name 플래그를 사용하여 특정 테스트만 대상으로 지정할 수도 있습니다.

테스트 실행 구성하기

테스트 실행에는 몇 가지 옵션이 있습니다:

  • bootstrap.toml에는 rust.verbose-tests 옵션이 있습니다. false이면 각 테스트마다 점 하나를 출력합니다(기본값). true이면 모든 테스트의 이름을 출력합니다. 이는 Rust 테스트 하네스의 --quiet 옵션에 해당합니다.
  • 환경 변수 RUST_TEST_THREADS에 테스트에 사용할 동시 스레드 수를 설정할 수 있습니다.

--pass $mode 전달하기

Pass UI 테스트에는 이제 check-pass, build-pass, run-pass의 세 가지 모드가 있습니다. --pass $mode를 전달하면, 테스트 파일에 //@ no-pass-override 지시문이 없는 한 이 테스트들은 주어진 $mode로 강제 실행됩니다. 예를 들어, tests/ui에 있는 모든 테스트를 check-pass로 실행할 수 있습니다:

./x test tests/ui --pass check

--pass $mode를 전달하면 테스트 시간을 줄일 수 있습니다. 각 모드에 대해서는 통과/실패 기대치 제어하기를 참조하십시오.

다른 “비교 모드“로 테스트 실행하기

UI 테스트는 컴파일러가 어떤 “모드“에 있는지에 따라 다른 출력을 낼 수 있습니다. 예를 들어, Polonius 모드를 사용할 때 테스트 foo.rs는 먼저 foo.polonius.stderr에서 기대 출력을 찾고, 찾지 못하면 일반적인 foo.stderr를 대신 사용합니다. 다음 명령은 UI 테스트 스위트를 Polonius 모드로 실행합니다:

./x test tests/ui --compare-mode=polonius

자세한 내용은 비교 모드를 참조하십시오.

테스트 수동으로 실행하기

때로는 테스트를 그냥 직접 실행하는 편이 더 쉽고 빠릅니다. 대부분의 테스트는 단순한 .rs 파일이므로, rustup 툴체인을 만든 후에 다음과 같이 할 수 있습니다:

rustc +stage1 tests/ui/issue-1234.rs

이 방법은 훨씬 빠르지만 항상 동작하지는 않습니다. 예를 들어, 일부 테스트에는 특정 컴파일러 플래그를 지정하거나 다른 크레이트에 의존하는 지시문이 포함되어 있으며, 이러한 옵션 없이는 동일하게 실행되지 않을 수 있습니다.

원격 머신에서 테스트 실행하기

테스트는 원격 머신에서 실행할 수도 있습니다(예: 다른 아키텍처용 빌드를 테스트하는 경우). 이는 빌드 머신에서 remote-test-client를 사용하여 원격 머신에서 실행 중인 remote-test-server로 테스트 프로그램을 보내는 방식으로 이루어집니다. remote-test-server는 테스트 프로그램을 실행하고 그 결과를 빌드 머신으로 다시 보냅니다. remote-test-server는 인증되지 않은 원격 코드 실행을 제공하므로 어디에서 사용하는지 주의하십시오.

이를 위해 먼저 원격 머신용 remote-test-server를 빌드하십시오(RISC-V를 예로 사용합니다):

./x build src/tools/remote-test-server --target riscv64gc-unknown-linux-gnu

바이너리는 ./build/host/stage2-tools/$TARGET_ARCH/release/remote-test-server에 생성됩니다. 이것을 원격 머신으로 복사하십시오.

원격 머신에서 --bind 0.0.0.0:12345 플래그(그리고 선택적으로 --verbose 플래그)와 함께 remote-test-server를 실행하십시오. 출력은 다음과 같아야 합니다:

$ ./remote-test-server --verbose --bind 0.0.0.0:12345
starting test server
listening on 0.0.0.0:12345!

서버를 0.0.0.0에 바인딩하면 여러분의 머신에 접근할 수 있는 모든 호스트가 여러분의 머신에서 임의의 코드를 실행할 수 있게 된다는 점에 유의하십시오. 포트 12345에 대한 외부 접근을 차단(블록)하도록 방화벽을 설정하거나, 바인딩할 때 더 제한적인 IP 주소를 사용할 것을 강력히 권장합니다.

remote-test-server에 연결하여 ping\n을 보내면 서버가 동작하는지 테스트할 수 있습니다. pong으로 응답해야 합니다:

$ nc $REMOTE_IP 12345
ping
pong

원격 러너를 사용하여 테스트를 실행하려면 TEST_DEVICE_ADDR 환경 변수를 설정한 다음 평소처럼 x를 사용하십시오. 예를 들어, IP 주소가 1.2.3.4인 RISC-V 머신에서 ui 테스트를 실행하려면 다음을 사용하십시오

export TEST_DEVICE_ADDR="1.2.3.4:12345"
./x test tests/ui --target riscv64gc-unknown-linux-gnu

remote-test-server를 verbose 플래그와 함께 실행했다면, 테스트 머신의 출력은 대략 다음과 같을 수 있습니다

[...]
run "/tmp/work/test1007/a"
run "/tmp/work/test1008/a"
run "/tmp/work/test1009/a"
run "/tmp/work/test1010/a"
run "/tmp/work/test1011/a"
run "/tmp/work/test1012/a"
run "/tmp/work/test1013/a"
run "/tmp/work/test1014/a"
run "/tmp/work/test1015/a"
run "/tmp/work/test1016/a"
run "/tmp/work/test1017/a"
run "/tmp/work/test1018/a"
[...]

테스트는 원격 머신이 아니라 x를 실행하는 머신에서 빌드됩니다. 예기치 않게 빌드에 실패하는 테스트(또는 잘못된 빌드 출력을 내는 ui 테스트)는 원격 머신에서 한 번도 실행되지 않은 채 실패할 수 있습니다.

x 명령이 remote-test-server에 연결하지 못하는 경우를 대비하여 기본 타임아웃이 30분으로 설정되어 있습니다. 이 타임아웃은 TEST_DEVICE_CONNECT_TIMEOUT_SECONDS 환경 변수로 변경할 수 있습니다.

에뮬레이터에서 테스트하기

쉽게 구할 수 없는 아키텍처의 경우, 일부 플랫폼은 에뮬레이터를 통해 테스트합니다. 표준 라이브러리가 잘 지원되고 호스트 운영 체제가 TCP/IP 네트워킹을 지원하는 아키텍처라면, 위에서 설명한 원격 머신 테스트 방법을 참고하십시오(이 경우 원격 머신은 에뮬레이션된 머신입니다).

에뮬레이터 안에서 테스트 실행을 조율하는 도구 모음도 있습니다. arm-android나 arm-unknown-linux-gnueabihf 같은 플랫폼은 GitHub Actions에서 에뮬레이션 환경으로 테스트를 자동 실행하도록 구성되어 있습니다. 아래에서는 대상의 테스트가 에뮬레이션 환경에서 어떻게 실행되는지 살펴봅니다.

armhf-gnu용 Docker 이미지에는 ARM CPU 아키텍처를 에뮬레이션하는 QEMU가 포함되어 있습니다. Rust 트리에는 테스트 프로그램과 라이브러리를 에뮬레이터로 보내고, 에뮬레이터 안에서 테스트를 실행하고, 그 결과를 읽어 오는 프로그램인 remote-test-client와 remote-test-server 도구가 포함되어 있습니다. Docker 이미지는 remote-test-server를 실행하도록 구성되어 있으며, 빌드 도구는 remote-test-client로 서버와 통신하여 테스트 실행을 조율합니다(src/bootstrap/src/core/build_steps/test.rs 참고).

iOS/tvOS/watchOS/visionOS 시뮬레이터에서 실행할 때도 마찬가지로 시뮬레이터를 “원격” 머신으로 취급할 수 있습니다. 흥미로운 점은 시뮬레이터 인스턴스와 호스트 macOS가 네트워크를 공유하므로 로컬 루프백 주소 127.0.0.1을 사용할 수 있다는 것입니다. 다음과 같이 하면 동작할 것입니다:

# Build the test server for the iOS simulator:
./x build src/tools/remote-test-server --target aarch64-apple-ios-sim

# If you already have a simulator instance open, copy the device UUID from:
xcrun simctl list devices booted
UDID=01234567-89AB-CDEF-0123-456789ABCDEF

# Alternatively, create and boot a new simulator instance:
xcrun simctl list runtimes
xcrun simctl list devicetypes
UDID=$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME)
xcrun simctl boot $UDID
# See https://nshipster.com/simctl/ for details.

# Spawn the runner on port 12345:
xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345

# In a new terminal, run tests via the runner:
export TEST_DEVICE_ADDR="127.0.0.1:12345"
./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo
# FIXME(madsmtm): Allow debuginfo tests to work (maybe needs `.dSYM` folder to be copied to the target?).

wasi(wasm32-wasip1)에서 테스트하기

일부 테스트는 wasm 대상 전용입니다. 이 테스트를 실행하려면 x test에 --target wasm32-wasip1을 전달해야 합니다. 또한 wasi sdk가 필요합니다. wasi sdk 저장소의 설치 안내를 따라 컴퓨터에 sysroot를 마련하십시오. wasm32-wasip1 대상 지원 페이지에 sdk가 빌드할 수 있어야 하는 최소 버전이 명시되어 있습니다. cmake 명령 몇 개를 실행하면 시간이 꽤 걸리고, 매우 걱정스러워 보이는 c++ 경고가 잔뜩 출력됩니다… 그런 다음 bootstrap.toml에서 다음과 같이 sysroot를 지정하십시오:

[target.wasm32-wasip1]
wasi-root = "<wasi-sdk location>/build/sysroot/install/share/wasi-sysroot"

저는 rust 폴더 옆에 git clone을 했기 때문에 경로가 ../wasi-sdk/build/....였습니다. 이제 다른 설정 없이 테스트가 바로 실행될 것입니다.