個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Microsoft MVP for Developer Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

Visual Studio App Center で、自動ビルド後にiOSの自動実機UIテストを実行する方法

はじめに

こんにちは、@hiro128_777です。

11月3日(土)に、品川でXamarin.iOS 、Xamarin.Androidのハンズオンを開催いたします!

Swift, Objective-C のコードを Xamarin.iOS に移植する際のポイントについてのハンズオンまたは、java のコードを Xamarin.Android に移植する際のポイントについてのハンズオンを選んで受講できますので、ご興味がある方はぜひご参加下さい!

jxug.connpass.com



では本題に入りましょう。


Visual Studio App Center で、自動ビルド後にiOSの自動実機UIテストを実行する方法


Visual Studio App Center で、自動ビルドを設定したら当然ながら次は自動でテストを走らせたくなりますよね!

というわけで、今回は自動ビルド後にiOSの自動実機UIテストを実行する手順についてご説明いたします。

今回の内容は下記リポジトリを利用しますので clone するか DL して下さい。
github.com


Visual Studio App Center のテスト設定に実機UIテストを走らせるデバイスの組み合わせのセットを登録します


Visual Studio App Center では、1回のテストで、複数の実機の自動UIテストを走らせることができますので、テストを走らせる実機を選択して登録しておきます。



Visual Studio App Center のテスト設定のデバイスセット設定を開きます。
f:id:hiro128:20181030180705p:plain


Set name を設定し、テストを実行するデバイスにチェックを入れ New device set で保存します。
f:id:hiro128:20181030180715p:plain


Device set が登録されていることを確認します。
f:id:hiro128:20181030180731p:plain


Visual Studio App Center にログインするキーを準備します。


自動実行されるシェルスクリプトが自動テストを実行するときに、事前に取得しておいたキーを使って App Center にログインします。そのキーをスクリプトから利用できるように環境変数に登録しておきます。



「Account settings」を開きます。
f:id:hiro128:20181030180748p:plain


「New API token」を開きます。
f:id:hiro128:20181030193140p:plain


APIの利用目的の説明とアクセス権を設定し保存します。
f:id:hiro128:20181030180958p:plain


キーが表示されるのでコピーしメモ(保管)しておきます。キーは画面を閉じると2度と表示されないのでご注意ください。
f:id:hiro128:20181030180945p:plain


キーが登録されていることを確認します。
f:id:hiro128:20181030180930p:plain


次にビルド設定を開きます。
f:id:hiro128:20181030181018p:plain


環境変数にキーを設定して、保存します。
f:id:hiro128:20181030181031p:plain


build 後に自動実行されるシェルスクリプトを準備します。


Visual Studio App Center には ビルドするcspojと同じ階層に、appcenter-post-build.shという名前でシェルスクリプトを配置しておくと、自動認識し build 後に自動実行してくれる機能があります。
よって、appcenter-post-build.shに、自動実機UIテストを実行する処理を書きます。

/src/Finish/iOS/appcenter-post-build.sh

#!/usr/bin/env bash

# Post Build Script

# Exit immediately if a command exits with a non-zero status (failure)
set -e 

##################################################
# variables

appCenterLoginApiToken=$AppCenterLoginToken # this comes from the build environment variables
appName="TomohiroSuzuki128/XamAppCenterSample2018iOS"
deviceSetName="TomohiroSuzuki128/my-devices"
publishedAppFileName="XamAppCenterSample2018.iOS.ipa"
sourceFileRootDir="$APPCENTER_SOURCE_DIRECTORY/src/Finish"
uiTestProjectName="UITests"
testSeriesName="all-tests"
##################################################

echo "##################################################################################################"
echo "Post Build Script"
echo "##################################################################################################"
echo "Starting Xamarin.UITest"
echo "   App Name: $appName"
echo " Device Set: $deviceSetName"
echo "Test Series: $testSeriesName"
echo "##################################################################################################"
echo ""

echo "> Build UI test projects"
find $sourceFileRootDir -regex '.*Test.*\.csproj' -exec msbuild {} \;

