Retail AI Adventurers Advent Calendar 2023 の投稿です。
Retail AI は、トライアルカンパニー を軸とした小売におけるお客様の買い物体験の向上を目指す企業です。
この投稿では、本業(SRE)のかたわらで取り組む Backend Tech Stack について書きます。
題材は、「Rust 初心者として、Standard な Test Code の実装方法」についてです。
Rust における Test Code の書き方と Go で一般的な Table Driven Tests1 を使った Test Code について書きます。
tl;dr
- Rust でも Go と同じような Table Driven Tests1 を実装できます。
- Rust では、compile 時に型チェックを行うため、Test Case の設計もより厳密になります。
- Rust では、Unit tests と Integration tests で実装方法が異なります。
- この投稿とは関係ありませんが、同日に別のアドカレ2 に投稿しています。
How to write tests: Rust
Unit tests and Integration tests
Rust では、Unit tests と Integration tests で実装方法が異なります。
Unit tests
logic 内に書きます。
Test Code であることを明示するために、Annotation cfg(test)
を付与します。
以下は、Official Docs より。
Unit Tests
The purpose of unit tests is to test each unit of code in isolation from the rest of the code to quickly pinpoint where code is and isn’t working as expected. You’ll put unit tests in the src directory in each file with the code that they’re testing. The convention is to create a module named tests in each file to contain the test functions and to annotate the module with cfg(test).ユニットテストの目的は、コードの各ユニットを他のコードから切り離してテストし、コードが期待通りに動いているところと動いていないところを素早く突き止めることです。ユニットテストは、テストするコードのある各ファイルの src ディレクトリに置きます。各ファイルの中にtestsという名前のモジュールを作成し、テスト関数を格納し、cfg(test)というアノテーションをつけるのが慣例です。
Integration tests
tests
directory に書きます。
以下は、Official Docs より。
Integration Tests
In Rust, integration tests are entirely external to your library. They use your library in the same way any other code would, which means they can only call functions that are part of your library’s public API. Their purpose is to test whether many parts of your library work together correctly. Units of code that work correctly on their own could have problems when integrated, so test coverage of the integrated code is important as well. To create integration tests, you first need a tests directory.Rustでは、統合テストは完全にライブラリの外部です。つまり、ライブラリのパブリックAPIの一部である関数のみを呼び出すことができます。統合テストの目的は、ライブラリの多くの部分が正しく連携して動作するかどうかをテストすることです。単体では正しく動作するコードも、統合すると問題が発生する可能性があります。統合テストを作成するには、まず tests ディレクトリが必要です。
adder
├── Cargo.lock
├── Cargo.toml
├── src
│ └── lib.rs
└── tests # Here
└── integration_test.rs # Here
Unit tests について、詳しく見ていきます。
まず、Unit tests は、cfg(test)
を付与するのが慣例です。
以下、sample code です。
Unit Tests を実行します。cargo test
vscode ➜ /workspaces/rust-api-samples/main (main) $ cargo test
Compiling main v0.1.0 (/workspaces/rust-api-samples/main)
Finished test [unoptimized + debuginfo] target(s) in 1m 33s
Running unittests src/main.rs (target/debug/deps/main-794ccb24f64c7f92)
running 3 tests
test routes::tests::err_api_response_users ... ok
test routes::tests::test_api_response_users ... ok
test routes::users_service_tests::test_fetch_users ... ok # Here
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
vscode ➜ /workspaces/rust-api-samples/main (main) $
Table Driven Tests in Rust
Table Driven Tests1 を Rust で実践するとどうなるか。
これは、諸元があるわけではなく、個人的に考えた実装方法です。
Vector 型の配列にテストケースを用意します。
vscode ➜ /workspaces/rust-api-samples/main (main) $ cargo test
Compiling main v0.1.0 (/workspaces/rust-api-samples/main)
Finished test [unoptimized + debuginfo] target(s) in 1m 36s
Running unittests src/main.rs (target/debug/deps/main-794ccb24f64c7f92)
running 4 tests
test routes::tests::err_api_response_users ... ok
test routes::tests::test_api_response_users ... ok
test routes::users_service_tests::test_fetch_users ... ok
test routes::users_service_tests::tdt_fetch_users ... ok # Here
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.28s
vscode ➜ /workspaces/rust-api-samples/main (main) $
How to write tests: Go
Go の test は、言わずと知れた Table Driven Tests
1 です。
mock3 として、database を先に用意します。
setupMockDB
で初期データを投入するのもあり。もしくは、db ファイルをコミットしておきます。
今回実装した Code は、以下です。
簡単ですが、Test Code については以上です。
この投稿をみて何か得られた方は、いいね ❤️ をお願いします。
それでは、次回のアドカレでお会いしましょう。👋
BTW
この投稿とは関係ありませんが、同日に別のアドカレに投稿しています。
CCoEクリスマス!クラウド技術を活用して組織をカイゼンした事例を投稿しよう! by KINTOテクノロジーズ Advent Calendar 2023
2023年11月に GA になった合成モニターについて書いています。
もしよろしければ、こちらも見ていただけると嬉しいです。