Kotlinで始めるテスト駆動開発(TDD)の基本フローと実践ガイド

Kotlinを使ったテスト駆動開発(TDD)は、ソフトウェアの品質を向上させる効果的な手法です。TDDでは、コードを書く前にテストを作成し、そのテストが成功するようにコードを実装・修正するというサイクルを繰り返します。このアプローチにより、バグの早期発見、リファクタリングの安全性向上、そして設計品質の向上が期待できます。本記事では、Kotlinを用いたTDDの基本的な概念と手順、具体的な実践方法について詳しく解説します。TDD初心者でもすぐに始められるように、環境設定から実際のコード例、リファクタリングのポイントまで網羅しています。

目次
  1. テスト駆動開発(TDD)とは
    1. TDDの目的
    2. TDDの基本原則
    3. KotlinでのTDDの利点
  2. TDDの基本サイクル
    1. 1. Red(失敗するテストを書く)
    2. 2. Green(テストを通すためのコードを書く)
    3. 3. Refactor(リファクタリング)
    4. TDDサイクルを繰り返す
  3. KotlinでTDDを始める準備
    1. 1. 開発環境のセットアップ
    2. 2. テストフレームワークの導入
    3. 3. テストの実行
    4. 4. テスト駆動開発を始める準備完了
  4. Kotlinにおける初めてのTDD実践
    1. 1. Red:失敗するテストを書く
    2. 2. Green:テストを通すためのコードを書く
    3. 3. Refactor:リファクタリング
    4. 4. TDDサイクルを繰り返す
  5. テストケースの書き方
    1. 1. テストケースの基本構造
    2. 2. テストケース作成のポイント
    3. 3. パラメータ化テストを活用する
    4. 4. テストケースのメンテナンス
  6. TDDでよくある問題と解決策
    1. 1. テストを書くことが面倒に感じる
    2. 2. すぐに実装を書いてしまう
    3. 3. テストが多すぎて管理が大変
    4. 4. 依存関係が多いコードのテストが難しい
    5. 5. テストが壊れやすい
    6. 6. テストが遅い
  7. リファクタリングの重要性
    1. リファクタリングとは何か
    2. リファクタリングの目的
    3. リファクタリングのタイミング
    4. リファクタリングの手法
    5. リファクタリング時の注意点
    6. リファクタリングの実例
    7. まとめ
  8. 実践的なTDDの応用例
    1. 1. 要件定義
    2. 2. Red-Green-Refactorのサイクルで開発
    3. 3. 例外処理のテスト追加
    4. 4. 完成したクラス
    5. まとめ
  9. まとめ

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


テスト駆動開発(Test-Driven Development、略称TDD)は、ソフトウェア開発の一手法であり、「テストを書いてからコードを書く」という特徴的なアプローチです。これは従来の「コードを書いてからテストする」という開発手順とは逆の流れです。

TDDの目的


TDDの主な目的は以下の通りです:

  • バグの早期発見:コードを書き進める前にテストがあるため、不具合を迅速に発見できます。
  • 設計の改善:TDDを実践すると、シンプルで保守しやすい設計を自然と導入できます。
  • リファクタリングの安全性:既存のテストがあるため、コードを修正しても意図しない挙動を防げます。

TDDの基本原則


TDDは「Red-Green-Refactor」という3つのステップで進められます。

  1. Red(失敗するテストを書く):要件を満たすためのテストを書きます。最初はテストが失敗することを確認します。
  2. Green(テストを通すためのコードを書く):テストが成功する最小限のコードを書きます。
  3. Refactor(リファクタリング):コードを改善し、重複や冗長を取り除きます。テストが成功する状態を維持します。

KotlinでのTDDの利点


Kotlinは、TDDを実践するのに適した言語です。以下の点がTDDを効率的に進める助けとなります:

  • 簡潔な構文:Kotlinのシンプルで冗長性の少ない文法はテストコードを素早く記述できます。
  • 強力な型システム:静的型付けにより、潜在的なエラーを早期に検出できます。
  • Javaとの互換性:JUnitなどのテストフレームワークを簡単に利用できます。

TDDを理解し実践することで、より信頼性が高く、保守しやすいソフトウェアをKotlinで開発できるようになります。

TDDの基本サイクル


