LoginSignup
68
53

More than 5 years have passed since last update.

iOSアプリにおけるTDD(テスト駆動開発)

Last updated at Posted at 2017-09-03

はじめに

先日、Yahoo! JapanのiOS黒帯インターンに参加させていただいたので、そこで利用されていた『TDD(テスト駆動開発〕』という開発手法を簡単にまとめてみました。

また、今回はSwift3で実装しています。Xcodeを事前にインストールしておきましょう。

ちなみに、インターン自体の感想などはブログの方にアップしているので、興味のある方はぜひご覧ください。
Yahoo!iOS黒帯インターンでの思い出

テスト駆動開発(TDD)

テスト駆動開発とは

テスト駆動開発は,小さなステップを繰り返してプログラムの設計と開発を行っていくソフトウェア開発手法です。テスト駆動開発は次の3ステップから構成されています。

  1. テストを書く
  2. 最低限の実装をする
  3. リファクタリング

(参考文献: 和田卓人のテスト駆動開発講座

もう少し詳しくみてみましょう。

テスト駆動開発の進め方

テスト駆動開発では、下の画像のように3つのステップに沿って開発を進めていきます。
テスト駆動開発.001.jpeg

1. テストを書く

テスト駆動開発では、まずはじめに追加したい機能のテストを書きます。ここでの「テスト」とは、開発者がコードで書くテスト用プログラムのことです。テストを書くことで、実装したものが正常に動いているかを自動で確認できます。

このときに大事なことは、「テストを一つだけ書く」ことです。
テスト駆動開発では機能の一つ一つを小さく作り洗練させていくことで、開発スピードと実装の正当性を実現しています。なのでTDDで開発をする際は、できるだけ「小さく」開発することが必要です。

出来上がったテストを実行してみると必ず「失敗」します。これは当たり前で、実現したい機能の最終形をテストで書いても実装はまだしていないからです。
テスト駆動開発ではこの状態を「Red(失敗)」といいます。

2. 最低限の実装をする

テストが書けたら次は実装を行います。ここで大事なことは「最低限の実装をする」ことです。
コードの再利用性や設計の美醜を考えるのではなく、テストが通るもっともシンプルな実装をします。
これによって、余計なことを考え作業を中断したことで開発スピードが落ちることはなくなります。

実装が正しく行われていれば、この時点でテストが通ります。
テスト駆動開発ではこの状態を「Green(成功)」といいます。

3. リファクタリング

実装をしたことでテストが通るようになり、機能が実現できました。しかし、最低限の実装をしたことでコードに無駄があったり愚直過ぎるコードだったりと,いくつか直したい点があると思います。

テスト駆動開発では、テストが通るままの状態でコード内部の設計をよくしていきます。このような作業のことを「リファクタリング」といいます。
リファクタリングすることで、ソースコードの重複や実装の最適化が行われ、メンテナンスなどがしやすくなります。

テスト駆動開発の流れが分かってきたと思うので、次は具体的にiOSでのテスト駆動開発がどのように行われるかみてみましょう。

iOSでのテスト手法

XCTest

XCTestとは、Xcode5から導入されたテストフレームワークです。iOS上でUnitTestを行う際にはよく使われますね。他にも外部テストフレムワークが存在しますが、今回はこちらのフレームワークを使ってみます。

Quick

quick.png

Quickは、SwiftObjective-Cのためのビヘイビア駆動開発フレームワーク(BDD Framework)です。
簡単にいうと、Xcode上でテストを書くための外部フレームワークです。

ビヘイビア駆動開発フレームワークについての説明はここでは省略させていただきます。

今回は使用しませんが、有名なので覚えておくといいでしょう。

実装

作りたいもの

helloQiita.png
今回は、スクリーン上に「Hello, Qiita.」が表示されるようにしましょう。

1. テストを書く

現在は上記画像のように「Hello, World.」が表示されていることにします。
helloWorld.png

では、テストを書いてみましょう。
Screen Shot 2017-09-03 at 15.20.41.png
「TestSample」というプロジェクトで行いたいと思います。まずは、左側のNavigation AreaからTestSampleTests.swiftを開きます。

TestSampleTests.swift
import XCTest
@testable import TestSample

class TestSampleTests: XCTestCase {

    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testLabelTitle() {
        let storyBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let viewController = storyBoard.instantiateViewController(withIdentifier: "viewController") as? ViewController

        viewController?.viewDidLoad()

        XCTAssertEqual(viewController?.label?.text, "Hello, Qiita.")

    }

初期のViewControllerにlabelという名前のUILabelが存在するので、それのtextがHello, Qiita.になっているはずというテストを書きました。

実際にテストを実行してみましょう。テストは⌘ + Uで実行できます。
Screen Shot 2017-09-03 at 16.30.12.png

テストが失敗(RED)してしまいました。では次に、テストが通るよう実装をしていきましょう。

2. 最低限の実装をする

今回のテストは、viewControllerがもつUILabeltextが「Hello, Qiita.」となることだったので、そうなるように実装を変更してみましょう。

ViewController.swift
import UIKit

class ViewController: UIViewController {

    var label: UILabel?

    override func viewDidLoad() {
        super.viewDidLoad()

        label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
        label?.center = CGPoint(
            x: self.view.frame.width  / 2,
            y: self.view.frame.height / 2
        )
        label?.textAlignment = .center
        label?.text = "Hello, World."

        self.view.addSubview(label!)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

現在のViewControllerクラスはこのような実装になっています。UILabelのtextを変更してみましょう。

label?.text = "Hello, Qiita."

では改めてテストを実行してみましょう。
Screen Shot 2017-09-03 at 16.38.51.png

テストが成功(Green)しました!では最後にリファクタリングをしましょう。

3. リファクタリング

リファクタリングでは、重複しているソースコードをまとめたり、視覚的にみやすくすることでメンテナンスを行いやすいようにします。

今回の例では特にリファクタする場所がないので、これで完了です。

感想

iOSでのテスト駆動開発(TDD)はどうだったでしょうか。実装より先にテストを書くので慣れるまで大変だと思いますが、慣れればこちらの方が開発が安全かつスムーズに行えそうですね。

ちなみにUILabelなどのUIKitのテストを書く際にはUITestというフレームワークを利用すると簡単にかけるらしいので、今後はそちらも試してみようと思います。

インターン自体の感想などはブログの方にアップしているので、興味のある方はぜひご覧ください。
Yahoo!iOS黒帯インターンでの思い出

参考文献

今回のQiitaを書くにあたり、下記のサイトを参考にさせていただきました。ありがとうございました。
Apple Document - XCTest
和田卓人のテスト駆動開発講座
市場で勝ち続けるための品質とテストの技術 by 山下 真一郎

サンプルファイル

今回使用したXcodeファイルはGithubにあげてあるので、ぜひ参考にしてください。
Github:サンプルファイル

68
53
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
68
53