Rustでテスト駆動開発(TDD)を導入する手順を徹底解説

Rustにおいて、テスト駆動開発(TDD)を導入することは、コードの品質を向上させ、バグの発生を抑えながら開発を進めるための効果的な手法です。TDDは、「テストを書いてからコードを書く」というプロセスを繰り返すことで、プログラムの振る舞いを明確に定義し、リファクタリングや変更がしやすい設計を実現します。

Rustは、安全性とパフォーマンスに優れたシステムプログラミング言語であり、強力な型システムとコンパイラによって、エラーを早期に検出することが可能です。Rustのテスト機能は標準ライブラリに組み込まれており、簡単にテストを追加・実行することができます。

本記事では、RustにおけるTDDの基本概念から具体的な手順、実践例までを詳細に解説します。TDDを取り入れることで、Rustプロジェクトの堅牢性を高め、バグの少ない効率的な開発が可能になります。

目次
  1. テスト駆動開発(TDD)とは何か
    1. TDDの基本サイクル
    2. TDDの利点
    3. TDDと従来の開発手法の違い
  2. RustでのTDDの利点
    1. 1. コンパイル時の安全性
    2. 2. 安心したリファクタリング
    3. 3. ドキュメンテーションの向上
    4. 4. パフォーマンスの最適化
    5. 5. エラー処理の強化
    6. 6. 信頼性の高い並行処理
  3. 環境設定とテストツール
    1. Rustのインストールとセットアップ
    2. プロジェクトの作成
    3. Rustの標準テストフレームワーク
    4. 人気のある追加ツール
    5. エディタとIDEのセットアップ
  4. 基本的なテストの書き方
    1. テスト関数の作成
    2. テストの実行
    3. 異なる種類のアサーション
    4. テストの失敗例
    5. テストの非同期処理
    6. 複数のテストをグループ化
  5. TDDのサイクル:レッド・グリーン・リファクタリング
    1. 1. レッド(Red) – 失敗するテストの作成
    2. 2. グリーン(Green) – テストを通すための最小限のコードを書く
    3. 3. リファクタリング(Refactor) – コードの改善
    4. TDDサイクルのポイント
  6. モジュールとクレートのテスト
    1. モジュールのテスト
    2. サブモジュールのテスト
    3. 外部クレートのテスト
    4. ドキュメントテスト
    5. テストのベストプラクティス
  7. 失敗しやすいポイントと対処法
    1. 1. 型エラーによるテスト失敗
    2. 2. 値の比較ミスによるテスト失敗
    3. 3. 非同期テストの落とし穴
    4. 4. パニックによるテスト失敗
    5. 5. モジュールのパス指定ミス
    6. 6. テストが実行されない問題
    7. まとめ
  8. 実践例:簡単なRustプロジェクトでのTDD
    1. 1. プロジェクトの作成
    2. 2. レッド(Red):失敗するテストの作成
    3. 3. グリーン(Green):テストを通すための最小限のコードを書く
    4. 4. リファクタリング(Refactor):コードの改善
    5. 5. 復号化機能の追加(TDDのサイクルを繰り返す)
    6. 6. 追加テスト:大文字や非アルファベット文字の対応
    7. まとめ
  9. まとめ

テスト駆動開発(TDD)とは何か


テスト駆動開発(Test-Driven Development、TDD)とは、ソフトウェアの開発手法の一つで、テストを先に書いてからコードを実装するというアプローチです。TDDでは「レッド(失敗するテストの作成)→グリーン(テストを通すためのコードを書く)→リファクタリング(コードの改善)」というサイクルを繰り返し、機能を小さなステップで追加していきます。

TDDの基本サイクル


TDDは次の3つのステップで進められます。

  1. レッド(Red)
    まず、失敗するテストを作成します。これにより、機能がまだ実装されていないことが明確になります。
  2. グリーン(Green)
    テストを通すために、最小限のコードを書きます。この時点で、テストが成功する状態にします。
  3. リファクタリング(Refactor)
    コードが正しく動作することを確認したら、コードの品質を向上させるためにリファクタリングを行います。

TDDの利点

  • バグの早期発見:テストを先に書くため、問題が早期に発見できます。
  • リファクタリングの安全性:テストがあるため、安心してコードの改善ができます。
  • ドキュメンテーションの役割:テストがコードの動作仕様を明示し、新しい開発者にも理解しやすくなります。