echo "> Run UI test command"
# Note: must put a space after each parameter/value pair
appcenter test run uitest --app $appName --devices $deviceSetName --app-path $APPCENTER_OUTPUT_DIRECTORY/$publishedAppFileName --test-series $testSeriesName --locale "ja_JP" --build-dir $sourceFileRootDir/$uiTestProjectName/bin/Debug --uitest-tools-dir $sourceFileRootDir/packages/Xamarin.UITest.*/tools --token $appCenterLoginApiToken 

echo ""
echo "##################################################################################################"
echo "Post Build Script complete"
echo "##################################################################################################"

このスクリプトがやっていることは、

  • UIテストプロジェクトをビルドする。
  • App Center に、自動UIテストのコマンドを発行し、実行させる。

の2つです。

このスクリプトを含んだリポジトリをプッシュすると、以下のように、App Center 側で認識されます。
f:id:hiro128:20181030181359p:plain

スクリプトデバッグ方法。

このようなスクリプトを自作するときに一番困るのが、

  • 「指定したファイルが見つからない」エラーが発生すること
  • 環境変数の中身がよくわからないこと

です。

よってスクリプトを自作するときには、下記のように環境変数ディレクトリの中身をコンソールに表示させながらスクリプトを書くことで効率よくデバッグできます。

# for test
echo $APPCENTER_SOURCE_DIRECTORY
echo ""
files="$APPCENTER_SOURCE_DIRECTORY/src/Finish/UITests/*"
for filepath in $files
do
  echo $filepath
done

ビルドを実行し、テスト結果を確認してテストが正しく実行されていることを確認します。


正しく実行されていれば、以下のようにテスト結果が確認できます。
f:id:hiro128:20181030181050p:plain


また、テストコード内に以下のように、app.Screenshot("<スクリーンショット名>")と記述することで、スクーンショットが自動で保存されます。

[Test]
public async void SucceedTranslate()
{
    await Task.Delay(2000);
    app.Screenshot("App launched");
    await Task.Delay(2000);
    app.Tap(c => c.Marked("inputText"));
    await Task.Delay(2000);
    app.EnterText("私は毎日電車に乗って会社に行きます。");
    await Task.Delay(2000);
    app.Screenshot("Japanese text entered");
    await Task.Delay(2000);
    app.DismissKeyboard();
    await Task.Delay(2000);
    app.Tap(c => c.Button("translateButton"));
    await Task.Delay(4000);
    var elements = app.Query(c => c.Marked("translatedText"));
    await Task.Delay(2000);
    app.Screenshot("Japanese text translated");
    await Task.Delay(2000);
    Assert.AreEqual("I go to the office by train every day.", elements.FirstOrDefault().Text);
}



保存されたスクリンショットは以下の手順で確認できます。

f:id:hiro128:20181030192206p:plain
f:id:hiro128:20181030192743p:plain
f:id:hiro128:20181030192238p:plain




これで、リポジトリにプッシュすると自動ビルドが走り、自動実機UIテストが実行されるようになりました!!


以上で、Visual Studio App Center で、自動ビルド後に自動実機UIテストを実行する方法は完了です。


今回は以上です。

Visual Studio App Center で、秘匿情報をビルド時にインサートする方法

はじめに

こんにちは、@hiro128_777です。

11月3日(土)に、品川でXamarin.iOS 、Xamarin.Androidのハンズオンを開催いたします!

Swift, Objective-C のコードを Xamarin.iOS に移植する際のポイントについてのハンズオンまたは、java のコードを Xamarin.Android に移植する際のポイントについてのハンズオンを選んで受講できますので、ご興味がある方はぜひご参加下さい!

jxug.connpass.com



では本題に入りましょう。

Visual Studio App Center で、秘匿情報をビルド時にインサートする方法


自動ビルドするときに API へのアクセスキーなどの秘匿情報などは、リポジトリにプッシュしてはいけません。でもそうすると、自動ビルド後のテストなどで、API にアクセスできないので自動テストで困ってしまいます。そういうときには、ビルドサーバがリポジトリから Clone した後か、ビルド前に秘匿情報をインサートする方法が便利です。

今回はその手順についてご説明いたします。

