VSTSからAppCenterでテスト

はじめに

ここまででAppCenterを使ってクラッシュ・エラーレポート、イベントによる分析、ビルド、テスト、配布ができるようになりました。 今度はVSTSからこのプロジェクトのビルドとAppCenterでのテストをできるようにします。

前準備

ここで注意点ですが、自分が試した限りではAppCenterでのビルドではではビルド成功するのにVSTSのビルドではそのままだと_CompileToDalvikWithDx:でOutOfMemoryで失敗します。 おそらくビルドの行われるホスト環境の違いによるものだと思いますが、詳しくは不明です。 のでVSTSでのビルドを行う前に次の行をXamarin.Androidの最初のPropertyGroupにセットしコードをプッシュしておいてください。

<JavaMaximumHeapSize>1G</JavaMaximumHeapSize>

AppCenterでデバイスセット作成

まずVSTSからのテストで使うため、AppCenterのTest>Device setsから新しいデバイスセットを作成します。 f:id:omanuke-ekunamo:20180409131902p:plain

ここではPixel2とNexus5Xを指定して適当な名前を付けNew device setで作成します。 f:id:omanuke-ekunamo:20180409131915p:plain

ビルド定義作成・実行

ビルド定義作成

VSTSに戻り新しいビルド定義を作成します。New definitionを押します。 f:id:omanuke-ekunamo:20180409131936p:plain

ソースを選び、Xamarin.Androidテンプレートを選びます。 f:id:omanuke-ekunamo:20180409132009p:plain f:id:omanuke-ekunamo:20180409132018p:plain

ビルドの各ステップの設定画面になります。

AppCenterConnection作成のためのAppCenterへのAPI Tokenの作成

後述のTest with Visual Studio App Centerタスクの設定で使うためAppCenterへのAPI Tokenを作成します。 AppCenterの左下のアカウントアイコンよりAccount Settingsを押します。 f:id:omanuke-ekunamo:20180409132052p:plain

API Tokensを選択し右上のNew API tokenを押す。 f:id:omanuke-ekunamo:20180409132119p:plain

適当な名前を付けて右下のAdd new API tokenを押す。ここではVSTSToAppCenterとしました。 f:id:omanuke-ekunamo:20180409132133p:plain

作成されたAPI tokenの値が表示されるのでコピーする。閉じると二度と見れないので注意してください。メモ帳などに書き写しておいてください。

設定

Test with Visual Studio App Centerのタスクについて設定します。デフォルトではDisableになっていますが、設定項目の下の方にあるControlOptions/EnableでEnableにできます。 f:id:omanuke-ekunamo:20180409132328p:plain

次の項目を設定します。

  • Prepare Tests
    • Test framwork = Xamarin UI Testを選択
    • Build direcotry = $(build.binariesdirectory)/$(BuildConfiguration)/test-assembly を設定。
    • Test tools directory = $(build.sourcesdirectory)/packages/Xamarin.UITest.2.2.4/tools 使っているXamarin.UITestのバージョンに合わせること。
  • Run Tests
    • App Center connection = Newより表示されたダイアログに適当な名前と先ほど作成したAPI Tokenを設定し作成、それを使います。
    • App slug = ユーザー名/アプリケーション名
    • Devices = ユーザー名/デバイスセット名
    • System language = Japanese
  • Control Options
    • Enabledにチェック

設定した項目は以下のようになります。 f:id:omanuke-ekunamo:20180409132900p:plain f:id:omanuke-ekunamo:20180409132914p:plain

ビルド実行

設定を終えたらSave&queueよりSave&queueをおして保存するとともにビルドを開始します。 開始したビルドの状況はこちらをクリックすることにより進行状況をログなどで確認できます。 f:id:omanuke-ekunamo:20180409132938p:plain f:id:omanuke-ekunamo:20180409132948p:plain

正しく設定できていれば次のようにAppCenterでのテストが開始されます。 f:id:omanuke-ekunamo:20180409133001p:plain

