Xcodeのテスト機能を触ってみた（macOS/Objective-C）

# 概要
- Xcodeのユニットテスト・UIテストの基本を触ってみました。

# 参考
- 【書籍】レベルアップObjective-C
- [Objective\-CでUITestを利用してスクリーンショットを撮る方法](https://qiita.com/BlackCat/items/4e9bb52e0c0189d9105e)
- [【Xcode】XCUITest \+ fastlane/snapshotで始めるUIテスト（前編） \- 文系プログラマの勉強ノート](http://an.hatenablog.jp/entry/2017/06/11/000000)

# 手順
## プロジェクトの作成
- 今回はmacOSアプリを、言語はObjective-Cで作成する

![-w719](https://i.imgur.com/UmtBY0e.jpg)

- テストをするので下記にチェック

![-w717](https://i.imgur.com/iwPTR6R.jpg)

## UnitTestの作成

- `MyCalc.h/m`を作成
- これに関数を追加し、UnitTestで確認する。

![-w718](https://i.imgur.com/nbav0G7.jpg)

### Code
- 被テスト対象関数を書くためのクラス`MyCalc.h/m`を作成する

```objc:MyCalc.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyCalc : NSObject
@property int valueA;
@property int valueB;
- (int)calcAdd; // A+Bを返すだけ
@end

NS_ASSUME_NONNULL_END
```



```objc:MyCalc.m
#import "MyCalc.h"

@implementation MyCalc

- (int)calcAdd {
    return self.valueA + self.valueB;
}

@end
```

- `UnitAndUITestSampleTests.m`に下記を追加
- `XCTAssertEqual`の他にも様々なテスト用の関数があるので、必要なものを使う。

```objc:UnitAndUITestSampleTests.m
- (void)testCalcAdd {
    MyCalc *calc = [MyCalc new];
    calc.valueA = 3;
    calc.valueB = 4;
    XCTAssertEqual([calc calcAdd], 7, @"Adding Test Error");
}
```

- なお、`MyCalc.h`がインポートできない場合は下記の通りに指定するといけた。
- もしくはクラス作成時にターゲットにUnitTestsを指定するとうまくいく？

```objc:UnitAndUITestSampleTests.m
#import "../UnitAndUITestSampleTests/MyCalc.h"
```

### ユニットテストの実行
- 全体のテストはProductタブのTestから行う（ショートカット`Command+U`）
- 先程の追加した関数のみテストしたいなら、下のチェックボックスをクリックすると良い。

![-w1059](https://i.imgur.com/LscoGZ9.jpg)

- エラーの場合は以下のように警告がでる。

![-w1408](https://i.imgur.com/6w9FU3i.jpg)

## UITestの作成
### Code
- `UnitAndUITestSampleUITests.m`に下記を追加

```objc:UnitAndUITestSampleUITests.m
- (void)testTakeScreenShot {
    XCUIApplication *app = [[XCUIApplication alloc] init];
    [app.buttons[@"button"] click];
    XCUIScreen *screen = [XCUIScreen mainScreen];
    XCUIScreenshot *screenShot = [screen screenshot];
    XCTAttachment *attachment = [XCTAttachment attachmentWithScreenshot:screenShot];
    attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
    attachment.name = @"tapped-button";
    [self addAttachment:attachment];
}
```

- 注意すべきは、TouchBarがあるMacBookProではボタン押下のアクションが`tap`ではなく`click`であること。（エラーとなりました）
- TouchBarがある場合

```objc
[app.buttons[@"button"] click];
```

- TouchBarがない場合

```objc
[app.buttons[@"button"] tap];
```

### xib

- 下記は`Accessibility Identify > Identifier`の設定値が`button`のボタンを取得し、クリックする、の意。

```objc
[app.buttons[@"button"] click];
```

- `Accessibility Identify > Identifier`はxibの以下で設定する。

![-w851](https://i.imgur.com/o2hrwXQ.jpg)

### UIテストの実行
- UnitTestと同様
- 全体のテストはProductタブのTestから行う

### スクリーンショットの確認

- 下記を選択すると画像が確認できる。

![-w757](https://i.imgur.com/h1Xr9Kw.jpg)

- スクリーンショットは以下の場所にある。（`.xcresult`は右クリックから中を見れる）
    - 余談：ファイルを探したい場合は`find`コマンドが便利。

```sh
sudo find / -name \tapped-button*
```

![-w971](https://i.imgur.com/ujtsdoI.jpg)

`/Users/<ユーザ名>/Library/Developer/Xcode/DerivedData/UnitAndUITestSample-<文字列>/Logs/Test/Test-UnitAndUITestSample-2019.10.31_18-03-18-+0900.xcresult/Attachments/tapped-button_1_4DF1C594-BF62-41DA-8980-D685B3F3EE66.png`

# Xcode11からのテスト周りの変更点
- 下記にXcode11からの変更点が、詳細に分かりやすく書かれています。
- [Xcode 11でのテスト周りの新機能を紹介します！ \- DeNA Testing Blog](https://swet.dena.com/entry/2019/10/23/080000)
- 例えばスクリーンショットの保存場所が変わっています。
    - e.g.

`/private/var/folders/xg/cbzvh5m16dd8n9dp6975xy7m0000gn/T/IDEResultCache/0~pf6CNubPm2J2g_F-WEZQfSXp4KERDiMmyMAT7A-Hgl_Bffp3uQmgiUN0NbxxiyR_3jyGqBUAHdQwrsEg8lSCaw==/tapped-button_1_5868A1BF-3F54-4D57-89E8-BB3F69459377.png`