今回の内容は下記リポジトリを利用しますので clone するか DL して下さい。
github.com

Visual Studio App Center のビルド設定に秘匿情報を環境変数として登録する


Visual Studio App Center のビルド設定を開きます。
f:id:hiro128:20181017190427p:plain



Environment variables に環境変数名とキーの値を登録します。


iOS

f:id:hiro128:20181017190444p:plain


Android

f:id:hiro128:20181121193606p:plain


ソースコード上に置き換え用の目印となる文字列を準備します。


/src/Finish/XamAppCenterSample2018/Variables.cs を確認してください。


/src/Finish/XamAppCenterSample2018/Variables.cs

using System;

namespace XamAppCenterSample2018
{
    public static class Variables
    {
        // NOTE: Replace this example key with a valid subscription key.
        public static readonly string ApiKey = "[ENTER YOUR API KEY]";
    }
}

上記の[ENTER YOUR API KEY]のように置き換えの目印になる文字列を設定しておきます。

clone 後に自動実行されるシェルスクリプトを準備します。


App Center には ビルドするcspojと同じ階層に、appcenter-post-clone.shという名前でシェルスクリプトを配置しておくと、自動認識し clone 後に自動実行してくれる機能があります。
よって、appcenter-post-clone.sh[ENTER YOUR API KEY]を本物のキーに置き換えを行う処理を書きます。


iOS

/src/Finish/iOS/appcenter-post-clone.sh


Android

/src/Finish/Droid/appcenter-post-clone.sh



#!/usr/bin/env bash

# Insert App Center Secret into Variables.cs file in my common project

# Exit immediately if a command exits with a non-zero status (failure)
set -e 

##################################################
# variables

# (1) The target file
MyWorkingDir=$(cd $(dirname $0); pwd)
DirName=$(dirname ${MyWorkingDir})
filename="$DirName/XamAppCenterSample2018/Variables.cs"

# (2) The text that will be replaced
stringToFind="\[ENTER YOUR API KEY\]"

# (3) The secret it will be replaced with
AppCenterSecret=$API_Key # this is set up in the App Center build config

##################################################


echo ""
echo "##################################################################################################"
echo "Post clone script"
echo "  *Insert App Center Secret"
echo "##################################################################################################"
echo "        Working directory:" $DirName
echo "Secret from env variables:" $AppCenterSecret
echo "              Target file:" $filename
echo "          Text to replace:" $stringToFind
echo "##################################################################################################"
echo ""


# Check if file exists first
if [ -e $filename ]; then
    echo "Target file found"
else
    echo "Target file($filename) not found. Exiting."
    exit 1 # exit with unspecified error code. Should be obvious why we can't continue the script
fi


# Load the file
echo "Load file: $filename"
apiKeysFile=$(<$filename)


# Seach for replacement text in file
matchFound=false # flag to indicate we found a match

while IFS= read -r line; do
if [[ $line == *$stringToFind* ]]
then
# echo "Line found:" $line
    echo "Line found"
    matchFound=true

    # Edit the file and replace the found text with the Secret text
    # sed: stream editior
    #  -i: in-place edit
    #  -e: the following string is an instruction or set of instructions
    #   s: substitute pattern2 ($AppCenterSecret) for first instance of pattern1 ($stringToFind) in a line
    cat $filename | sed -i -e "s/$stringToFind/$AppCenterSecret/" $filename

    echo "App secret inserted"

    break # found the line, so break out of loop
fi
done< "$filename"

# Show error if match not found
if [ $matchFound == false ]
then
    echo "Unable to find match for:" $stringToFind
    exit 1 # exit with unspecified error code.
fi

echo ""
echo "##################################################################################################"
echo "Post clone script completed"
echo "##################################################################################################"


このスクリプトがやっていることは、

  • キーを置き換えるファイルを探す。
  • ファイルの中から置き換え用の目印となる文字列を探し、本物のキーに置き換える。

それだけです。


このスクリプトを含んだリポジトリをプッシュすると、以下のように、App Center 側で認識されます。


iOS

f:id:hiro128:20181017190644p:plain


Android