テスト駆動開発(TDD)は、「Red-Green-Refactor」の3つのステップを繰り返すサイクルによって進められます。このシンプルなサイクルを守ることで、品質の高いコードを効率的に開発できます。

1. Red(失敗するテストを書く)


まず、要件や仕様に基づいて、最初にテストケースを作成します。この時点では、まだ実装が存在しないため、テストは失敗するはずです。この失敗(Red)を確認することが、TDDサイクルの出発点です。

Kotlinでの例

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class CalculatorTest {
    @Test
    fun `addition of two numbers`() {
        val calculator = Calculator()
        assertEquals(5, calculator.add(2, 3))
    }
}

この時点でCalculatorクラスとaddメソッドは未実装なので、テストは失敗します。

2. Green(テストを通すためのコードを書く)


次に、テストが成功するための最小限のコードを実装します。正確にテストが通るように、シンプルで余計な処理を含まないコードを書くのがポイントです。

Kotlinでの例

class Calculator {
    fun add(a: Int, b: Int): Int {
        return a + b
    }
}

この実装により、先ほど書いたテストが成功(Green)するようになります。

3. Refactor(リファクタリング)


テストが成功したら、コードのリファクタリング(整理・改善)を行います。この時点では、コードの挙動を変更しない範囲で、重複や冗長性を取り除きます。テストがあるので、リファクタリング後も正しい動作が保証されます。

リファクタリング例

// 例えば、複数の演算をサポートするためのリファクタリング
class Calculator {
    fun add(vararg numbers: Int): Int {
        return numbers.sum()
    }
}

TDDサイクルを繰り返す


この「Red-Green-Refactor」のサイクルを小さな単位で繰り返しながら、徐々に機能を拡張していきます。これにより、コードが常にテストで検証され、バグが少なく品質の高いソフトウェアを構築できます。

KotlinでTDDを始める準備


Kotlinを使ってテスト駆動開発(TDD)を始めるには、適切な環境設定とテストフレームワークの導入が必要です。以下に、TDDを行うための準備手順を解説します。

1. 開発環境のセットアップ


KotlinでTDDを行うために、以下のツールを準備します:

  • IDE:IntelliJ IDEA(Community版でも可)またはAndroid Studio
  • ビルドツール:GradleまたはMaven
  • JDK:Java Development Kit 8以降

Gradleプロジェクトの作成


IntelliJ IDEAで新規Gradleプロジェクトを作成し、Kotlinのサポートを追加します。

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.9.0'
}

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit5'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0'
}

test {
    useJUnitPlatform()
}

2. テストフレームワークの導入


Kotlinでは、JUnit 5が一般的なテストフレームワークとして使用されます。上記のbuild.gradle設定でJUnit 5を追加したら、テストを作成できる状態になります。

JUnit 5のテストクラス作成


以下は、KotlinでJUnit 5を使った基本的なテストクラスの例です。

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class SampleTest {

    @Test
    fun `addition works correctly`() {
        val sum = 2 + 3
        assertEquals(5, sum)
    }
}

3. テストの実行


IntelliJ IDEAでテストクラスを右クリックし、「Run Tests」を選択すると、テストが実行されます。成功・失敗の結果がIDE上に表示されるため、すぐに確認できます。

4. テスト駆動開発を始める準備完了


これでKotlinのTDDを始める準備が整いました。これから、Red-Green-Refactorのサイクルに従いながら、TDDを実践していきましょう。

Kotlinにおける初めてのTDD実践


ここでは、Kotlinを用いたシンプルなTDDの流れを、具体的な例を用いて実践していきます。例として、「文字列の長さを返す関数」をTDDで開発してみましょう。

1. Red:失敗するテストを書く


まず、テストケースを書いて、意図した動作ができるか確認します。StringUtilsクラスにgetLengthというメソッドを作成し、文字列の長さを返すことをテストします。

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class StringUtilsTest {

    @Test
    fun `getLength returns correct length of the string`() {
        val stringUtils = StringUtils()
        assertEquals(5, stringUtils.getLength("hello"))
    }
}

この段階では、StringUtilsクラスとgetLengthメソッドは未実装なので、テストは失敗します。これがTDDの「Red」フェーズです。

2. Green:テストを通すためのコードを書く


次に、テストを成功させるための最小限のコードを実装します。

class StringUtils {
    fun getLength(input: String): Int {
        return input.length
    }
}

