LoginSignup
1
2

More than 3 years have passed since last update.

いきなり!TDD(当方テスト初心者でいきなりTDD!) 1日目

Posted at

TDDとは

Test-Driven Developmentのこと。ある機能に対して期待する結果を、プロダクトコードより先に”失敗するテスト”として書き(テストファースト)、実装のゴールを目指す開発スタイル。同時に、「テストしやすい」 == 「よい設計」と捉えるならば、よい設計手法とも言えます。「心理的安全を得たままにプロダクトコードの改善をすること」が目的の1つとなります。

■メリット

  • メンテナンスがしやすい
  • デバッグにかける時間を減らせる
  • 素早い設計判断、設計改善を行える

 
■デメリット

  • チームの成熟度やプロジェクトの状況によっては、アダとなることがある
  • 仕様変更が生じたと時は、テストのメンテナンスも発生する
  • ビルド時間がテストファーストの負荷を上げる

レッド/グリーン/リファクタリング

1、レッド:これから作るもののゴールを定める(テストを書く)
2、グリーン:期待する結果を満たす足場を作る(プロダクトコードを書く)
3、リファクタリング:作った羽柴を保ちながら改良を行う(コード整理、共通化、設計見直し)

開発環境

  • Xcode 10.3
  • Swift
  • XCTest

作るもの

ポーカー

まずは、実装したいことをTODOリストに書き起こす

[目的]
-スート(suit)とランク(rank)を与えて、カード(card)を生成する
-生成したカードから文字列表記(notation)を取得する

↓TODOリストに置き換える

[TODOリスト]

  • Cardを定義して、インスタンスを作成する
    • CardはSuitを持つ
    • CardはRankを持つ
  • Cardのインスタンスから文字列表記(notation)を取得する

プロジェクト作成

1.Xcode > Create a new Xcode Project > Single View App
2.プロジェクト名:TDDPokerBySwift
3.Include Unit Testsのチェックをオン
4.Next > ディレクトリ指定 > Create

初回テスト

Command + U でテスト実行

Build SuccessでOK

実際にテストを作成する

TDDPokerBySwiftTests.swiftを開いて、以下のように修正する

TDDPokerBySwiftTests.swift
import XCTest
@testable import TDDPokerBySwift

class TDDPokerBySwiftTests: XCTestCase {

    func testInitializeCard() {
        let card1 = Card(suit: .heart, rank: .three)
        XCTAssertEqual(card1.suit, .heart)
        XCTAssertEqual(card1.rank, .three)

        let card2 = Card(suit: .spade, rank: .jack)
        XCTAssertEqual(card2.suit, .spade)
        XCTAssertEqual(card2.rank, .jack)
    }
}

Command + U でテスト実行してみましょう。
当然、エラーになります。これは、テストコードのエラーでなはく、単純にCardクラスが存在しないためのコンパイルエラーです。
スクリーンショット 2019-08-08 16.03.40.png

Cardクラスを作成しましょう。今回もMVVMで作成していければと思いますので、
Project Navigator > TDDPokerBySwiftグループ > 右クリック > New Groupで、
- Models
- Views
- ViewControllers
を作成して、Models/Card.swiftを作成します。
スクリーンショット 2019-08-08 16.07.46.png

Card.swift
import Foundation

struct Card {

    enum Suit {
        case spade
        case heart
        case club
        case diamond
    }

    enum Rank {
        case ace
        case two
        case three
        case four
        case five
        case six
        case seven
        case eight
        case nine
        case ten
        case jack
        case queen
        case king
    }

    let suit: Suit
    let rank: Rank
}

それでは、Command + U でテスト実行してみましょう。
Build Succeeded > Test Succeeded となれば成功です。

ここまでで、レッド > グリーンまで作業しました。
仕上げに、リファクタリングです。

テストコードを以下に書き換えましょう。

TDDPokerBySwiftTests.swift
import XCTest
@testable import TDDPokerBySwift

class TDDPokerBySwiftTests: XCTestCase {

    func testInitializeCard() {

        var card: Card

        card = Card(suit: .heart, rank: .three)
        XCTAssertEqual(card.suit, .heart)
        XCTAssertEqual(card.rank, .three)

        card = Card(suit: .spade, rank: .jack)
        XCTAssertEqual(card.suit, .spade)
        XCTAssertEqual(card.rank, .jack)
    }
}

ローカル変数cardに統一したことで、直前に代入しているカードにアサーションをかけていると読めるようになりました。
それでは、Command + U でテスト実行してみましょう。

問題なければ、TODOリストにチェックを入れます。

  • Cardを定義して、インスタンスを作成する
    • CardはSuitを持つ
    • CardはRankを持つ
  • Cardのインスタンスから文字列表記(notation)を取得する

今回やったこと、理解したこと

  • TODOリストを書いて、取り組むべき問題を細分化した
  • テストの失敗か環境によるものかを切り分ける為に、テストを書き始める前にプロジェクトのテストを一度実行した
  • テストケースから考えることで、型をうまく利用し、考慮しなければならないテストケースを減らした
  • レッド > グリーン > リファクタリング まで一貫して行った

まとめ

今回やったことのようなシンプルなinitは、実際、テスト対象にはならないようなものだそうです。次節において、本格的なTDDが始まると思いますので、引き続き、頑張っていきましょう。

参考

演習問題
http://devtesting.jp/tddbc/?TDDBC%E4%BB%99%E5%8F%B007%2F%E8%AA%B2%E9%A1%8C

サンプルリポジトリ
https://github.com/ktanaka117/TDDPokerBySwift

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2