f:id:hiro128:20181121194150p:plain


ビルドを実行し、ログを確認してシェルスクリプトが正しく実行されていることを確認。


正しく実行されていれば、以下のようにログで確認できます。
f:id:hiro128:20181017190653p:plain


以上で、Visual Studio App Center で、秘匿情報をビルド時にインサートする手順は完了です。




今回は以上です。




次回は、ビルド後に自動UIテストが走る設定についてご説明します。
hiro128.hatenablog.jp

Microsoft Most Valuable Professional (Microsoft MVP) を再受賞いたしました!

こんにちは、@hiro128_777です。


遅ればせながらご報告させていただきます。

この度、Microsoft Most Valuable Professional (Microsoft MVP) を再受賞いたしました。カテゴリは前回同様 Visual Studio and Development Technologies です。


おかげさまで、Microsoft MVP として2年目を迎えることができました。


これもひとえに、ハンズオンに参加して頂いた方々、スタッフとしてご協力を頂いた方々、ブログや twitter で交流させて頂いた方々、いつもお世話になっているJXUGの皆様のおかげです。改めてお礼申し上げます。本当にありがとうございました。


昨年は主にハンズオンを中心に活動してきました。というのも、Xamarin では、知識よりもまずは実際に手を動かし、様々な地雷を踏み、その解決方法を体験して頂くことが何よりも重要だと感じているからです。


特に今まで Windows 中心に開発されてきた開発者の方の場合、特に iOS 開発時の面倒なお約束を乗り越えるのは非常にストレスが溜まる作業です(私自身がそうでした)。そこをある程度ご体験頂くだけでもその後がかなり楽になります。


クロスプラットフォーム開発も、いろいろ選択肢が出てきましたので、少しでも多くの皆様に Xamarin を選択していただけるように、今後も積極的にハンズオンを実施していきます。


また、今後は Xamarin と Azure や App Center などの連携のハンズオンも積極的に実施していきたいです。


そこで、早速ですが、今月7月28日(土)に、品川で Xamarin.iOS & Xamarin.Android と App Center のハンズオンを開催いたします!

今回は、Visual Studio for Mac による Xamarin.iOS、Xamarin.Android を利用したモバイル アプリの作成方法から Visual Studio App Center を利用した自動ビルドおよび自動 UI テストの手順までを総括的に体験することができるハンズオンを開催いたします。ご興味がある方はぜひご参加下さい!

jxug.connpass.com



それでは、また、1年間よろしくお願いいたします。

私自身楽しみながらコミュニティ活動を続けていきたいです。

皆様とどこかの勉強会でお会いできること楽しみにしております。

Xamarin.iOS で Core ML を利用し画像判定を行う(1) Custom Vision Service での学習モデルの作成

はじめに


こんにちは、@hiro128_777です。

Xamarin.iOS で Core ML を触ってみたかったので試してみることにしました。

私は駅弁が大好きなので、弁当の写真を学習させ、駅弁と普通の弁当を判定させるサンプルを作成したいと思います。




学習モデルの作成


Core ML を利用するには、学習モデルである .mlmodel ファイルを作成します、作成方法はいろいろありますが、一番簡単なのは Azure の Custom Vision Service で学習モデルを作成し、エクスポート機能で .mlmodel ファイルを吐き出す方法です。



Custom Vision Service で学習モデルを作成


学習させるにはサンプルの画像を準備します。今回は駅弁の写真と普通の弁当の写真をそれぞれ30枚程度準備しました。

f:id:hiro128:20180221180232p:plain



Custom Vision Service のページを開き、ログインします。

f:id:hiro128:20180221180056p:plain



利用規約に同意します。

f:id:hiro128:20180221180249p:plain



プロジェクトを作成します。

f:id:hiro128:20180221180304p:plain



名前を入力し、Domains は General(compact) を選択します。

f:id:hiro128:20180221180316p:plain



駅弁の画像全部をアップロードします。

f:id:hiro128:20180221180335p:plain
f:id:hiro128:20180221180357p:plain



Ekibenというタグをつけます。

f:id:hiro128:20180221180409p:plain



