Help us understand the problem. What is going on with this article?

UnityでuGUIのUIテストを自動化

More than 1 year has passed since last update.

これはUnity 4.6から導入された新UI、uGUIでのUIテストの自動化方法の紹介です。

前提

チームで開発をしていると困るのが動かなくなるコミット。
「何もしていないのに急に動かなくなった」「git pullしたらボタン遷移しなくなった」経験ありませんか?困りますよね?
そこでUIテストを自動化すればそのような悩みを少し解消できますよ!

UIテスト自動化の仕組み

正常に動く時に「タップ操作を記録」して、随時「タップ操作の再生」を行い「テストの結果判定」で問題があれば通知する、という方法でやってみます。

タップ操作の記録

単純に毎フレームタップイベントがないか判断します。1
次にuGUIの「EventSystem.current.currentSelectedGameObject」を参照し、タップされたGameObjectを取得できます。
これでXY座標とGameObjectが手に入るので、タップ操作の記録ができました。
合わせてSystem.Diagnostics.Stopwatchを使ってタップ間隔も保持しておくと再生時に役立ちます。

IEnumerator record()
{
    var timer = System.Diagnostics.Stopwatch.StartNew();
    while (true)
    {
        yield return null;
        if (!Input.GetMouseButtonDown(0))
        {
            continue;
        }

        var go = EventSystem.current.currentSelectedGameObject;
        if (go == null)
        {
            Debug.Log("クリックされたけどUI部品は見つからなかった");
            continue;
        }

        var p = Input.mousePosition;
        Debug.Log(string.Format("クリック座標={0}x{1} クリックされたGameObject={2} 経過時間={3}",
            p.x,
            p.y,
            go.name,
            timer.Elapsed.TotalSeconds));
    }
}

タップ操作の再生

再生の方はuGUIのEventSystemを色々と使います。
まずPointerEventDataでイベントインスタンスを作って、そこにタップ座標などの情報を設定し、EventSystem.current.RaycastAll()で当たり判定を行い、第二引数のresultsにヒットしたUI要素の一覧が格納されます。
あとはresultsの各要素に対してExecuteEvents.Execute()でイベントを発行すればOK。

以下の例では指定したXY座標にあるuGUIのButtonコンポーネントのOnClick()が実行されるようイベントを送信します。1

void play(int x, int y)
{
    var ev = new PointerEventData(EventSystem.current);
    var results = new List<RaycastResult>();
    ev.position = new Vector2(x, y);
    ev.button = PointerEventData.InputButton.Left;
    EventSystem.current.RaycastAll(ev, results);
    foreach (var result in results)
    {
        ExecuteEvents.Execute<IPointerClickHandler>(
            result.gameObject,
            ev,
            (handler, eventData) => handler.OnPointerClick((PointerEventData)eventData));
    }
}

テストの結果判定

EventSystem.current.RaycastAllで取得できる要素にGameObjectがありますので、このGameObjectが期待したものであればテストは成功、そうでなければテスト失敗としてもいいです。
さらにタップイベント送信時にApplication.CaptureScreenshotを使えば、自動でどんどんタップさせながら画面キャプチャを保存できテスト内容が視覚的に分かりやすくなります。画面キャプチャはテスト失敗時にも役立つでしょう。

まとめ

非常に短いコードでタップの記録と再生が実装できました。
uGUIは本当に便利ですね![^2]


  1. 動作確認しやすいよう左クリックでの判定でコードを載せましたがiPhoneとかで動作させるにはInput.Touchesを参照します 

tadokoro
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした