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

#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クラスが存在しないためのコンパイルエラーです。
<img width="746" alt="スクリーンショット 2019-08-08 16.03.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468725/264b0239-2b4c-0826-ccfa-8bd04b0aab6a.png">

Cardクラスを作成しましょう。今回もMVVMで作成していければと思いますので、
Project Navigator > TDDPokerBySwiftグループ > 右クリック > New Groupで、
- Models
- Views
- ViewControllers
を作成して、Models/Card.swiftを作成します。
<img width="268" alt="スクリーンショット 2019-08-08 16.07.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468725/b7b43cc3-f50d-a6a7-ede9-9b2fdd2b1a38.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リストにチェックを入れます。

- [x]  Cardを定義して、インスタンスを作成する
 - [x]  CardはSuitを持つ
 - [x]  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://dev.classmethod.jp/event/twadatddworkshopsappororeport/

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