Posted at

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

More than 1 year has passed since last update.

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


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 : 期待する動作は何か


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テストの後に処理を行う




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 : テスト行った後に処理を行う




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と併用すると楽にテストコードが書けるかと思います。

よかったら試してみてください。

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

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が使えなかった場合は以下のメソッドを変わりに書きましょう。

class QiitaPresentsTests: QuickSpec {

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

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

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