TDDと従来の開発手法の違い


従来の開発手法では、コードを書いた後でテストを作成するため、後付けのテストが不完全になりがちです。一方、TDDでは先にテストを書くため、常にコードがテストでカバーされ、設計のミスや抜け漏れを防ぐことができます。

RustでTDDを導入することで、システム全体の安全性を確保しつつ、効率的に開発を進めることができます。

RustでのTDDの利点


Rustはその特性から、テスト駆動開発(TDD)を導入する際に多くの利点があります。安全性やパフォーマンスを重視したRustにTDDを組み合わせることで、より堅牢なコードが作成できます。

1. コンパイル時の安全性


Rustの強力な型システムと所有権モデルにより、コンパイル時に多くのエラーが検出されます。TDDを組み合わせることで、コンパイルエラーとテストエラーの両方を早期に発見し、バグの少ないコードを開発できます。

2. 安心したリファクタリング


TDDではテストを先に書くため、リファクタリング時にコードが壊れていないかすぐに確認できます。Rustのテストフレームワークと合わせることで、変更が安全に行えるため、コードの品質向上が容易です。

3. ドキュメンテーションの向上


テストはコードの仕様書の役割も果たします。Rustのテストコードがあることで、新しい開発者が関数やモジュールの使い方を理解しやすくなります。

4. パフォーマンスの最適化


Rustではパフォーマンスを維持しつつ、安全なコードを書けます。TDDを使うことで、パフォーマンス最適化の際に意図しない動作変更を防ぎ、性能と正確性を両立できます。

5. エラー処理の強化


RustのResult型やOption型を活用することで、エラー処理を明確に行えます。TDDを導入することで、エラー処理が期待通りに動作しているかを検証し、例外的なケースに強いコードを書けます。

6. 信頼性の高い並行処理


Rustは安全な並行処理をサポートしています。TDDで並行処理のテストをしっかり行うことで、データ競合や不正なメモリ操作を防ぎ、信頼性の高いプログラムを構築できます。

TDDとRustの特性を活かすことで、バグが少なく、保守性・安全性・パフォーマンスに優れたシステムを効率的に開発できます。

環境設定とテストツール


Rustでテスト駆動開発(TDD)を始めるためには、適切な開発環境の設定とテストツールの理解が必要です。以下では、Rustの環境構築から、標準テストフレームワークや追加ツールについて解説します。

Rustのインストールとセットアップ


Rustをインストールするには、公式のrustupツールを使用します。ターミナルで以下のコマンドを実行します。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

インストールが完了したら、Rustのバージョンを確認します。

rustc --version

プロジェクトの作成


新しいRustプロジェクトを作成するには、cargoコマンドを使います。

cargo new my_tdd_project
cd my_tdd_project

これにより、プロジェクトディレクトリが作成され、基本的なファイル構成が用意されます。

Rustの標準テストフレームワーク


Rustには標準でテスト機能が組み込まれています。cargo testコマンドでテストを実行できます。例えば、以下のようにsrc/lib.rsにテストを追加します。

// src/lib.rs
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);
    }
}

テストを実行するには、次のコマンドを使用します。

cargo test

人気のある追加ツール

  1. cargo-watch
    コードの変更を監視し、変更があるたびにテストを自動で実行するツールです。インストール方法:
   cargo install cargo-watch

使用方法:

   cargo watch -x test
  1. cargo-nextest
    高速で並列テストが可能な次世代テストランナーです。大規模プロジェクトでのテスト実行を効率化します。
   cargo install cargo-nextest
  1. mockall
    モック(擬似オブジェクト)を作成するためのライブラリで、依存関係のテストに役立ちます。

エディタとIDEのセットアップ


RustのTDDに適したエディタやIDEには以下のものがあります。

  • Visual Studio Code: rust-analyzer拡張機能でRustの開発が快適になります。
  • IntelliJ IDEA / CLion: Rustプラグインをインストールすることで、強力なサポートが受けられます。
  • Vim / Neovim: rust.vimcoc-rust-analyzerプラグインを使用。

これでRustのTDDを行うための環境設定が整いました。次に、実際にテストを書いてTDDのサイクルを回していきましょう。

基本的なテストの書き方