VSTSから実行したテストは完了後にAppCenterを見ると実行結果を確認できます。 f:id:omanuke-ekunamo:20180409133025p:plain f:id:omanuke-ekunamo:20180409133034p:plain

終わりに

これでVSTSからもAppCenterでテストができるようになりました。 気になるのはAppCenterの方でテストを行う際にはKeyStoreを設定したのですが、こちらでは設定しないままでも大丈夫されるようです。この辺疎いんですが、どうなってるんですかね… まぁとにかくこれでXamarin.FormsアプリをAppCenterやVSTSを絡めてゴニョゴニョするとっかかりができると思いますので、皆さま各自必要に応じて掘り下げていってくださいまし。

AppCenterでテスト・ビルド

はじめに

AppCenterへのAnalytics/Diagnosticsの連携とローカルでのUITestの実行ができるようになりました。 今回はAppCenterでのTest/Buildが実行できるようにしたいと思います。

AppCenterでTest

StartTestingYourAppより新しいテストを設定します。 f:id:omanuke-ekunamo:20180409124510p:plain

まずテストを行いたい端末を指定します。ここではPixel2とGalaxy9を指定します。 f:id:omanuke-ekunamo:20180409124543p:plain

次にパラメータを指定します。 System languageを適当なものに変更、テストフレームワークをXamarin.UITestにします。 f:id:omanuke-ekunamo:20180409124603p:plain

パラメータを指定すると以下のようなテストを実行するための手順が表示されます。 f:id:omanuke-ekunamo:20180409124619p:plain

手順にあるようにNode.jsやnpmがないならインストール後appcenter-cliパッケージをインストールします。 Xamarin.UITestのバージョンがおそらくAppCenterTestに必要なバージョンより古いものなのでNugetManagerより更新します。 f:id:omanuke-ekunamo:20180409124647p:plain

コマンドプロンプトで更新したXamarin.UITestのパッケージのディレクトリに移動し Running testsにある実行コマンドをコピーしapkファイルへのパスとUITest1.dllのディレクトリを適当なものに指定して実行します。 f:id:omanuke-ekunamo:20180409124730p:plain   AppCenterの画面でも実行中のテストを確認できます。 f:id:omanuke-ekunamo:20180409124840p:plain

終了すると以下のように結果を確認できます。 各テストを掘り下げると各デバイスでの実行結果などを見ることができます。 f:id:omanuke-ekunamo:20180409124856p:plain

※今回まっさらな環境から作るように新しいMSアカウントを作っており、上記のコマンドをコマンドプロンプトから実行しようとしたところ普段使ってるMSアカウントに結びついてしまってるようなメッセージが表示されてテスト実行がうまくいきませんでした。 普段使ってるMSアカウントのAppCenterで同様に新しいテスト実行を作成し実行したところ無事テストが始まりました。 どのようにMSアカウントが残って関連してしまったのか不明ですしだいぶおま環な気がしますが、メモとして残しておきます。

AppCenterでビルド

ローカルのソースをVSTSリポジトリにプッシュ

VSTSにアカウントがない場合は登録します。 ここでは次のように作成しました。 f:id:omanuke-ekunamo:20180409125029p:plain

作成したソリューションはまだソース管理をしていないのでVSの右下からGitをソースコントロールとして設定します。 f:id:omanuke-ekunamo:20180409125057p:plain

VisualStudioでチームエクスプローラーを開きLocal Git RepositoriesよりこのソリューションのリポジトリXFormCIをダブルクリックします。 f:id:omanuke-ekunamo:20180409125134p:plain

こちらの画面でSyncをクリックします。 f:id:omanuke-ekunamo:20180409125213p:plain

Push to Visual Studio Team ServicesのPublish Git Repoをクリックします。 f:id:omanuke-ekunamo:20180409125306p:plain

先ほど作成したVSTSを選んで Add an accountをクリックします。 f:id:omanuke-ekunamo:20180409125328p:plain

