プログラミング教室で iOS アプリの作り方を説明しました. その4

[前回](http://qiita.com/mironal/items/5080248a73f75c96fbd6)
---

## 概要

今回は Xcode の AutoLayout 機能を使って UI をデザインする方法とテストについて説明しました。

画面を作る -> その画面をテストするという流れです。

今回も諸事情でほぼマンツーマンで教える形でした。

## やること

### UI デザイン

StoryBoard で AutoLayout を使って UI を組み立てます。

作ったのは以下の様な画面です。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/03b52407-8834-91cd-a2a1-3ab130dc5ec9.png)

階層構造は以下の様な状態ですカッコ内にどのパーツかのヒントを書いてあります。

```
UIView
  - UIView (ピンク色の部分)
    - UIButton (押す！)
    - UILabel (押す前)
  - UIView (緑色の部分)
    - UITextField (TextField)
    - UIButton (入力)
    - UILabel (label)
```

### テスト

テストは Unit Test と UI Test の説明を行いました。

今回のメインは AutoLayout だったのでテストは簡単に動作を確認する程度の説明でした。

## 進め方 (1時間程度)

### UI デザイン

まずは先ほど示した画面を何もヒント無しに組み上げてもらいました。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/03b52407-8834-91cd-a2a1-3ab130dc5ec9.png)


その状態でシミュレーターで起動してもらって以下のようにレイアウトが崩れることを確認しました。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/60fbf8de-f42f-14d8-e186-39b40c1380a3.png)

その後、 AutoLayout の使い方の説明を行いました。

画面右下にある小さいこのボタンを駆使していい感じに設定をしていきます。 Control ボタンを押しながらドラッグする方法も説明しました。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/7781b6cb-8645-2da9-99d1-07f70c197ef9.png)

アプリを起動しなくても Preview の機能を使って各画面サイズでどのように表示されるのかの確認方法も説明しました。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/dfba7a3c-0a85-5fe3-b579-249e55af3503.png)

そんなこんなで正しく AutoLayout の設定を行うと以下のように各画面サイズで正しく表示できました。

![image](https://qiita-image-store.s3.amazonaws.com/0/17704/4435d79c-3260-d238-fdae-de31b84af9c3.png)

シミュレーターでも確認してひとまず完了です。

この段階では横画面にした時にレイアウトが崩れてしまうのでそれにも対応させようと思いましたが、時間的に足りなそうだったのでテストの話に移りました。

AutoLayout はパズルのように設定を組み立てていくのでお題を用意して後は考えて組んでもらうとゲームのようで面白いのかなと思いました。

### テスト

まずは Unit Test の説明をしました。 


ここでは Xcode でのテストがどのような機能なのかを確認することをメインとして以下の様なコードを書いて `setUp()` などがどのタイミングで呼ばれるかを確認しました。

次に `add` メソッドを用意して最初は間違えた値を返すようにして `XCTAssertEqual` でテストが失敗することを確認した後に `add` メソッドを修正してテストが成功することを確認しました。

```swift
import XCTest
@testable import TestTest

class TestTestTests: XCTestCase {

    override func setUp() {
        super.setUp()
        // 各テストの前に実行される
        print("setup")
    }

    override func tearDown() {
        // 各テストの後に実行される
        print("tearDown")
        super.tearDown()
    }

    // テストメソッド
    func testExample() {

        let a = 1
        let b = 2

        // 3 になってて欲しい
        let sum = add(a, b: b)

        XCTAssertEqual(sum, 3)
    }

    // 別のクラスにあるメソッド
    func add(a: Int, b: Int) -> Int {
        return a + b
    }

    // テストメソッド
    func testHoge() {

        print("2")
    }
}
```

次に UI テストを行いました。

UI テストは画面上のボタンをタップしたり、テキストフィールドに文字を入れたりする動作をシミュレートしながら画面が正しく機能しているのかを自動的にテストする機能です。

以下の動画を見るとどのように動作するものなのかイメージできると思います。

[https://youtu.be/A0klH3VmPkA?t=1m21s](https://youtu.be/A0klH3VmPkA?t=1m21s)

さらに画面上の UI パーツを取得する方法として `UI recording` という機能があることを説明しました。

この辺りは時間がなかったので駆け足な説明になってしまいました。

## まとめ

AutoLayout は画面上でどんどん出来上がっていくので面白かったのかなと思います。

テストはテストの必要性についての質問が度々出ましたが納得の行く回答ができませんでした。

サンプルで示すような簡単な例ではそもそもテストの必要性を感じ取ってもらえなかったためテストが重要であることが理解できるようなシナリオが必要だと思いました。

また機会があれば以下の様なことを例にあげて説明していこうかなと思います。

- ある程度複雑なモジュールが正しく動くことを示す上でテストの有用性
  - このある程度複雑なという程度が難しい
- 既存コードをリファクタリングする上でのテストの有用性
- バグを示す上でのテストの有用性


## 授業風景

![IMG_8654.jpg](https://qiita-image-store.s3.amazonaws.com/0/17704/94d42a48-a5e2-0c42-c291-d38e4a5e93d2.jpeg)