rust-testing について
Rust 開発者向けのテスト支援スキルです。ユニット、統合、ドキュメント、非同期、プロパティベースのテスト例と実行コマンドを扱います。
主な機能
- 01ユニット・統合テストのパターン
- 02ドキュメントテストの例
- 03tokio による非同期テスト
- 04proptest によるプロパティテスト
- 05カバレッジ用コマンド
活用シーン
- 01Rust モジュールへのユニットテスト追加
- 02統合テストによる API の検証
- 03非同期処理とタイムアウトの確認
- 04テストカバレッジの測定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ autumnsgrove/ lattice --skill rust-testingインストール後、Claude Code で/rust-testingを入力して読み込まれたか確認します。
詳細
Rust のテストスキル
有効化するタイミング
次の場合にこのスキルを有効化します:
- Rust のユニットテストを作成するとき
- 統合テストを作成するとき
- ドキュメントテストを扱うとき
- プロパティベーステストを設定するとき
- ベンチマークを実行するとき
クイックコマンド
# Run all tests
cargo test
# With output
cargo test -- --nocapture
# Run specific test
cargo test test_user_create
# Run tests in module
cargo test auth::
# Run ignored tests
cargo test -- --ignored
# Doc tests only
cargo test --doc
# Integration tests only
cargo test --test integration
ユニットテスト(同じファイル内)
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_add_negative() {
assert_eq!(add(-1, -1), -2);
}
}
テスト属性
#[test]
fn regular_test() { }
#[test]
#[ignore]
fn slow_test() { } // Skip unless --ignored
#[test]
#[should_panic]
fn test_panic() {
panic!("This should panic");
}
#[test]
#[should_panic(expected = "specific message")]
fn test_panic_message() {
panic!("specific message here");
}
#[test]
fn test_with_result() -> Result<(), String> {
let result = some_operation()?;
assert_eq!(result, expected);
Ok(())
}
アサーション
// Basic
assert_eq!(1 + 1, 2);
assert_ne!(1 + 1, 3);
assert!(true);
// With messages
assert_eq!(result, expected, "values should match: got {}", result);
// Pattern matching
assert!(matches!(value, Pattern::Variant(_)));
// Option/Result
assert!(some_option.is_some());
assert!(some_result.is_ok());
統合テスト
// tests/api_integration.rs
use my_crate::{Config, Server};
#[test]
fn test_server_startup() {
let config = Config::default();
let server = Server::new(config);
assert!(server.start().is_ok());
}
ディレクトリ構成
project/
├── Cargo.toml
├── src/
│ ├── lib.rs # Unit tests in #[cfg(test)]
│ └── user.rs # Module with inline tests
└── tests/ # Integration tests
├── common/
│ └── mod.rs # Shared utilities
└── api_test.rs
トレイトを使ったモック
pub trait UserRepository {
fn find_by_id(&self, id: u64) -> Option<User>;
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
struct MockUserRepo {
users: HashMap<u64, User>,
}
impl UserRepository for MockUserRepo {
fn find_by_id(&self, id: u64) -> Option<User> {
self.users.get(&id).cloned()
}
}
#[test]
fn test_user_service() {
let mut users = HashMap::new();
users.insert(1, User { id: 1, email: "[email protected]".into() });
let repo = MockUserRepo { users };
let service = UserService::new(Box::new(repo));
let user = service.get_user(1).unwrap();
assert_eq!(user.email, "[email protected]");
}
}
非同期テスト(tokio)
#[tokio::test]
async fn test_async_operation() {
let result = fetch_data().await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_with_timeout() {
let result = tokio::time::timeout(
Duration::from_secs(5),
slow_operation()
).await;
assert!(result.is_ok());
}
ドキュメントテスト
/// Adds two numbers together.
///
/// # Examples
///
/// ```
/// use my_crate::add;
/// let result = add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
プロパティベーステスト(proptest)
use proptest::prelude::*;
proptest! {
#[test]
fn test_add_commutative(a: i32, b: i32) {
prop_assert_eq!(add(a, b), add(b, a));
}
}
カバレッジ
# Using cargo-tarpaulin
cargo install cargo-tarpaulin
cargo tarpaulin --out Html
# Using cargo-llvm-cov
cargo install cargo-llvm-cov
cargo llvm-cov --html
関連リソース
ベンチマークの criterion による実行、セットアップ/ティアダウンのパターン、Mockall クレートの使い方、CI の設定など、詳細については AgentUsage/testing_rust.md を参照してください。
コメント
Markdown 対応