Open9

iOS開発でテストを書くときのTipsやメモ

urourourouro

iOSアプリ開発をTDDで進めたり、テストの無いコードにテストを入れたりすることが多いので、知見だな〜と思ったことや参考になった記事などを書いていければと思います。

urourourouro

よく使うショートカット

  • Cmd + U : すべてのテストを実行
  • Ctrl + Alt + Cmd + G : 最後に実行したテストを再実行
    • TDDでRed-Green-Refactorとやってるとめちゃくちゃ使う
  • Ctrl + Alt + Cmd + U : カーソル乗ってるところのテストを実行

これらはメニューの Product や Product > Perform Action からも実行できる

  • Cmd + Ctrl + ↑ / Cmd + Ctrl + ↓ : ファイルの移動
    • 対応するファイルを開く
    • Swift だとテストファイル <-> 実装ファイルを行き来できる
    • Obj-C だとヘッダファイル <-> 実装ファイル <-> テストファイルを行き来できる
urourourouro

XCTAssertEqual は expectedが先か?actualが先か?

https://masilotti.com/xctest-tips-and-tricks/
この記事で少し言及があってふと気になった。

特に決まっている感じは無い?
XCTest だと actual が先の方が多い?
なお実際にはどちらかと言うより、↑記事で言われている通りプロジェクトで統一されていることの方が大事だと思う。

http://xunitpatterns.com/Assertion Method.html#Equality Assertion
xUnit Patterns だと expected, actual の順。

https://developer.apple.com/documentation/xctest/2142776-xctassertequal
XCTAssertEqualのドキュメントにあるコードだと actual, expected の順に書かれている。

https://github.com/apple/swift-corelibs-xctest/blob/main/Sources/XCTest/Public/XCTAssert.swift#L132
swift-corelibs-xctest の XCTAssert のコメントは actual, expected の順に書かれている。

https://github.com/apple/swift-corelibs-foundation/search?q=XCTAssert
swift-corelibs-foundation でも actual が先のテストの方が多い気がする。

urourourouro

XCTestでの話。

テストメソッド1つだけを実行したい場合

  • キーボードショートカットの Ctrl + Alt + Cmd + U を使う
  • メニューの Product > Perform Action > Run "testXXX()" を使う
  • Source Editor 上の Run Button を使う
    • ここの再生ボタンのようなやつ
  • Test Navigator から実行する
    • 左ペインにあるテストクラス・テストメソッド一覧

see: Running Tests and Viewing Results

複数のテストメソッドを選んで実行したい場合

Test Navigator で Shift で複数選択して右クリックすると、"Run N Test Methods" という項目が出る。
ここで選んだテストだけ実行できる。

ただしテストがいっぱいあると実行したいテストを探すのに時間がかかるときがある。
そんなときは Source Editor の Run Button を右クリックすると出てくるメニューの "Reveal in Test Navigator" を使うと、該当するテストを Test Navigator 上で選択状態にしてくれる。いくらか選びやすい。

urourourouro

テスト用のオブジェクト生成をやりやすくする

https://medium.com/bleeding-edge/writing-better-unit-tests-in-swift-part-one-e4a06fbc682b

この記事で紹介されていた方法。
Model や Entity のようなクラスに .create() メソッドを生やすことで、テストするときのデータ生成を簡単にする。

let user1 = User(id: 1, name: "Example", imageURL: URL(string: "https://example.com")!, ...
let user2 = User(id: 2, name: "Example", imageURL: URL(string: "https://example.com")!, ...
let user3 = User(id: 3, name: "Example", imageURL: URL(string: "https://example.com")!, ...

みたいなデータ生成があるとき、

extension User {
    static func create(
        id: Int = 1
        name: String = "Example",
        imageURL: URL = URL(string: "https://example.com")!
    ) -> User {
        User(
            id: id,
            name: name,
            imageURL: imageURL
        )
    }
}

な extension を書いておくと、

let user1 = User.create()
let user2 = User.create(id: 2)
let user3 = User.create(id: 3)

な感じに簡略化できる。
factory_bot っぽい。