Rustでは標準ライブラリにテスト機能が組み込まれているため、簡単にテストを作成・実行できます。ここでは、基本的なテストの書き方とその実行方法について解説します。

テスト関数の作成


Rustのテストは、#[test]アトリビュートを付けた関数として定義します。例えば、src/lib.rsに次のような関数とテストを追加します。

// src/lib.rs

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);
    }
}
  • #[cfg(test)]:テストモジュールをコンパイルするのはテスト実行時のみになります。
  • assert_eq!マクロ:二つの値が等しいかどうかを検証します。

テストの実行


作成したテストは、以下のコマンドで実行できます。

cargo test

実行結果の例:

running 1 test
test tests::test_add ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

異なる種類のアサーション


Rustでは、さまざまなアサーションマクロが用意されています。

  1. assert!:条件がtrueであることを確認します。 #[test] fn test_positive_number() { let x = 5; assert!(x > 0); }
  2. assert_eq!:二つの値が等しいことを確認します。 #[test] fn test_equality() { assert_eq!(2 + 2, 4); }
  3. assert_ne!:二つの値が等しくないことを確認します。
    rust #[test] fn test_inequality() { assert_ne!(2 + 2, 5); }

テストの失敗例


テストが失敗する場合の例を示します。

#[test]
fn test_failure_example() {
    assert_eq!(2 + 2, 5); // これは失敗します
}

失敗すると、次のような出力が表示されます。

---- tests::test_failure_example stdout ----
thread 'tests::test_failure_example' panicked at 'assertion failed: `(left == right)`
  left: `4`,
 right: `5`', src/lib.rs:7:5

テストの非同期処理


Rustでは非同期テストもサポートしています。async関数をテストする場合は、tokioなどの非同期ランタイムを利用します。

#[tokio::test]
async fn test_async_example() {
    let result = async { 5 }.await;
    assert_eq!(result, 5);
}

複数のテストをグループ化


テストモジュールを使うことで、複数のテストをグループ化できます。

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

    #[test]
    fn test_add() {
        assert_eq!(add(1, 2), 3);
    }

    #[test]
    fn test_subtract() {
        assert_eq!(1 - 2, -1);
    }
}

Rustの基本的なテスト機能を理解することで、TDDのサイクルをスムーズに回せるようになります。次はTDDの具体的なサイクル「レッド・グリーン・リファクタリング」について解説します。

TDDのサイクル:レッド・グリーン・リファクタリング


テスト駆動開発(TDD)は、「レッド(Red)→グリーン(Green)→リファクタリング(Refactor)」という3つのステップで構成されています。Rustにおけるこのサイクルの具体的な進め方について解説します。

1. レッド(Red) – 失敗するテストの作成


まず、まだ存在しない機能のためにテストを書きます。このテストは必ず失敗することが前提です。これにより、機能がまだ実装されていないことを確認できます。

例:文字列を反転する関数を作成するテスト

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

    #[test]
    fn test_reverse_string() {
        assert_eq!(reverse_string("hello"), "olleh");
    }
}

この時点ではreverse_string関数は存在しないため、コンパイルエラーになります。テストを実行すると、以下のエラーが表示されます。

error[E0425]: cannot find function `reverse_string` in this scope

2. グリーン(Green) – テストを通すための最小限のコードを書く


次に、テストをパスするために最小限のコードを実装します。正確さよりも、テストが通ることを優先します。

例:reverse_string関数の追加

pub fn reverse_string(s: &str) -> String {
    s.chars().rev().collect()
}

テストを再度実行すると、成功することが確認できます。

cargo test

出力結果:

running 1 test
test tests::test_reverse_string ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

3. リファクタリング(Refactor) – コードの改善


テストが通ったら、コードを改善(リファクタリング)します。リファクタリング後もテストがパスすることを確認し、機能が壊れていないことを保証します。

リファクタリング例:不要なコメントや冗長なコードを整理

pub fn reverse_string(s: &str) -> String {
    s.chars().rev().collect::<String>()
}

再度、テストを実行して動作確認します。

cargo test

