redis-rs の cluster のテストが何度やっても通らなくてハマった。ただし、テスト名を指定して一個ずつであれば成功する。該当するテストは以下。
redis-rs/test_cluster.rs at bd8dc731ded564329d74717dfacc5cce748d891f · mitsuhiko/redis-rs · GitHub
このテストは redis server を立ち上げてクラスタを組んでテストを実行している。このとき、各サーバには 7000
番ポートから順番に割り当てている。
redis-rs/cluster.rs at bd8dc731ded564329d74717dfacc5cce748d891f · mitsuhiko/redis-rs · GitHub
そして、デフォルトでは cargo test
1 は複数のテストを並列に実行する。直列な世界に生きているので、ここに気がつくまでに時間がかかってしまった。
テストの実行ファイルでヘルプを表示させると、デフォルトでは並列実装すると書いてある。
$ target/debug/deps/test_cluster-cdbee22b93a5c3e7 --help
Usage: --help [OPTIONS] [FILTER]
Options:
..snip..
--test-threads n_threads
Number of threads used for running tests in parallel
..snip..
By default, all tests are run in parallel. This can be altered with the
--test-threads flag or the RUST_TEST_THREADS environment variable when running
tests (set it to 1).
..snip..
実際、 rustc
側で実装を見ると、デフォルトは CPU コア数であることがわかる。
rust/concurrency.rs at 4ae328bef47dffcbf363e5ae873f419c06a5511d · rust-lang/rust · GitHub
並列で実行すると test_cluster.rs
が落ちるのは明確だ。 7000
番 port が競合しているので、それぞれのテストで使う redis のサーバが建てられなくなってしまう。直列で実行するしかない。
redis-rs のリポジトリには、 Makefile
があり、そこで --test-threads
が指定されている。これはテストの実行ファイルが持つオプションなので cargo
に直接渡すことはできず、 -- --test-threads=1
というように --
の後ろに指定しなければならない。
redis-rs/Makefile at bd8dc731ded564329d74717dfacc5cce748d891f · mitsuhiko/redis-rs · GitHub
ところで、 --test-threads=1
とは別に、 cargo
には --jobs
というオプションがある。
$ cargo test --help
..snip..
-j, --jobs <N> Number of parallel jobs, defaults to # of CPUs
..snip..
ドキュメントは以下にある。紛らわしいが、実行ファイルのビルドに使う CPU 数を指定するオプションらしい。
doc.rust-lang.org
The --jobs argument affects the building of the test executable but does not affect how many threads are used when running the tests.
今回のように「単体テストが逐次実行しかできない」という場合には --jobs
ではなく --test-threads
を使わねばならない。指定先も cargo
に指定するのか単体テストの実行ファイル側に指定するのかも別れていてわかりにくい。
そもそも、「単体テストが逐次実行しかできない」という状況がイケてないなあとは思う。