Rustにおけるテストコードの配置とmain.rsの関数テスト方法

Rustのプロジェクトにおいて、テストコードは主に以下の二つの形式で記述される。

1. ソースファイル内でのモジュール化されたテスト

関数ごとの単体テストを行う場合、実装と同じファイル内に #[cfg(test)] 属性付きのモジュールとして記述することが一般的である。このモジュールでは、親スコープから必要な要素をインポートして利用する。

// src/main.rs
pub fn calculate_sum(x: i32, y: i32) -> i32 {
    x + y
}

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

    #[test]
    fn verify_calculate_sum() {
        assert_eq!(calculate_sum(4, 5), 9);
    }
}

2. 独立したテストファイルによる統合テスト

ライブラリクレートや大規模なアプリケーションでは、tests ディレクトリ配下に個別のテストファイルを作成し、それらを使って統合レベルのテストを構築するのが適切である。これらのテストは公開されたAPIを使用して動作確認を行う。

my_project/
├── src/
│   ├── lib.rs
│   └── main.rs
└── tests/
    └── api_tests.rs

tests/api_tests.rs:

use my_project::calculate_sum;

#[test]
fn integration_check() {
    assert_eq!(calculate_sum(10, 20), 30);
}

main.rs内の関数に対するテストの書き方

  • 関数の可視性を変更する: テスト対象となる関数が main.rs 内にある場合は、pub キーワードを付けて外部からアクセス可能にする必要がある。
  • 同一ファイル内でのテスト記述: 上記のように、main.rs 内部にテストモジュールを設置することで、直接テストを実行できる。
  • ロジックの分離によるテスト容易性向上: 実際の処理部分を lib.rs へ移動させることで、より自然にテスト可能な設計となる。main.rs はエントリポイントとして、その機能を呼び出すだけにするのが望ましい。

再構成後のディレクトリ構造:

src/
├── lib.rs
└── main.rs

src/lib.rs:

pub fn perform_addition(a: i32, b: i32) -> i32 {
    a + b
}

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

    #[test]
    fn addition_works() {
        assert_eq!(perform_addition(7, 8), 15);
    }
}

src/main.rs:

use my_project::perform_addition;

fn main() {
    let output = perform_addition(6, 4);
    println!("計算結果: {}", output);
}

タグ: rust testing cargo test-module integration-test

6月24日 19:28 投稿