TDDサイクルのポイント

  1. 小さなステップで進める
    大きな機能を一度に実装せず、少しずつテストとコードを書いて進めます。
  2. 失敗するテストを確認する
    必ず最初にテストが失敗することを確認し、テストが正しく機能しているかを確かめます。
  3. テストが通る最小限のコードを書く
    余分な機能やロジックは追加せず、テストが通るためだけのコードを実装します。
  4. リファクタリングを恐れない
    テストがあることで、リファクタリングによる動作変更のリスクを抑えられます。

この「レッド・グリーン・リファクタリング」のサイクルを繰り返すことで、バグが少なく、保守性の高いRustコードが効率的に作成できます。

モジュールとクレートのテスト


Rustではコードの再利用性や保守性を高めるために、モジュールやクレートを活用します。ここでは、モジュールや外部クレートをテストする方法について解説します。

モジュールのテスト


Rustのプロジェクトでは、複数のモジュールを使ってコードを整理します。それぞれのモジュールに対してテストを書くことで、個別の機能を確認できます。

例:モジュールを使った計算関数のテスト

// src/lib.rs

pub mod math {
    pub fn add(a: i32, b: i32) -> i32 {
        a + b
    }

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

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

    #[test]
    fn test_add() {
        assert_eq!(math::add(2, 3), 5);
    }

    #[test]
    fn test_subtract() {
        assert_eq!(math::subtract(5, 3), 2);
    }
}

ポイント

  • モジュールの公開関数にはpubを付けます。
  • テストモジュール内では、use文でテスト対象のモジュールをインポートします。

サブモジュールのテスト


モジュールが階層化されている場合、サブモジュールのテストも行えます。

// src/lib.rs

pub mod operations {
    pub mod math {
        pub fn multiply(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

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

    #[test]
    fn test_multiply() {
        assert_eq!(math::multiply(2, 3), 6);
    }
}

外部クレートのテスト


外部クレート(ライブラリ)を使用する場合もテストが可能です。外部クレートをCargo.tomlに追加し、テストを書きます。

例:regexクレートを使った文字列検索のテスト

  1. Cargo.tomlに依存クレートを追加
   [dependencies]
   regex = "1"
  1. コードとテストの実装
   use regex::Regex;

   pub fn contains_number(text: &str) -> bool {
       let re = Regex::new(r"\d+").unwrap();
       re.is_match(text)
   }

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

       #[test]
       fn test_contains_number() {
           assert!(contains_number("Hello 123"));
           assert!(!contains_number("Hello World"));
       }
   }
  1. テストの実行
   cargo test

ドキュメントテスト


Rustでは、ドキュメンテーションコメント内にサンプルコードを書き、そのサンプルをテストすることができます。

/// 二つの数値を加算する関数。
/// 
/// # 例
///
/// ```
/// let result = my_crate::add(2, 3);
/// assert_eq!(result, 5);
/// ```
pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

ドキュメントテストを実行するには、以下のコマンドを使います。

cargo test --doc

テストのベストプラクティス

  • モジュールごとにテストを書く:各モジュールに対応したテストを作成し、機能ごとに検証します。
  • エラーケースを考慮する:正常系だけでなく、異常系のテストも忘れずに書きます。
  • 外部クレートのバージョンを固定する:依存するクレートのバージョンを指定し、互換性の問題を防ぎます。

モジュールやクレートごとにしっかりとテストを書くことで、Rustプロジェクトの品質と保守性を向上させましょう。

失敗しやすいポイントと対処法


Rustでテスト駆動開発(TDD)を行う際に、よく直面する失敗パターンとその対処法について解説します。これらのポイントを意識することで、効率的にTDDを進め、エラーを回避できます。

1. 型エラーによるテスト失敗


Rustは強力な型システムを持つため、型のミスマッチがよく発生します。

例:型が合わないケース

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

#[test]
fn test_add() {
    let result = add(2, "3"); // 型エラー
}

対処法

  • 型を正確に指定する。
  • コンパイラのエラーメッセージを確認し、型の不一致を修正する。

2. 値の比較ミスによるテスト失敗


アサーションマクロassert_eq!assert_ne!を使った比較で、期待値と実際の値が異なることがあります。

例:期待値と実際の値の不一致

pub fn square(x: i32) -> i32 {
    x * x
}

#[test]
fn test_square() {
    assert_eq!(square(3), 8); // 正しい期待値は9
}

対処法