このコードを追加した後、テストを再実行すると、テストが成功します。これが「Green」フェーズです。

3. Refactor:リファクタリング


テストが成功したら、コードのリファクタリングを行います。現段階ではシンプルなコードなので、リファクタリングは不要ですが、必要に応じてコードの整理や改善を行います。

例えば、メソッド名や引数の名前をより明確にする場合:

class StringUtils {
    fun calculateLength(text: String): Int {
        return text.length
    }
}

テストも対応して修正します。

@Test
fun `calculateLength returns correct length of the string`() {
    val stringUtils = StringUtils()
    assertEquals(5, stringUtils.calculateLength("hello"))
}

4. TDDサイクルを繰り返す


この「Red-Green-Refactor」のサイクルを繰り返し、機能を追加・改善していきます。例えば、以下のように新しい要件を追加することもできます。

  • 空文字列の場合、長さは0であること
  • nullの入力に対する処理

TDDを繰り返すことで、少しずつ機能が充実し、バグの少ない堅牢なコードを開発できます。

テストケースの書き方


テスト駆動開発(TDD)において、効果的なテストケースを書くことは非常に重要です。Kotlinでのテストケースの書き方と、ポイントを具体例を交えて解説します。

1. テストケースの基本構造


テストケースは一般的に以下の構造で書きます:

  1. セットアップ(初期設定)
  2. 実行(テスト対象の処理を実行)
  3. 検証(期待する結果と実際の結果を比較)

KotlinのJUnit 5を使った例:

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class CalculatorTest {

    @Test
    fun `addition of two positive numbers`() {
        // セットアップ
        val calculator = Calculator()

        // 実行
        val result = calculator.add(3, 5)

        // 検証
        assertEquals(8, result)
    }
}

2. テストケース作成のポイント

明確で分かりやすい名前を付ける


テストケースの名前は、テストの目的や期待する結果が一目で分かるように付けます。一般的に、「何をテストするか」「期待する結果」を記述します。

良い例

@Test
fun `subtracting two numbers returns correct result`() 

悪い例

@Test
fun testSubtraction()

1つのテストケースは1つの事象を検証する


1つのテストケースで複数の動作を検証しないようにします。単一責任に従い、1つのテストで1つの事象を確認することで、問題の特定が容易になります。

境界値やエッジケースを考慮する


通常のケースだけでなく、境界値やエッジケースも考慮してテストします。

例:空文字列の長さをテスト

@Test
fun `getLength returns 0 for empty string`() {
    val stringUtils = StringUtils()
    assertEquals(0, stringUtils.getLength(""))
}

例外やエラーハンドリングのテスト


例外が正しくスローされるか確認するテストも重要です。

例:null入力に対する例外処理

import org.junit.jupiter.api.assertThrows

@Test
fun `getLength throws exception for null input`() {
    val stringUtils = StringUtils()
    assertThrows<IllegalArgumentException> {
        stringUtils.getLength(null)
    }
}

3. パラメータ化テストを活用する


複数の入力で同じ処理をテストする場合、パラメータ化テストを使用すると効率的です。

JUnit 5の@ParameterizedTestの例:

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import kotlin.test.assertEquals

class CalculatorTest {

    @ParameterizedTest
    @CsvSource("1, 2, 3", "3, 4, 7", "10, 5, 15")
    fun `addition of two numbers returns correct result`(a: Int, b: Int, expected: Int) {
        val calculator = Calculator()
        assertEquals(expected, calculator.add(a, b))
    }
}

4. テストケースのメンテナンス

  • 重複を避ける:共通の初期化処理は@BeforeEachを使ってまとめましょう。
  • 定期的にリファクタリング:テストコードも定期的にリファクタリングし、保守性を高めましょう。

効果的なテストケースを書くことで、TDDがより強力な手法となり、バグの少ない高品質なコードを維持できます。

TDDでよくある問題と解決策


テスト駆動開発(TDD)を進める中で、初心者から経験者までさまざまな問題に直面することがあります。ここでは、TDDでよくある問題とその解決策について解説します。

1. テストを書くことが面倒に感じる


問題:テストケースを書く手間が増え、開発スピードが遅く感じることがあります。

