EarlGreyのコードにQuickのコードを付け合わせて可読性を上げる


例えばこんなUITestコードがある場合、若干見にくいかと思います

```swift

import XCTest
import EarlGrey

@testable import QiitaPresents

class QiitaPresentsTests: XCTest {
  
  
  func testButton() {
    EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
    
    EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_selected())
    
    var success: Bool = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
      var error: NSError?
      
      EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Hoge"), error: &error)
      
      return error == nil
      }.wait(withTimeout: 5)
    
    GREYAssertTrue(success, reason: "Hogeに変わらなかった、、、、")

    EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
    
    EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_not(grey_selected()))
    
    success = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
      var error: NSError?
      
      EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"), error: &error)
      
      return error == nil
      }.wait(withTimeout: 5)
    
    GREYAssertTrue(success, reason: "Fugaに変わらなかった、、、、")

  }
}


```

こんな時はEarlGreyとQuickを併用して使うようにしましょう。

# Quickのdescribe/context/itを使おう！

先ずは、describe/context/itを使いましょう。
そうするとかなり可読性が上がると思います

各Quickメソッドの引数(String型)は以下のように書きます。

`describe`: どんなテストか
`context` : どんな条件のテストをするのか
`it`      : 期待する動作は何か

```swift:

import EarlGrey
import Quick

@testable import QiitaPresents

class QiitaPresentsTests: QuickSpec {
  
  override func spec() {
    describe("画面テスト") {
      context("メイン画面上") {
        it("Hogeが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_selected())
          
          let success: Bool = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Hoge"), error: &error)
            
            return error == nil
          }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
        
        it("Fugaが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_not(grey_selected()))
          
          let success = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"), error: &error)
            
            return error == nil
          }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
      }
    }
  }
}

```

# `beforeEach`/`afterEach`を使ってテストの前後で確認したい事を書こう！

Quickには各`it`テストの始まりの前と終わりの後に処理を挟むことができます。
`beforeEach`: `it`テストの前に処理を行う
`afterEach` : `it`テストの後に処理を行う

```swift:例

import EarlGrey
import Quick

@testable import QiitaPresents

class QiitaPresentsTests: QuickSpec {
  
  override func spec() {
    describe("画面テスト") {
      
      beforeEach {
        /// ラベルが表示されているか確認
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_sufficientlyVisible())
      }
      
      afterEach {
        /// ラベルが表示されているか確認
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_sufficientlyVisible())
      }
      context("メイン画面") {
        it("Hogeが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_selected())
          
          let success: Bool = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Hoge"), error: &error)
            
            return error == nil
            }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
        
        it("Fugaが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_not(grey_selected()))
          
          let success = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"), error: &error)
            
            return error == nil
            }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
      }
    }
  }
}

```

今回は、`grey_sufficientlyVisible()`を使っていますが（アホみたいな例です。すいません）、お好きな処理を記述してください。

# `beforeSuite`/`afterSuite`を使ってテストの最初と最後に確認を行う。

`beforeEach`/`afterEach`とはまた別に、テストの最初と最後に処理を挟むことができます。
`beforeSuite`: テストを行う前に処理を行う
`afterSuite` : テスト行った後に処理を行う

```swift:例

import EarlGrey
import Quick

@testable import QiitaPresents

class QiitaPresentsTests: QuickSpec {
  
  override func spec() {
    describe("画面テスト") {
      
      beforeSuite {
        /// テスト前は"Fuga"か
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"))
      }

      afterSuite {
        /// テスト後は"Fuga"か
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"))
      }

      beforeEach {
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_sufficientlyVisible())
      }
      
      afterEach {
        EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_sufficientlyVisible())
      }
      
      context("メイン画面") {
        it("Hogeが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_selected())
          
          let success: Bool = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Hoge"), error: &error)
            
            return error == nil
            }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
        
        it("Fugaが表示されるか") {
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).perform(grey_tap())
          
          EarlGrey.select(elementWithMatcher: grey_kindOfClass(UIButton.self)).assert(grey_not(grey_selected()))
          
          let success = GREYCondition(name: "値が変わるまで5秒間待つ") { () -> Bool in
            var error: NSError?
            
            EarlGrey.select(elementWithMatcher: grey_accessibilityID("resultLabel")).assert(grey_text("Fuga"), error: &error)
            
            return error == nil
            }.wait(withTimeout: 5)
          
          GREYAssertTrue(success, reason: "値が変わらなかった、、、、")
        }
      }
    }
  }
}
```

これを使えばUITest前にAPIを叩いて、画面の準備を行うことができるかと思います。


# お願い
間違い箇所などがある場合は、指摘していただけると嬉しいです

# 最後に

いかがでしたでしょうか。
Quickはテストをするタイミングをコントールできるので、EarlGreyと併用すると楽にテストコードが書けるかと思います。
よかったら試してみてください。

※一応、クソースコドを載せておきます。

```swift
import UIKit

class ViewController: UIViewController {

  @IBOutlet weak var resultLabel: UILabel!
  @IBOutlet weak var button: UIButton!
  
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    
    resultLabel.accessibilityIdentifier = "resultLabel"
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }
  @IBAction func didPushButtoon(_ sender: Any) {
    
    button.isSelected = !button.isSelected
    
    resultLabel.text = button.isSelected ? "Hoge" : "Fuga"
  }
}
```

#おまけ
もし、`afterSuite`/`beforeSuite`が使えなかった場合は以下のメソッドを変わりに書きましょう。

```swift
class QiitaPresentsTests: QuickSpec {

   /// テストの前に処理を行う
  class func setUp() {
    /// 処理
  }
  
  /// テストの後に処理を行う
  class func tearDown() {
    /// 処理
  }
}
```

代わりに使えるかと思います。