  • 期待値を再確認する。
  • デバッグ出力で中間値を確認する。

3. 非同期テストの落とし穴


非同期関数をテストする場合、ランタイムが正しく設定されていないとテストが失敗します。

例:非同期関数のテスト

#[tokio::test]
async fn test_async_function() {
    let result = async_function().await;
    assert_eq!(result, "Hello"); // 非同期関数が正しくない場合に失敗
}

対処法

  • 非同期ランタイム(tokioやasync-std)を正しく設定する。
  • 非同期関数が期待通りの値を返すことを確認する。

4. パニックによるテスト失敗


関数内でpanic!が発生すると、テストが失敗します。

例:パニックが発生するケース

pub fn divide(a: i32, b: i32) -> i32 {
    if b == 0 {
        panic!("Division by zero");
    }
    a / b
}

#[test]
fn test_divide() {
    divide(4, 0); // パニックが発生
}

対処法

  • エラー処理を適切に実装し、パニックを避ける。
  • should_panicアトリビュートを使い、パニックが期待されることを示す。
#[test]
#[should_panic(expected = "Division by zero")]
fn test_divide_by_zero() {
    divide(4, 0);
}

5. モジュールのパス指定ミス


モジュールや関数のパス指定が間違っていると、テストが失敗します。

例:パス指定の誤り

mod utils {
    pub fn greet() -> String {
        "Hello".to_string()
    }
}

#[test]
fn test_greet() {
    assert_eq!(crate::greet(), "Hello"); // 間違ったパス指定
}

対処法

  • 正しいパス指定を確認する。
  • use文を活用してモジュールをインポートする。
#[test]
fn test_greet() {
    use crate::utils::greet;
    assert_eq!(greet(), "Hello");
}

6. テストが実行されない問題


cargo testでテストが実行されない場合、#[cfg(test)]#[test]の指定が正しいか確認します。

対処法

  • #[cfg(test)]アトリビュートが正しく付けられていることを確認する。
  • 関数が#[test]アトリビュートでマークされていることを確認する。

まとめ


RustでTDDを進める際は、型エラー、非同期処理、パニック、モジュールパス指定ミスに注意し、問題が発生した場合はコンパイラのエラーメッセージを確認しながら修正していきましょう。これにより、スムーズにTDDを実践できるようになります。

実践例:簡単なRustプロジェクトでのTDD


ここでは、Rustでテスト駆動開発(TDD)を使って簡単なプロジェクトを作成する実践例を紹介します。具体的には、文字列を暗号化・復号化する簡単なシーザー暗号プログラムをTDDで開発していきます。


1. プロジェクトの作成


まず、cargoを使って新しいプロジェクトを作成します。

cargo new caesar_cipher
cd caesar_cipher

2. レッド(Red):失敗するテストの作成


src/lib.rsにテストを書きます。シーザー暗号は、各文字を指定したシフト数でずらして暗号化する方法です。

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

    #[test]
    fn test_encrypt() {
        assert_eq!(encrypt("hello", 3), "khoor");
    }
}

この時点ではencrypt関数が存在しないため、コンパイルエラーが発生します。


3. グリーン(Green):テストを通すための最小限のコードを書く


encrypt関数を実装し、テストが通るようにします。

pub fn encrypt(text: &str, shift: i32) -> String {
    text.chars()
        .map(|c| {
            let base = if c.is_lowercase() { 'a' } else { 'A' };
            (((c as u8 - base as u8 + shift as u8) % 26) + base as u8) as char
        })
        .collect()
}

テストを実行します。

cargo test

出力結果:

running 1 test
test tests::test_encrypt ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

4. リファクタリング(Refactor):コードの改善


コードの可読性や安全性を改善します。

pub fn encrypt(text: &str, shift: i32) -> String {
    text.chars()
        .map(|c| {
            if c.is_ascii_alphabetic() {
                let base = if c.is_lowercase() { 'a' } else { 'A' };
                let shifted = (c as u8 - base as u8 + shift as u8) % 26;
                (shifted + base as u8) as char
            } else {
                c
            }
        })
        .collect()
}

5. 復号化機能の追加(TDDのサイクルを繰り返す)


復号化機能のテストを書きます。

#[test]
fn test_decrypt() {
    assert_eq!(decrypt("khoor", 3), "hello");
}

コンパイルエラーが発生するので、decrypt関数を実装します。

