waveさんの技術日誌

wave1008の日記の新館です。

Shiratesを使ってみよう - 画面ニックネーム -

Shirates画面ニックネームを紹介します。

こちらの記事の翻訳です。 dev.to

画面ニックネーム(Screen Nickname)

Shiratesでは画面ニックネームJSONファイルで定義することができます。画面ニックネームはテストコードを読みやすく生産性を高いものにします。

画面ニックネームの機能

サンプルコードの入手

本記事で説明するサンプルコードの完成版はこちらから入手してください。 https://github.com/wave1008/shirates-samples-nicknames

Example 1: 電卓

  • Appium Inspectorを起動します
  • Calculatorアプリをキャプチャします

  • [電卓メイン画面].jsontestConfig/screens/calculatorディレクトリの下に作成します

  • Appium Inspectorを使用して画面の要素を調査し、画面ニックネームファイルを以下のように編集します

[電卓メイン画面].json

{
  "key": "[電卓メイン画面]",

  "identity": "[AC][()]",

  "selectors": {
    "[計算式]": "#formula",
    "[計算結果]": "#result_final",
    "[計算結果プレビュー]": "#result_preview",

    "[√]": "#op_sqrt",
    "[π]": "#const_pi",
    "[^]": "#op_pow",
    "[!]": "#op_fact",

    "[AC]": "#clr",
    "[()]": "#parens",
    "[%]": "#op_pct",

    "[÷]": "#op_div",
    "[×]": "#op_mul",
    "[-]": "#op_sub",
    "[+]": "#op_add",
    "[=]": "#eq",
    "[⌫]": "#del",

    "[0]": "#digit_0",
    "[1]": "#digit_1",
    "[2]": "#digit_2",
    "[3]": "#digit_3",
    "[4]": "#digit_4",
    "[5]": "#digit_5",
    "[6]": "#digit_6",
    "[7]": "#digit_7",
    "[8]": "#digit_8",
    "[9]": "#digit_9",
    "[.]": "#dec_point"
  }

}

テスト実行時に"[AC][()]"の識別子によって[電卓メイン画面]を識別できるように成ります。 例えば、現在表示中の画面が[電卓メイン画面]であることを以下のように検証することができます。

it.screenIs("[電卓メイン画面]")

CalculatorTest

以下は画面ニックネームなしの場合とありの場合の電卓のテストコードです。画面ニックネームなしの場合、resource-idのような低レベルの識別子を使用する必要があります。一方、画面ニックネームありの場合、抽象化された画面ニックネームセレクターニックネームを使用することができます。

package calculator

import org.junit.jupiter.api.Order
import org.junit.jupiter.api.Test
import shirates.core.driver.commandextension.*
import shirates.core.testcode.UITest

class CalculatorTest : UITest() {

    @Test
    @Order(10)
    fun withoutNickname() {

        scenario {
            case(1) {
                condition {
                    it.tapAppIcon("電卓")
                }.expectation {
                    it.exist("#clr")
                    it.exist("#parens")
                }
            }
            case(2) {
                action {
                    it.tap("#clr")
                }.expectation {
                    it.select("#formula")
                        .textIsEmpty()
                    it.select("#result_preview")
                        .textIsEmpty()
                }
            }
            case(3) {
                action {
                    it.tap("#digit_1")
                }.expectation {
                    it.select("#formula")
                        .textIs("1")
                    it.select("#result_preview")
                        .textIsEmpty()
                }
            }
            case(4) {
                action {
                    it.tap("#op_add")
                }.expectation {
                    it.select("#formula")
                        .textIs("1+")
                    it.select("#result_preview")
                        .textIsEmpty()
                }
            }
            case(5) {
                action {
                    it.tap("#digit_2")
                }.expectation {
                    it.select("#formula")
                        .textIs("1+2")
                    it.select("#result_preview")
                        .textIs("3")
                }
            }
            case(6) {
                action {
                    it.tap("#eq")
                }.expectation {
                    it.select("#result_final")
                        .textIs("3")
                }
            }
        }
    }

    @Test
    @Order(20)
    fun withNickname() {

        scenario {
            case(1) {
                condition {
                    it.tapAppIcon("電卓")
                }.expectation {
                    it.screenIs("[電卓メイン画面]")
                }
            }
            case(2) {
                action {
                    it.tap("[AC]")
                }.expectation {
                    it.select("[計算式]")
                        .textIsEmpty()
                    it.select("[計算結果プレビュー]")
                        .textIsEmpty()
                }
            }
            case(3) {
                action {
                    it.tap("[1]")
                }.expectation {
                    it.select("[計算式]")
                        .textIs("1")
                    it.select("[計算結果プレビュー]")
                        .textIsEmpty()
                }
            }
            case(4) {
                action {
                    it.tap("[+]")
                }.expectation {
                    it.select("[計算式]")
                        .textIs("1+")
                    it.select("[計算結果プレビュー]")
                        .textIsEmpty()
                }
            }
            case(5) {
                action {
                    it.tap("[2]")
                }.expectation {
                    it.select("[計算式]")
                        .textIs("1+2")
                    it.select("[計算結果プレビュー]")
                        .textIs("3")
                }
            }
            case(6) {
                action {
                    it.tap("[=]")
                }.expectation {
                    it.select("[計算結果]")
                        .textIs("3")
                }
            }
        }
    }
}

テスト結果

画面ニックネームなし画面ニックネームありのテスト結果を確認して比較してみてください。画面ニックネームありの方が理解しやすいことがわかると思います。

_Report(simple).html

CalculatorTest@a.xlsx


まとめ

Shiratesでは画面ニックネームJSONファイルで定義することができます。画面ニックネームはテストコードを読みやすく生産性を高いものにします。