解決策

  • 小さなステップで進める:1回のTDDサイクルで小さな単位のテストを書くことで負担を軽減できます。
  • テストの自動化を活用:GradleやMavenのタスクでテストを自動実行し、効率化を図りましょう。
  • シンプルなテストから始める:複雑なテストを書こうとせず、シンプルなテストから着手しましょう。

2. すぐに実装を書いてしまう


問題:TDDの手順を無視して、つい先に実装を書いてしまうことがあります。

解決策

  • Red-Green-Refactorを意識する:必ずテストを先に書いて失敗を確認する習慣をつけましょう。
  • ペアプログラミングを活用:他の開発者とペアで作業することで、TDDの手順を守りやすくなります。

3. テストが多すぎて管理が大変


問題:テストケースが増えすぎて、管理が煩雑になり、修正が難しくなることがあります。

解決策

  • テストの命名規則を統一する:テスト名に一貫性を持たせ、何をテストしているか分かりやすくします。
  • テストのグループ化:関連するテストをクラスやパッケージ単位でまとめましょう。
  • 共通の初期化処理を整理@BeforeEach@AfterEachを活用して初期化処理を共通化します。

4. 依存関係が多いコードのテストが難しい


問題:依存関係が多いクラスをテストしようとすると、セットアップが複雑になりがちです。

解決策

  • モックやスタブを活用する:MockitoやMockKなどのライブラリを使用し、依存関係をモック化します。
  • 依存性注入(DI)を導入:クラスに依存関係を直接持たせず、外部から注入することでテストが容易になります。

例:MockKを使ったモックの例

import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class UserServiceTest {

    @Test
    fun `getUserName returns correct name`() {
        val userRepository = mockk<UserRepository>()
        every { userRepository.findNameById(1) } returns "John Doe"

        val userService = UserService(userRepository)
        assertEquals("John Doe", userService.getUserName(1))
    }
}

5. テストが壊れやすい


問題:小さな変更を加えただけで、多くのテストが失敗することがあります。

解決策

  • 堅牢なテストを書く:実装の詳細に依存しすぎない、振る舞いをテストするように心がけましょう。
  • リファクタリングを定期的に行う:テストコードも含めて定期的にリファクタリングし、保守性を高めます。

6. テストが遅い


問題:テストケースが多くなると、すべてのテスト実行に時間がかかることがあります。

解決策

  • ユニットテストと統合テストを分ける:ユニットテストは高速に実行し、統合テストは必要に応じて実行します。
  • 並列テスト実行:GradleやJUnit 5の並列実行機能を活用してテストを高速化します。

TDDでよくある問題を理解し、これらの解決策を取り入れることで、TDDの効果を最大限に引き出し、効率よく高品質なコードを開発できます。

リファクタリングの重要性


リファクタリングは、テスト駆動開発(TDD)の中核を成す重要なプロセスです。TDDの「Red-Green-Refactor」のサイクルにおける「Refactor」フェーズでは、テストが成功する状態を維持しながら、コードを改善します。これにより、コードの保守性や可読性が向上し、将来的なバグのリスクが減少します。

リファクタリングとは何か


リファクタリングは、コードの外部から見た挙動を変えずに内部の構造を整理・改善する作業です。テストがあることで、リファクタリング後も正しく動作していることが確認できます。

リファクタリングの目的

  • コードの可読性向上:他の開発者がコードを理解しやすくなります。
  • 重複の排除:DRY(Don’t Repeat Yourself)の原則に基づき、同じコードを繰り返さないようにします。
  • 保守性向上:コードがシンプルになり、修正や追加がしやすくなります。
  • バグの削減:構造を整理することで、潜在的なバグの発生を防ぎます。

リファクタリングのタイミング


TDDでは、以下のタイミングでリファクタリングを行います:

  1. テストが成功した後:Greenフェーズでテストが通った後にリファクタリングします。
  2. コードが複雑になったと感じた時:重複や冗長が目立った時に整理します。
  3. 新しい機能を追加する前:新機能を追加しやすくするため、関連するコードをリファクタリングします。

リファクタリングの手法


いくつかの代表的なリファクタリング手法を紹介します。

1. メソッドの抽出(Extract Method)


複数の処理が1つのメソッドにまとまっている場合、独立したメソッドに分けます。

Before

fun calculateTotal(prices: List<Int>): Int {
    var total = 0
    for (price in prices) {
        total += price
    }
    println("Total: $total")
    return total
}

After

