• 13
    Like
  • 0
    Comment

この記事は、Xamarin(その2) Advent Calendar 2016 の18日目の記事です。
Xamarin Test Recoderを使ってできることを一通り試してみたいと思います。

Why Xamarin Test Recorder

モバイル向けのUIテストフレームワークとして有名なところでAppiumがあります。
AppiumはC#、Java,JSなど多様な言語でUIオートメーションテストを行うことができますが、
Appium.App(exe)というスタンドアロンアプリで、UIオートメーションテストを行うために必要なテストコードを自動で生成してくれる補助ツールもあります。
これがなかなかイケていて、アプリをぽちぽち操作するだけでテストコードを自動生成してくれます。

一方、Xamarin社が提供するテストフレームワークには、Rubyで記載するCalabashやC#で記述するXamarin.UITestがあります。
いずれもUIオートメーションのためのフレームワークとしてやれることはAppiumとあまり変わりませんが、テストコードを記述するには、REPLなどを使って調査しながら書いていく形であり、それ自体にはAppium.Appのようなテストコード自動生成機能はありません。

そこでXamarin Test Recorderですよ!

Xamarin Test Recoderとは

概要

Xamarin.UITestでのUIオートメーションテストを行うために必要なテストコードを自動で生成してくれる補助ツールです。
https://www.xamarin.com/test-cloud/recorder

できること

  • Simulatorを利用したUIテストのレコーディング
  • 実機を利用したUIテストのレコーディング
  • Xamarin.UITestコードのエクスポート
  • Xamarin Test Cloudへのアップロード

提供形態

OS 提供形態 ライセンス
Windows VS2013 or VS2015 の拡張機能 VS Enterprise subscription
Mac Xamarin Test Recorder(スタンドアロンアプリ)

必要条件

項目 iOS Android 備考
Minumum Ver 8.0〜 4.3 (API level 19)
Package App(Simulator),IPA(実機) APK

Xamarin Test Recoderの画面構成

アプリを開くと、4ペインで構成されています。
TestRecorder-parts-xs.png

①でレコード開始と停止、再生とファイル出力ができます。
②レコード対象のデバイスとアプリを指定します。
③レコーダーによって記録された操作が表示されます。
④レコーダーによって記録された操作がC#コードに変換されたものが表示されます。

それでは、実際に試してみましょう。

Xamarin Test Recorder触ってみよう

Xamarin Test Recorderのインストール

Test RecorderはVisual StudioやXamarin Studioに標準でインストールされないので、以下のHPよりダウンロードしましょう。
https://www.xamarin.com/test-cloud/recorder

Mac版はこんなアイコンでした。

TestRecorderIcon.png

インストール完了したら、早速開いてみましょう。

TestRecorderHome.png

USBで接続されたデバイスとシミュレータが選択できます。
TestRecorder_selectDevice.png
ここでは、シミュレータを選択します。

次に、Appで対象のアプリを選択します。
ここでは、Xamarin Dev DaysのHandsOnで使用したDevDaysSpeakersを使用してみます。
iPhoneSimulatorをターゲットにして、ビルドすると、
{RootDir}/DevDays/HandsOnLab/Finish/DevDaysSpeakers/DevDaysSpeakers.iOS/bin/iPhoneSimulator/Debug
の中に、 DevDaysSpeakersiOS.app が生成されるので、これを選択します。

そうすると自動的にシミュレータを立ち上げ、アプリをシミュレータにインストールし、起動しました。途中でInternetの接続許可が出るので、OKしています。
では、早速メイン機能である、レコーディングをやってみましょう。

Record

まずは以下をご覧ください。
TestRecorder_Record.gif

Recordボタン押下後、アプリで「Sync Speakers」を押しています。
自動的にコードと操作が記録されていきます。

app.Tap(x => x.Text("Sync Speakers"));

リスト表示後、リストの先頭行をタップしています。

app.Tap(x => x.Class("UITableViewCellContentView"));

