テストの実行
x を使用してテストコレクション全体を実行できます。
ただし、ローカル開発中に 全体の テストコレクションを実行したいことはほとんどありません。
非常に長い時間がかかるためです。
ローカル開発については、テストのサブセットを実行する方法に関する後続のサブセクションを参照してください。
単に ./x test を実行すると、ステージ 1 コンパイラをビルドしてから、テストスイート全体を実行します。
これには tests/ だけでなく、library/、compiler/、
src/tools/ パッケージのテストなども含まれます。
通常は、変更が実行されると想定されるテストスイートのサブセット(またはそれよりさらに小さいテストの集合)のみを実行したいはずです。 PR CI はテストコレクションのサブセットを実行し、merge queue 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"))を入力し、 return に続いて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
ステージ 1 コンパイラを使用して標準ライブラリでテストを実行する
./x test --stage 1 library/std
実行したいテストスイートを列挙することで、 まったく変更していないコンポーネントのテストを実行せずに済みます。
bors は完全なステージ 2 ビルドでのみテストを実行することに注意してください。 そのため、テストはステージ 1 でも 通常は 問題なく動作しますが、いくつかの制限があります。
ステージ 2 コンパイラを使用してすべてのテストを実行する
./x test --stage 2
コンパイラ/ライブラリでユニットテストを実行する
次のようにして、特定のファイルでユニットテストを実行したい場合があります。
./x test compiler/rustc_data_structures/src/thin_vec/tests.rs
しかし残念ながら、それは不可能です。 代わりに次を呼び出す必要があります。
./x test compiler/rustc_data_structures/ --test-args thin_vec
個別のテストを実行する
よく行われるもう 1 つのことは、個別のテストを実行することです。
多くの場合、それは修正しようとしているテストです。
前述のように、これを行うには完全なファイルパスを渡すか、代わりに --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 オプションを使用して行うことができ、
テストのビルド時にコンパイラへ追加の引数を渡せます。
参照ファイルの編集と更新
コンパイラの出力を意図的に変更した場合、または新しいテストを作成している場合は、
テストサブコマンドに --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 test harness の--quietオプションと同等です。- 環境変数
RUST_TEST_THREADSには、テストに使用する並行スレッド数を設定できます。
--pass $mode を渡す
pass の UI テストには現在、check-pass、build-pass、run-pass の 3 つのモードがあります。
--pass $mode が渡されると、テストファイルにディレクティブ //@ no-pass-override が存在しない限り、
これらのテストは指定された $mode で強制的に実行されます。
たとえば、tests/ui 内のすべてのテストを check-pass として実行できます。
./x test tests/ui --pass check
--pass $mode を渡すことで、テスト時間を短縮できます。
各モードについては、pass/fail 期待値の制御を参照してください。
異なる「compare modes」でテストを実行する
UI テストでは、コンパイラが特定の「モード」にあるかどうかによって、出力が異なる場合があります。
たとえば、Polonius モードを使用している場合、テスト foo.rs はまず期待される出力を foo.polonius.stderr から探し、見つからなければ通常の foo.stderr にフォールバックします。
以下は、Polonius モードで UI テストスイートを実行します:
./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 テスト)は、リモートマシン上で一度も実行されないまま失敗する場合があります。
remote-test-server に x コマンドから到達できない場合に備えて、デフォルトのタイムアウトは 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 を使用できることです。
次のような方法で動作するはずです:
# iOS シミュレータ向けにテストサーバーをビルドします:
./x build src/tools/remote-test-server --target aarch64-apple-ios-sim
# 既にシミュレータインスタンスを開いている場合は、以下からデバイス UUID をコピーします:
xcrun simctl list devices booted
UDID=01234567-89AB-CDEF-0123-456789ABCDEF
# または、新しいシミュレータインスタンスを作成して起動します:
xcrun simctl list runtimes
xcrun simctl list devicetypes
UDID=$(xcrun simctl create $CHOSEN_DEVICE_TYPE $CHOSEN_RUNTIME)
xcrun simctl boot $UDID
# 詳細は https://nshipster.com/simctl/ を参照してください。
# ポート 12345 でランナーを起動します:
xcrun simctl spawn $UDID ./build/host/stage2-tools/aarch64-apple-ios-sim/release/remote-test-server -v --bind 127.0.0.1:12345
# 新しいターミナルで、ランナー経由でテストを実行します:
export TEST_DEVICE_ADDR="127.0.0.1:12345"
./x test --host='' --target aarch64-apple-ios-sim --skip tests/debuginfo
# FIXME(madsmtm): debuginfo テストが動作するようにします(`.dSYM` フォルダをターゲットにコピーする必要があるかもしれません)。
wasi (wasm32-wasip1) でテストを実行する
一部のテストは wasm ターゲット固有です。
これらのテストを実行するには、x test に --target wasm32-wasip1 を渡す必要があります。
さらに、wasi sdk が必要です。
コンピュータ上に sysroot を取得するには、wasi sdk repository のインストール手順に従ってください。
wasm32-wasip1 target support page には、sdk がビルドできなければならない最小バージョンが指定されています。
時間がかかり、非常に気になる c++ の警告を大量に出す cmake コマンドがいくつかあります…
その後、bootstrap.toml で次のように sysroot を指定します:
[target.wasm32-wasip1]
wasi-root = "<wasi-sdk location>/build/sysroot/install/share/wasi-sysroot"
私の場合は rust フォルダーの隣に git clone したので、../wasi-sdk/build/.... でした。
これで、テストはそのまま実行できるはずで、他に何も設定する必要はありません。