画像が登録されました。同様に普通の駅弁の写真も登録します。
Trainをクリックし、学習をスタートします。

f:id:hiro128:20180221180437p:plain



学習が完了しました。
Exportします。

f:id:hiro128:20180221180457p:plain



iOSを選択します。

f:id:hiro128:20180221180508p:plain



ダウンロードします。

f:id:hiro128:20180221180537p:plain



.mlmodel ファイルが作成されました!!
非常に簡単です!!

f:id:hiro128:20180221180557p:plain




今回はここまでです。

2月10日(土)に、品川でXamarin.iOS 、Xamarin.Androidのハンズオンを開催いたしました!

こんにちは、@hiro128_777です。

2月10日(土)に、品川でXamarin.iOS 、Xamarin.Androidのハンズオンを開催いたしました!

jxug.connpass.com

今回は30名の方々にご参加いただきました。

f:id:hiro128:20180219145241j:plain

メンターにも強力な方に来ていただき非常に助かりました。この場をお借りして御礼申し上げます。本当にありがとうございました。

Androidの部は講師を@mishi_csさんがご担当されました。以下のレポートを参照ください。

rksoftware.hatenablog.com

私はiOSの部を担当しました。毎度のことながら躓きが多かったのが「実機デバッグの環境構築」でした。

今回は、

  • キーチェーンアクセスのパスワードがログインパスワードと違っており、しかもかからなくなってしまっているため、再度設定を行う必要があった。
  • 原因不明でビルドできなかったが、実機を抜き差しすることでうまくいった

など、のトラブルが発生しました。両者とも、Xamarin.iOSを触ってみた場合には自力解決が難しいものでしたので、ハンズオンで体験、解決できたのはよかったです。


いつも通り、コーディングではあまり躓きは少なかった印象ですが、「難易度が高い」との感想を持たれた方が多かったようです。

アンケート結果

ハンズオンを最後まで完了できたか

f:id:hiro128:20180219145057p:plain


今回、iOSでは全員の方がアプリ起動を確認できましたが、全体ではうまく動かなかった方がいらっしゃいました。
今後も全員がアプリを動かせるようにサポートしていきます。

難易度

f:id:hiro128:20180219145209p:plain


難易度についてですが、67%の方が「簡単」「ちょうどいい」とご回答され、28%の方が「難しい」とご回答されました。


割合としては、前回、前々回と同様の状況です。


確かにちょっと難しいですが、習得する価値がある内容ですので、今後もなるべくわかりやすくご説明できるよう改善していきますが、レベル感としては現状を維持したいと考えています。


時間

f:id:hiro128:20180219145222p:plain


時間ですが、94%以上の方が「ちょうどいい」とご回答されましたので、ボリューム的には今のままを続けたいと考えております。

ハンズオン自体は、休憩などを省くと正味3時間程度でした。集中力的にも3時間程度がちょうどいい長さだと考えております。


役に立ったか

f:id:hiro128:20180219145035p:plain


なんと94%の方に「役に立った」とご回答を頂けました!
主催者としては非常にうれしい結果となりました!
今後全員の方に「役に立った」と感じていただけるよう努力していきます。



その他のご感想

その他のご感想としては、

  • Xamarin.Androidは比較的簡単だが、Xamarin.iOSはSwiftの知識が必要で、ちょっと難しい

というご意見を挙げられた方が多かったです。
これは確かにその通りで、Xamarin.iOSの方がハマりどころやApple独自のエコシステムなどの面でもハードルが高いため、ハンズオンで一度ハマりを経験することがお役に立つのではないかと考えております。


また、

  • 独学でやるより全然テンポよく学習できた

というご意見もいただきました。

ハンズオンの目的がまさに「これ」ですので、主催者としては大変嬉しいご感想でした。

皆様のご意見を参考に今後も有意義なハンズオンを開催できるように精進いたします。



最後にお忙しい中休日にお時間を作ってご参加頂いた皆様、本当にありがとうございました!



懇親会はAzureもくもく会さまと合同で行い、とても楽しい時間を過ごせました!!



また、JXUGのイベントでお会いできるのを楽しみにしております!