fun calculateTotal(prices: List<Int>): Int {
    val total = sumPrices(prices)
    println("Total: $total")
    return total
}

fun sumPrices(prices: List<Int>): Int {
    return prices.sum()
}

2. 変数のリネーム(Rename Variable)


変数名を分かりやすいものに変更します。

Before

val a = "John Doe"

After

val customerName = "John Doe"

3. 重複コードの排除


同じ処理を複数箇所で使っている場合、共通のメソッドやクラスにまとめます。

リファクタリング時の注意点

  1. テストを必ず実行する:リファクタリング後は必ずテストを実行し、動作が変わっていないことを確認します。
  2. 小さなステップで行う:大規模な変更を一度に行わず、小さな変更を繰り返しましょう。
  3. コミットを細かく分ける:リファクタリングごとにコミットし、問題があれば戻れるようにします。

リファクタリングの実例


以下は、リファクタリング前後の例です。

Before

fun calculateDiscount(price: Double, isMember: Boolean): Double {
    if (isMember) {
        return price * 0.9
    } else {
        return price
    }
}

After

fun calculateDiscount(price: Double, isMember: Boolean): Double {
    val discountRate = if (isMember) 0.9 else 1.0
    return price * discountRate
}

まとめ


リファクタリングは、TDDにおいてコード品質を維持し続けるための重要なプロセスです。テストがあることで安心してリファクタリングができ、コードが複雑になるのを防げます。TDDの「Red-Green-Refactor」のサイクルを守り、定期的にリファクタリングを行うことで、保守しやすく高品質なコードを維持しましょう。

実践的なTDDの応用例


Kotlinでテスト駆動開発(TDD)を実践する具体的なシナリオを見ていきましょう。ここでは、シンプルなタスク管理アプリを例にして、TDDの応用方法を解説します。

1. 要件定義


以下の要件を持つタスク管理アプリをTDDで開発します:

  1. タスクを追加できる。
  2. タスクの一覧を取得できる。
  3. タスクを完了済みにできる。

2. Red-Green-Refactorのサイクルで開発


各機能をTDDで実装するステップを順番に進めます。

ステップ1:タスクを追加する機能

Red(失敗するテストを書く)
タスクを追加し、リストに正しく格納されることをテストします。

import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class TaskManagerTest {

    @Test
    fun `addTask should add a task to the task list`() {
        val taskManager = TaskManager()
        taskManager.addTask("Buy groceries")
        assertEquals(1, taskManager.getAllTasks().size)
        assertEquals("Buy groceries", taskManager.getAllTasks()[0].description)
    }
}

Green(テストを通すためのコードを書く)
テストが通るための最小限の実装を行います。

data class Task(val description: String, var isCompleted: Boolean = false)

class TaskManager {
    private val tasks = mutableListOf<Task>()

    fun addTask(description: String) {
        tasks.add(Task(description))
    }

    fun getAllTasks(): List<Task> {
        return tasks
    }
}

Refactor(リファクタリング)
現時点でコードはシンプルなので、リファクタリングは不要です。


ステップ2:タスクの一覧を取得する機能

Red(失敗するテストを書く)
追加したタスクが一覧として正しく取得できることを確認します。

@Test
fun `getAllTasks should return all added tasks`() {
    val taskManager = TaskManager()
    taskManager.addTask("Buy groceries")
    taskManager.addTask("Write report")
    val tasks = taskManager.getAllTasks()
    assertEquals(2, tasks.size)
    assertEquals("Buy groceries", tasks[0].description)
    assertEquals("Write report", tasks[1].description)
}

このテストはすでに実装済みのaddTaskgetAllTasksで成功するはずです。


ステップ3:タスクを完了済みにする機能

Red(失敗するテストを書く)
タスクを完了済みに設定できることをテストします。

@Test
fun `completeTask should mark a task as completed`() {
    val taskManager = TaskManager()
    taskManager.addTask("Buy groceries")
    taskManager.completeTask(0)
    assertEquals(true, taskManager.getAllTasks()[0].isCompleted)
}

Green(テストを通すためのコードを書く)
テストが通るための最小限のコードを追加します。

fun completeTask(index: Int) {
    if (index in tasks.indices) {
        tasks[index].isCompleted = true
    }
}

Refactor(リファクタリング)
重複コードがないか、メソッド名や変数名が適切か確認します。