VSTSのアカウント情報を入れた後の画面でPublish Repositoryを押します。 ここはイメージ取り忘れました(´・ω・`)

成功するとLocalのリポジトリVSTSにプッシュされ、そのリポジトリを含むプロジェクトが作成されます。 f:id:omanuke-ekunamo:20180409125356p:plain

AppCenterでのビルド設定・実行

ビルド設定

AppCenterに戻ってBuildを選択、リポジトリの選択の画面になるのでVSTSを選択します。 f:id:omanuke-ekunamo:20180409125439p:plain

アクセス許可を承認します。 f:id:omanuke-ekunamo:20180409125502p:plain

プロジェクト一覧が出ますのでXFormCIを選択します。 f:id:omanuke-ekunamo:20180409125522p:plain

その中のリポジトリを選択します。 f:id:omanuke-ekunamo:20180409125543p:plain

ブランチ一覧が出てきます。のでブランチを押します。 f:id:omanuke-ekunamo:20180409125610p:plain

Configure buildを押して設定画面を表示します。 f:id:omanuke-ekunamo:20180409125629p:plain

設定画面です。 f:id:omanuke-ekunamo:20180409125645p:plain

Sign buildsをオンにすると実機への配布ができるようになりますのでオンにします。

キーストア作成

実機への配布にキーストアが必要なので作成しましょう。 こちらを参考に以下のようにコマンドプロンプトから実行します。

C:\Users\miyasaka>keytool -genkey -v -keystore xample.keystore -alias publishingdoc -keyalg RSA -keysize 2048 -validity 10000
キーストアのパスワードを入力してください:
新規パスワードを再入力してください:
姓名を入力してください。
[hoge]: hoge
組織単位名を入力してください。
[Fuga]: Fuga
組織名を入力してください。
[FugaFuga]: FugaFuga
都市名または地域名を入力してください。
[Piyo]: Piyo
都道府県名を入力してください。
[PiyoPiyo]: PiyoPiyo
この単位に該当する2文字の国コードを入力してください。
[JP]: JP
CN=hoge, OU=Fuga, O=FugaFuga, L=Piyo, ST=PiyoPiyo, C=JPでよろしいですか。
[いいえ]: はい

10,000日間有効な2,048ビットのRSAの鍵ペアと自己署名型証明書(SHA256withRSA)を生成しています
ディレクトリ名: CN=hoge, OU=Fuga, O=FugaFuga, L=Piyo, ST=PiyoPiyo, C=JP
<publishingdoc>の鍵パスワードを入力してください
(キーストアのパスワードと同じ場合はRETURNを押してください):
ビルド設定残り・実行

先ほどのAppCenterのビルド設定に今作ったkeystoreを登録し、作成時に使った値を設定します。 設定したらSave&Buildを押します。 ビルドが開始されます。クリックすると進行中のビルドログが見れます。 f:id:omanuke-ekunamo:20180409125919p:plain f:id:omanuke-ekunamo:20180409125931p:plain

ビルドに成功後、DistributeのReleaseを選択すると今作成したテスターへの配布物ができています。 f:id:omanuke-ekunamo:20180409130010p:plain

それをクリックすると詳細が表示され、右上にリンクがありますのでそこよりapkをダウンロードしてインストールできます。 f:id:omanuke-ekunamo:20180409130034p:plain

終わりに

これでAppCenterでテスト・ビルドをすることができるようになりました。 最後にVSTSからAppCenterでテストできるようにしましょう。->続き

Xamarin.Forms AndroidプロジェクトでAppCenterへの連携とローカルでUITest

はじめに

Xamarin.UITestをそろそろ行わないといけないかなーと思い、どうせやるならAppCenterで複数デバイスでテストしたいよねとかCIに組み込みたいよねとか夢を膨らませてやってみたら思いのほか設定方法とかで手間取ったので記事にまとめますた。 長いので

の3記事に分けますた。適当に必要なところだけ見てください。

ということでこの記事ではVSでXamarin.Formsプロジェクト作成、そこにAppCenterへAnalytics、Diagnosticsデータを連携するところとUITestを実装するところをやっていきます。 とりあえずAndroidだけです。iOSの方はまためんどくさそうなのでまたの機会に( ^ω^)・・・

Xamarin.Formsプロジェクト作成

まずXamari.Formsプロジェクトを作成します。

Xamarin.FormsアプリケーションでテンプレートはBlankApp、プラットフォームはAndroidと今回は使いませんがiOS、.NET Standardでのコードシェアとしました。

機能を確かめるための簡単なアプリとして次のようなものを作成します。

  • 起動すると機能確認用のボタンが並んだページが表示。
  • TOSECONDボタン:次の画面に遷移。UITestでの動作確認用
  • ONPROGRESSボタン:AppCenterのAnalyticsのEventを送信。
  • RAISE EXボタン:例外を発生させアプリをクラッシュさせる。
  • LOG EXボタン:例外を発生させるがキャッチしてAppCenterのDiagnosticsのErrorを送信。

起動画面

次の画面

ソースはこちらに置いておきます。

AppCenterとのAnalytics/Diagnostics連携

AppCenterアカウント作成

appcenter.msでAppCenterのアカウントを作成します。作成直後は以下のような画面になります。

AppCenter-App作成

AppCenterでアプリを管理するためのAppを作成します。これはプラットフォームごとに作る必要があるので同じ目的のアプリでも別々に作る必要があります。 App nameは適当なもの設定,OS=Android,Platform=XamarinとしてAdd new appを押します。

GetttingStartの画面になります。Xamarin.Formsを選ぶとXamarin.Formsプロジェクトでどこに何を設定したらいいかが出てきます。

ちなみに左上の紫色のボタン?を押すとホーム画面となり管理しているアプリの一覧が見れます。

AppCenterに関するコード追加

Nuget追加

Manage Nuget Package for SolutionよりMicrosoft.AppCenter.CrashesとMicrosoft.AppCenter.Analyticsを追加します。 今回は.NET Standadのプロジェクトでも使うのでAndroidプロジェクトとともにそちらもチェックします。

App.xaml.cs

MainPageは画面遷移ができるよう、NavigationPageでくるみます。 AppCenterのGetting Startedに表示されるコードをコピペしてOnStartに貼り付けます。とりあえずiOSやuwpはつかなわないのでその部分は削除しました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using Xamarin.Forms;

namespace XFormCI
{
    public partial class App : Application
    {
        public App ()
        {
            InitializeComponent();

            MainPage = new NavigationPage(new MainPage());
        }

        protected override void OnStart ()
        {
            // Handle when your app starts
            AppCenter.Start("android=16ce8137-548f-43bb-b8fc-4b0b2695419f;",
                typeof(Analytics), typeof(Crashes));
        }

        protected override void OnSleep ()
        {
            // Handle when your app sleeps
        }

        protected override void OnResume ()
        {
            // Handle when your app resumes
        }
    }
}
MainPage.xaml、SecondPage.xaml

後でUITestの時に使うAutomtionIdをMainPageのToSecondBtnとSecondPageのLabelに追加します。

MainPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
  x:Class="XFormCI.MainPage"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  xmlns:local="clr-namespace:XFormCI"
  BackgroundColor="Orange">
  <StackLayout>
    <Label
      HorizontalOptions="Center"
      Text="Welcome to Xamarin.Forms!"
      VerticalOptions="Center" />
    <Button
      AutomationId="ToSecondBtn"
      Clicked="ToSecondClicked"
      Text="ToSecond" />
    <Button
      BackgroundColor="Red"
      Clicked="OnProgress"
      Text="OnProgress"
      TextColor="White" />
    <Button
      BackgroundColor="DarkOrange"
      Clicked="OnRaiseEx"
      Text="Raise Ex"
      TextColor="White" />
    <Button
      BackgroundColor="CornflowerBlue"
      Clicked="OnLogEx"
      Text="Log Ex"
      TextColor="White" />
  </StackLayout>
</ContentPage>

SecondPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
  x:Class="XFormCI.SecondPage"
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  BackgroundColor="SkyBlue">
  <ContentPage.Content>
    <StackLayout>
      <Label
        AutomationId="SecondPageText"
        HorizontalOptions="CenterAndExpand"
        Text="Welcome to Xamarin.Forms!"
        VerticalOptions="CenterAndExpand" />
    </StackLayout>
  </ContentPage.Content>
</ContentPage>
MainPage.xaml.cs

ToSecondClickedでSecondPageに遷移します。 OnProgressでAnalytics.TrackEventを呼んでAppCenterへAnalyticsのEventを送信します。 OnRaiseExで未ハンドルの例外を上げてアプリをクラッシュさせます。これはのちの起動後にAppCenterへCrashとして送信されます。 OnLogExでCrashes.TrackErrorを呼んでAppCenterへDiagnosticsのErrorを送信します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;

namespace XFormCI
{
    public partial class MainPage : ContentPage
    {
        private int _counter;
        private int _logExCounter;

        public MainPage()
        {
            InitializeComponent();
        }

        private void ToSecondClicked(object sender, EventArgs e)
        {
            (Application.Current.MainPage as NavigationPage)?.PushAsync(new SecondPage());
        }

        private void OnProgress(object sender, EventArgs e)
        {
            Analytics.TrackEvent("ReportProgress",
                new Dictionary<string, string>() {{"counter", (_counter++).ToString()}});
        }

        private void OnRaiseEx(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        private void OnLogEx(object sender, EventArgs e)
        {
            try
            {
                throw new ArithmeticException();
            }
            catch (Exception ex)
            {
                Crashes.TrackError(ex,
                    new Dictionary<string, string>() {{"logExCounter", (_logExCounter++).ToString()}});
            }
        }
    }
}

ちなみに自分の環境ではVisualStudio2017の15.6.Xのバグなのかわかりませんが、

<AndroidSdkBuildToolsVersion>23.0.3</AndroidSdkBuildToolsVersion>

をXamarin.Androidの最初のItemGroupに追加しないとDebugでもうまく実機にDeployできない現象が起きるのでここで追加しておきます。

AppCenterにAnalytics/EventやDiagnostics/Crash・Errorが送信されるのを確認

いまAppCenterでAnalyticsやDiagnosticsを見ても何も表示されません。

起動してOnProgress、OnLogEx、OnRaiseExを押します。OnRaiseExを押すとクラッシュしますのでアプリを再起動しましょう。 そうするとAnalyticsのEventややDiagnosticsのCrash、Errorに情報が上がるようになります。 本来は一度行えばすぐ表示されるべきはずな気がしますが、CrashやErrorなどは何度か行い画面を開きなおさないと表示されないなどとなりましたのでうまく反映されない場合は何度か繰り返してみてください。このテスト中Edgeを使っていたのですが、その後もEdgeだと何かうまく動いていない風なところがありましたのでその辺が関係してるのかもしれません。

Analytics/Overview

Analytics/Events

Diagnostics/Crashes

Diagnostics/Errors

またこれらの情報はAnalytics/Log flowで大体リアルタイムで見ることができます。どちらかというとデバッグや動作確認用でしょうか。Log flowはEventを送信した後3-4秒で反映されるのではと思います。ほかの画面はリフレッシュしないと更新されませんかね。 またLogFlowはEdgeだと更新がうまく行われずChromeではうまく言ったなどありましたのでブラウザの違いも影響あるかもしれないので注意してください。 Analytics/Log flow

VSよりUITest実行

AppCenterへの連携ができましたので今度はUITestを行えるようにします。

UITestで使う用のAPK作成

デフォルトでは実機にDeployを行った際にapkファイルがbin/Debugなどに作られていると思いますが、ない場合はArchiveで作るなど何らかの方法でapkファイルを作成してください。 ちなみにDebugで作成したapkをUITestで使いたい場合はAndroid OptionのUse Shared Runtimeをオフにしないと怒られます。

UITestプロジェクト作成

ソリューションにUI Test App(Xamarin.UITest|Cross-Platform)プロジェクトを追加します。

UITest実行できるように設定。

AppInitializer.cs

VSでテスト実行できるよう、ApkFileを指定します。ちなみにこの記述はそのままでAppCenterでのUITestが行えるようです。 EnableLocalScreenShotsも指定します。

using System;
using System.IO;
using System.Linq;
using Xamarin.UITest;
using Xamarin.UITest.Queries;

namespace UITest1
{
    public class AppInitializer
    {
        public static IApp StartApp(Platform platform)
        {
            if (platform == Platform.Android)
            {
                return ConfigureApp
                    .Android
                    .ApkFile(@"D:\MyDocuments\cvs\XFormCI\XFormCI\XFormCI.Android\bin\Debug\com.companyname.XFormCI-Signed.apk")
                    .EnableLocalScreenshots()
                    .StartApp();
            }

            return ConfigureApp
                .iOS
                .StartApp();
        }
    }
}
Tests.cs

TestFixtureのiOSコメントアウトします。 デフォルトでAppLaunchesが作られていると思いますが、そこにapp.Repl()と記述します。

using System;
using System.IO;
using System.Linq;
using NUnit.Framework;
using Xamarin.UITest;
using Xamarin.UITest.Queries;

namespace UITest1
{
    [TestFixture(Platform.Android)]
//    [TestFixture(Platform.iOS)]
    public class Tests
    {
        IApp app;
        Platform platform;

        public Tests(Platform platform)
        {
            this.platform = platform;
        }

        [SetUp]
        public void BeforeEachTest()
        {
            app = AppInitializer.StartApp(platform);
        }

        [Test]
        public void AppLaunches()
        {
            app.Repl();
        }
    }
}
Replの実行

ソリューションエクスプローラーのUITestプロジェクトを右クリックしてRun Unit Testsを押します。

初回はアプリが起動するまで時間がかかるかもしれませんのでVSのOutputウィンドウのTestやUnit Test Sessionsの画面などでRunning状態なのかエラーで止まっているのかなど確認してください。 やがてアプリが起動するとともにReplウィンドウが表示されます。 Replウィンドウが起動後treeを実行してエレメントツリーを表示すると次のようになります。

Replを使ってXamarin.UITestのコマンドのテストを行いつつUITestを記述していくことになるのではと思います。 またスクリーンショットはUITest1/bin/Debugの下に作成されます。複数のテストでスクリーンショットを取った場合全部同じファイル名になってしまう気がするんですが、これは何か買える方法あるんですかね…

画面遷移のテスト

app.Repl()をコメントアウトしてSecondPageに遷移することを確認するテストToSecondを追加します。テスト内容としてはSecondPageに遷移するボタンをタップし、SecondPageの中にあるUI要素がエレメントツリーに現れるのを待つというものです。 コードは次のようになります。

        [Test]
        public void AppLaunches()
        {
            app.Screenshot("First screen.");
            //app.Repl();
        }

        [Test]
        public void ToSecond()
        {
            app.Tap(x => x.Marked("ToSecondBtn"));
            app.WaitForElement(x => x.Marked("SecondPageText"));
            app.Screenshot("Second screen.");
        }

こちらも右クリックからテストを実行して動作を確認します。

終わりに

これで素のXamarin.FormsプロジェクトからAnalytics/DiagnosticsをAppCenterに連携させ、UITestもローカルで実行できるようになりました。 次はAppCenterで今やったUITestを複数のデバイスを使って行えるようにします。->続き