pub fn decrypt(text: &str, shift: i32) -> String {
    encrypt(text, 26 - (shift % 26))
}

再度テストを実行します。

cargo test

出力結果:

running 2 tests
test tests::test_encrypt ... ok
test tests::test_decrypt ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

6. 追加テスト:大文字や非アルファベット文字の対応


追加のテストケースを書いて、機能が正しいことを確認します。

#[test]
fn test_encrypt_with_uppercase() {
    assert_eq!(encrypt("Hello, World!", 3), "Khoor, Zruog!");
}

#[test]
fn test_decrypt_with_uppercase() {
    assert_eq!(decrypt("Khoor, Zruog!", 3), "Hello, World!");
}

再度テストを実行します。

cargo test

出力結果:

running 4 tests
test tests::test_encrypt ... ok
test tests::test_decrypt ... ok
test tests::test_encrypt_with_uppercase ... ok
test tests::test_decrypt_with_uppercase ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

まとめ


この実践例では、Rustでシーザー暗号の暗号化と復号化機能をTDDで開発しました。TDDのサイクル(レッド→グリーン→リファクタリング)を繰り返し、少しずつ機能を追加・改善していくことで、バグが少なく保守性の高いコードが作成できます。

まとめ


本記事では、Rustにおけるテスト駆動開発(TDD)の手順と実践方法について解説しました。TDDの基本サイクルである「レッド(失敗するテストの作成)→グリーン(テストを通すコードの作成)→リファクタリング(コードの改善)」をRustのプロジェクトに適用することで、バグの少ない、安全で保守性の高いコードを効率的に開発できます。

Rustの強力な型システム、標準のテストフレームワーク、非同期処理、モジュールシステムを活用することで、TDDの効果を最大限に引き出すことが可能です。小さなステップでテストとコードを繰り返し、エラーや問題点に早期に気づくことが、信頼性の高いシステムを構築するための鍵となります。

TDDをRustプロジェクトに導入し、品質向上と効率的な開発を目指しましょう。

コメント

コメントする

目次
  1. テスト駆動開発(TDD)とは何か
    1. TDDの基本サイクル
    2. TDDの利点
    3. TDDと従来の開発手法の違い
  2. RustでのTDDの利点
    1. 1. コンパイル時の安全性
    2. 2. 安心したリファクタリング
    3. 3. ドキュメンテーションの向上
    4. 4. パフォーマンスの最適化
    5. 5. エラー処理の強化
    6. 6. 信頼性の高い並行処理
  3. 環境設定とテストツール
    1. Rustのインストールとセットアップ
    2. プロジェクトの作成
    3. Rustの標準テストフレームワーク
    4. 人気のある追加ツール
    5. エディタとIDEのセットアップ
  4. 基本的なテストの書き方
    1. テスト関数の作成
    2. テストの実行
    3. 異なる種類のアサーション
    4. テストの失敗例
    5. テストの非同期処理
    6. 複数のテストをグループ化
  5. TDDのサイクル:レッド・グリーン・リファクタリング
    1. 1. レッド(Red) – 失敗するテストの作成
    2. 2. グリーン(Green) – テストを通すための最小限のコードを書く
    3. 3. リファクタリング(Refactor) – コードの改善
    4. TDDサイクルのポイント
  6. モジュールとクレートのテスト
    1. モジュールのテスト
    2. サブモジュールのテスト
    3. 外部クレートのテスト
    4. ドキュメントテスト
    5. テストのベストプラクティス
  7. 失敗しやすいポイントと対処法
    1. 1. 型エラーによるテスト失敗
    2. 2. 値の比較ミスによるテスト失敗
    3. 3. 非同期テストの落とし穴
    4. 4. パニックによるテスト失敗
    5. 5. モジュールのパス指定ミス
    6. 6. テストが実行されない問題
    7. まとめ
  8. 実践例:簡単なRustプロジェクトでのTDD
    1. 1. プロジェクトの作成
    2. 2. レッド(Red):失敗するテストの作成
    3. 3. グリーン(Green):テストを通すための最小限のコードを書く
    4. 4. リファクタリング(Refactor):コードの改善
    5. 5. 復号化機能の追加(TDDのサイクルを繰り返す)
    6. 6. 追加テスト:大文字や非アルファベット文字の対応
    7. まとめ
  9. まとめ