その後"Go to Website"を押し、アプリからSafariを開き、
SafariからDevDaysSpeakerに戻る操作を行っていますが、そこはレコードされませんでした。
アプリのスクロールはレコードされています。

app.ScrollDown();
app.ScrollUp();

ここまででレコードを終わります。

なお、右側ペインのC#コードは直接編集不可です。
左側のペインでは、操作の取り消し、スクリーンショットの追加は可能でした。簡単な変更は可能でしたが、新規操作の追加などはできず、基本はアプリ画面の操作で行うことしかできないと思っていいかと思います。(Assertionの追加などはできない。)

続けてReplayを行なっています。

Replay

TestRecorder_Replay.gif

リプレイでは、"Go to Website"までは順調に進んでいますが、
やはりSafariからDevDaysSpeakerに戻る操作がないため、それ以降のテストが実施されていません。

Calabashでは、テスト対象アプリ以外の操作はできないため、REPLを使っても、同じように操作できません。

Export UITest

ExportからUITest用のコードを出力できます。
出力したファイルを開くと、以下が生成されていました。

using System;
using NUnit.Framework;
using Xamarin.UITest;
using Xamarin.UITest.iOS;

[TestFixture]
public class RecorderTest {
    iOSApp app;

    [SetUp]
    public void SetUp()
    {
        app = ConfigureApp.iOS.AppBundle("/Users/masamba/Documents/Development/Xamarin/DevDays/HandsOnLab/Finish/DevDaysSpeakers/DevDaysSpeakers.iOS/bin/iPhoneSimulator/Debug/xtr-DevDaysSpeakersiOS.app").StartApp();
    }


    [Test]
    public void NewTest() {
        app.Tap(x => x.Text("Sync Speakers"));
        app.Tap(x => x.Class("UITableViewCellContentView"));
        app.Tap(x => x.Text("Speak"));
        app.Tap(x => x.Text("Go to Website"));
        app.Tap(x => x.Text("Speakers"));
        app.ScrollDown();
        app.ScrollUp();
    }

}

興味深いのは、以下です。

app = ConfigureApp.iOS.AppBundle("/Users/masamba/Documents/Development/Xamarin/DevDays/HandsOnLab/Finish/DevDaysSpeakers/DevDaysSpeakers.iOS/bin/iPhoneSimulator/Debug/xtr-DevDaysSpeakersiOS.app").StartApp();

アプリの開始要求をしていますが、 xtr-DevDaysSpeakersiOS.appとなっています。
ディレクトリを見てみると、確かに、 xtr- がついたAppができています。
公式を見てみると、こんなことが書いていました。

When recording tests for an iOS application, the Test Recorder will automatically inject a special library called the Test Recorder Plugin into the app bundle (Android apps do not need this library). The Test Recorder Plugin is extra code that allows the Test Recorder to observe the application that is being tested and generated the C# code for the various events.

