Files
wehub-resource-sync d48cda4081
CI / Test (ubuntu-latest, Node 18.x, bun) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, npm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, pnpm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, yarn) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 20.x, bun) (push) Failing after 17m13s
CI / Test (ubuntu-latest, Node 20.x, npm) (push) Failing after 18m42s
CI / Test (ubuntu-latest, Node 20.x, pnpm) (push) Failing after 15m0s
CI / Test (ubuntu-latest, Node 20.x, yarn) (push) Failing after 49m44s
CI / Test (ubuntu-latest, Node 22.x, bun) (push) Failing after 51m55s
CI / Test (ubuntu-latest, Node 22.x, pnpm) (push) Failing after 21m57s
CI / Test (ubuntu-latest, Node 22.x, npm) (push) Failing after 37m39s
CI / Test (ubuntu-latest, Node 22.x, yarn) (push) Failing after 34m7s
CI / Validate Components (push) Failing after 37m15s
CI / Python Tests (push) Failing after 10m1s
CI / Security Scan (push) Failing after 10m1s
CI / Lint (push) Failing after 17m12s
CI / Coverage (push) Failing after 20m19s
CI / Test (macos-latest, Node 18.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, yarn) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:55:55 +08:00

4.5 KiB
Raw Permalink Blame History

paths
paths
**/*.rs

Rust テスト

このファイルは common/testing.md を Rust 固有のコンテンツで拡張します。

テストフレームワーク

  • ユニットテストには #[cfg(test)] モジュール内の #[test] を使用する
  • パラメータ化テストとフィクスチャには rstest を使用する
  • プロパティベーステストには proptest を使用する
  • トレイトベースのモッキングには mockall を使用する
  • 非同期テストには #[tokio::test] を使用する

テストの構成

my_crate/
├── src/
│   ├── lib.rs           # #[cfg(test)] モジュール内のユニットテスト
│   ├── auth/
│   │   └── mod.rs       # #[cfg(test)] mod tests { ... }
│   └── orders/
│       └── service.rs   # #[cfg(test)] mod tests { ... }
├── tests/               # 統合テスト(各ファイル = 個別のバイナリ)
│   ├── api_test.rs
│   ├── db_test.rs
│   └── common/          # 共有テストユーティリティ
│       └── mod.rs
└── benches/             # Criterion ベンチマーク
    └── benchmark.rs

ユニットテストは同じファイル内の #[cfg(test)] モジュールに配置する。統合テストは tests/ に配置する。

ユニットテストのパターン

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn creates_user_with_valid_email() {
        let user = User::new("Alice", "alice@example.com").unwrap();
        assert_eq!(user.name, "Alice");
    }

    #[test]
    fn rejects_invalid_email() {
        let result = User::new("Bob", "not-an-email");
        assert!(result.is_err());
        assert!(result.unwrap_err().to_string().contains("invalid email"));
    }
}

パラメータ化テスト

use rstest::rstest;

#[rstest]
#[case("hello", 5)]
#[case("", 0)]
#[case("rust", 4)]
fn test_string_length(#[case] input: &str, #[case] expected: usize) {
    assert_eq!(input.len(), expected);
}

非同期テスト

#[tokio::test]
async fn fetches_data_successfully() {
    let client = TestClient::new().await;
    let result = client.get("/data").await;
    assert!(result.is_ok());
}

mockall によるモッキング

本番コードでトレイトを定義し、テストモジュールでモックを生成する:

// 本番トレイト — 統合テストがインポートできるように pub にする
pub trait UserRepository {
    fn find_by_id(&self, id: u64) -> Option<User>;
}

#[cfg(test)]
mod tests {
    use super::*;
    use mockall::predicate::eq;

    mockall::mock! {
        pub Repo {}
        impl UserRepository for Repo {
            fn find_by_id(&self, id: u64) -> Option<User>;
        }
    }

    #[test]
    fn service_returns_user_when_found() {
        let mut mock = MockRepo::new();
        mock.expect_find_by_id()
            .with(eq(42))
            .times(1)
            .returning(|_| Some(User { id: 42, name: "Alice".into() }));

        let service = UserService::new(Box::new(mock));
        let user = service.get_user(42).unwrap();
        assert_eq!(user.name, "Alice");
    }
}

テストの命名

シナリオを説明する記述的な名前を使用する:

  • creates_user_with_valid_email()
  • rejects_order_when_insufficient_stock()
  • returns_none_when_not_found()

カバレッジ

  • 80%以上の行カバレッジを目標にする
  • カバレッジレポートには cargo-llvm-cov を使用する
  • ビジネスロジックに集中する — 生成コードと FFI バインディングは除外する
cargo llvm-cov                       # サマリー
cargo llvm-cov --html                # HTML レポート
cargo llvm-cov --fail-under-lines 80 # しきい値以下で失敗

テストコマンド

cargo test                       # すべてのテストを実行
cargo test -- --nocapture        # println 出力を表示
cargo test test_name             # パターンに一致するテストを実行
cargo test --lib                 # ユニットテストのみ
cargo test --test api_test       # 特定の統合テスト(tests/api_test.rs
cargo test --doc                 # ドキュメントテストのみ

参考

プロパティベーステスト、フィクスチャ、Criterion によるベンチマークを含む包括的なテストパターンについてはスキル: rust-testing を参照。