3. 例外処理のテスト追加


タスクを完了する際に不正なインデックスが渡された場合、例外をスローする処理を追加します。

Red(失敗するテストを書く)

import org.junit.jupiter.api.assertThrows

@Test
fun `completeTask should throw exception for invalid index`() {
    val taskManager = TaskManager()
    taskManager.addTask("Buy groceries")
    assertThrows<IndexOutOfBoundsException> {
        taskManager.completeTask(5)
    }
}

Green(テストを通すためのコードを書く)

fun completeTask(index: Int) {
    if (index !in tasks.indices) {
        throw IndexOutOfBoundsException("Invalid task index")
    }
    tasks[index].isCompleted = true
}

4. 完成したクラス


最終的に完成したTaskManagerクラスです。

data class Task(val description: String, var isCompleted: Boolean = false)

class TaskManager {
    private val tasks = mutableListOf<Task>()

    fun addTask(description: String) {
        tasks.add(Task(description))
    }

    fun getAllTasks(): List<Task> {
        return tasks
    }

    fun completeTask(index: Int) {
        if (index !in tasks.indices) {
            throw IndexOutOfBoundsException("Invalid task index")
        }
        tasks[index].isCompleted = true
    }
}

まとめ


このように、TDDのサイクル「Red-Green-Refactor」を繰り返しながら機能を追加することで、バグの少ない堅牢なコードを効率的に開発できます。TDDを実践することで、Kotlinのコード品質を向上させ、メンテナンスしやすいアプリケーションを構築できます。

まとめ


本記事では、Kotlinを用いたテスト駆動開発(TDD)の基本的な流れについて解説しました。TDDの「Red-Green-Refactor」サイクルに従い、テストを書いてからコードを実装し、リファクタリングを行う手順を理解することで、バグの少ない高品質なソフトウェアを効率的に開発できます。

TDDを実践することで、以下の利点が得られます:

  • バグの早期発見:テストが先にあるため、不具合をすぐに特定できます。
  • 設計の改善:シンプルで保守しやすいコードが自然と生まれます。
  • リファクタリングの安全性:テストが動作を保証するため、安心してリファクタリングできます。

TDDは最初は面倒に感じるかもしれませんが、小さなステップを繰り返すことで、効率よく健全なコードを維持できます。Kotlinの強力な機能と共に、TDDを日々の開発に取り入れて、より品質の高いアプリケーションを構築しましょう。

コメント

コメントする

目次
  1. テスト駆動開発(TDD)とは
    1. TDDの目的
    2. TDDの基本原則
    3. KotlinでのTDDの利点
  2. TDDの基本サイクル
    1. 1. Red(失敗するテストを書く)
    2. 2. Green(テストを通すためのコードを書く)
    3. 3. Refactor(リファクタリング)
    4. TDDサイクルを繰り返す
  3. KotlinでTDDを始める準備
    1. 1. 開発環境のセットアップ
    2. 2. テストフレームワークの導入
    3. 3. テストの実行
    4. 4. テスト駆動開発を始める準備完了
  4. Kotlinにおける初めてのTDD実践
    1. 1. Red:失敗するテストを書く
    2. 2. Green:テストを通すためのコードを書く
    3. 3. Refactor:リファクタリング
    4. 4. TDDサイクルを繰り返す
  5. テストケースの書き方
    1. 1. テストケースの基本構造
    2. 2. テストケース作成のポイント
    3. 3. パラメータ化テストを活用する
    4. 4. テストケースのメンテナンス
  6. TDDでよくある問題と解決策
    1. 1. テストを書くことが面倒に感じる
    2. 2. すぐに実装を書いてしまう
    3. 3. テストが多すぎて管理が大変
    4. 4. 依存関係が多いコードのテストが難しい
    5. 5. テストが壊れやすい
    6. 6. テストが遅い
  7. リファクタリングの重要性
    1. リファクタリングとは何か
    2. リファクタリングの目的
    3. リファクタリングのタイミング
    4. リファクタリングの手法
    5. リファクタリング時の注意点
    6. リファクタリングの実例
    7. まとめ
  8. 実践的なTDDの応用例
    1. 1. 要件定義
    2. 2. Red-Green-Refactorのサイクルで開発
    3. 3. 例外処理のテスト追加
    4. 4. 完成したクラス
    5. まとめ
  9. まとめ