⚠️
The presence of the Test Recorder Plugin in an IPA is grounds for the Apple App Store to reject the app bundle; do not submit any IPAs that were used by the Test Recorder to the App Store for distribution.
```

Test Recorder用のPluginがバンドルされたアプリが自動生成され、App StoreにあげたらRejectされるから気をつけろということまで書いています。
ちなみに、Xamarin.UITestや、Calabashを使う場合、Nugetから、 Xamarin.TestCloud.Agentパッケージをインストールする必要がありますので、このパッケージがインストールされたと思います。

なお、すでにXamarin.TestCloud.Agentをインストールしてパッケージしている場合は、Xamarin Test Recorderのプレファレンスで
Automatically inject Calabash into iOS apps のチェックをOFFにすると良さそうです。
TestRecorder_preference.png

Send to Test Cloud

右上のExportボタンより、 Send to Test Cloud ボタンを押してみます。
スクリーンショット 2016-12-18 2.42.30.png

シミュレータ用の.appではなく、IPAをよこせと怒られたので、
スクリーンショット 2016-12-18 3.11.45.png

ついでにWebsiteを開くところを省いて以下とし、再度実行しました。

[Test]
public void NewTest() {
    app.Tap(x => x.Text("Sync Speakers"));
    app.Tap(x => x.Marked("Cliff Sentell"));
    app.Tap(x => x.Text("Speakers"));
    app.ScrollDown();
    app.ScrollUp();
}

そうするとブラウザが起動し、Xamarin Test Cloudのサイトに誘導されました。

スクリーンショット 2016-12-18 16.59.21.png

デバイスを選択し進めると、すでにApp BundleのValidatingが始まっていました。
スクリーンショット 2016-12-18 17.00.40.png
通常は、Xamarin Test CloudのCLIか、Xamarin Studioからパッケージをアップロードする必要がありますが、Xamarin Test Recorderからアップロードができるということのようですね。

そうこうする間に、Runningになって、テストが実行されていました。
結果、一応成功ということでした。

スクリーンショット 2016-12-18 17.15.02.png

17-12-2016 20:00:07.946 +01:00 - 3 - iOS test running Xamarin.UITest version: 2.0.3
17-12-2016 20:00:08.020 +01:00 - 77 - Using TEST_CLOUD configuration override.
17-12-2016 20:00:08.850 +01:00 - 907 - Running in Test Cloud, on device with iOS8 or higher.
17-12-2016 20:02:07.781 +01:00 - 119834 - Tapping element matching Text("Sync Speakers") at coordinates [ 187.75, 86 ].
17-12-2016 20:02:12.447 +01:00 - 124500 - Tapping element matching Marked("Cliff Sentell") at coordinates [ 117.75, 167.25 ].
17-12-2016 20:02:14.361 +01:00 - 126413 - Tapping element matching Text("Speakers") at coordinates [ 62.5, 42.25 ].
17-12-2016 20:02:14.723 +01:00 - 126775 - Scrolling down
17-12-2016 20:02:16.037 +01:00 - 128089 - Scrolling up
17-12-2016 20:02:16.037 +01:00 - 128089 - Scrolling up with query.
Took final screenshot. { Title: "After test", FileName: "/Volumes/Data/xamarin/workspaces/37800a19-9d4b-40a2-9b8d-d920ff0c49de/workspace/screenshot-final-f5e4658103a1471bb1a1d8ce2f643e86.png", ElapsedMilliseconds: 385 }
Completed run. 19 events collected.

実際は、非同期処理や画面遷移などの結果、特定の文字が表示されるまでWaitするだとか、操作の結果をAssertionする必要があるので、
直接Test Cloudにあげることはあまりないでしょう。

Xamarin.UITestをTest Recorderを使わずに記述するには、REPLを使って調べながら実施していくことになるので、それよりは楽かもしれません。

なお、Test Recorderで操作した結果は、C#コードとして出力できるほか、Test Recorderでリプレイするために設定ファイル(.xtrs)として出力することもできます。

スクリーンショット 2016-12-18 17.35.37.png

.xtrsファイルを開いて、直接編集できたら楽だな!と思い、開いてみましたが、json形式で、整形後20000行超あり、面倒くさそうでしたのでやめました。定義すべき情報が多いので、あまり効率的ではなくやるべきではなさそうです。

まとめ

  • Xamarin Test Recorderを使うと、Xamarin UITest用のUIオートメーションテストコードの自動生成が可能
  • Assertionの追加などはTest Recorderではできないため、Test RecorderとXamarin Test Cloudだけで簡単UITestとするのはまだ早い。
  • 操作をRecordしたC#コードをExportして、Xamarin UITestで使うのが主流と思われる。
  • Calabashには対応していないため、Xamarin.UITestにターゲットされてしまう。Amazon Device Farmなどのクラウドテストサービスでは、Xamarin.UITestをサポートしていない。
  • Xamarin.UITestをREPLを使って記述している場合は、非常に楽になるかも!

以上です。
興味が出た方は試してみてはいかがでしょうか。