AWS Device Farmでcalabash-androidを動かして画面キャプチャを取得したり、日本語で試験を書いてみる

以前にCalabsh-Androidを動かしてみました。

[Calabash-Androidを利用してAndroidのシナリオテストを日本語で書いてみる](http://toshihirock.blogspot.jp/2014/03/calabash-androidandroid.html)

上記を参考(自分のブログですが）にCalabash-andoridをAWS Device Farmで動かしてみたのでメモ

# 参考

+ [calabash-android](https://github.com/calabash/calabash-android)
+ [Working with Calabash for Device Farm](https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/test-types-android-calabash.html)

# 環境

+ MacOSX
+ AndroidSDKなどの設定は完了済み

# Calabash-android?

こちらの資料がわかりやすかったです。

[Calabash-AndroidでBDDしようぜ!](http://www.slideshare.net/chariderpato/calabashbdd)

# テスト対象アプリ

AndroidStudioで作成したHelloWorld!と表示されるだけのアプリ

![Screen Shot 2015-07-15 at 6.08.02 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/cd899917-2f08-2f0c-b9d0-7d4ef0383079.png "Screen Shot 2015-07-15 at 6.08.02 AM.png")

なお、Clabash-andoridではテストの際にインターネットアクセスを許容していないとダメなのでAndroidManifestは以下のように **android.permission.INTERNET** を追記してビルドしておいてください。

```lang:app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.toshihirock.helloworld" >

    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```


# calabash-andoridのインストール

[calabash-android-instalation](https://github.com/calabash/calabash-android/blob/master/documentation/installation.md)

以下のコマンドでインストール。Rubyのバージョンは公式ドキュメントを見る限りruby 1.8.7以上であれば大丈夫のようです。

```
$gem install calabash-android
```

確認

```
$gem list --local |grep android
calabash-android (0.5.12)
```

なお、calabashでは環境変数`$ANDROID_HOME`が設定されている必要があるのでやっておいてください

# calabash-androidの設定

Calabash-androidで必要なファイル群を以下のコマンドで作成します。

```
$cd {your-android-project}
$calabash-android gen
----------Question----------
I'm about to create a subdirectory called features.
features will contain all your calabash tests.
Please hit return to confirm that's what you want.
---------------------------


----------Info----------
features subdirectory created.
---------------------------
```

これでカレントディレクトリにfeaturesというディレクトリができているのが確認できるかと思います。

```
$tree features
features
├── my_first.feature
├── step_definitions
│   └── calabash_steps.rb
└── support
    ├── app_installation_hooks.rb
    ├── app_life_cycle_hooks.rb
    ├── env.rb
    └── hooks.rb
```

試験はhoge.featureという形で作成すればよく、とりあえずmy_first.featureというファイルができました。(一つのファイルに複数の試験を書くのも可能)

# 試験の変更

スケルトンで作成された試験だと今回のアプリとは合っていないので以下のように「起動されたらHello world!と表示されること」という意味の試験に変更します。

```lang:my_first.feature
Feature: HelloWorld feature

  Scenario: Display "Hello World!"
    Then I see "Hello world!"
```

# ローカル環境で実行してみる

まずは、ローカル環境でテストが成功するか確認します。
エミュレーターが起動した状態で以下のコマンドを実行します。 **app/build/outputs/apk/app-debug.apk**という部分はテスト対象のアプリのapkに変更してください。

```
$cd {your-android-project}
$calabash-android run app/build/outputs/apk/app-debug.apk
Feature: HelloWorld feature

  Scenario: Display "Hello world!" # features/my_first.feature:3
1299 KB/s (560158 bytes in 0.421s)
1703 KB/s (933970 bytes in 0.535s)
    Then I see "Hello world!"      # calabash-android-0.5.12/lib/calabash-android/steps/assert_steps.rb:5

1 scenario (1 passed)
1 step (1 passed)
0m17.717s
```

上記の通り、テストがpassしたことが分かります。

# AWS Device farmへアップロードするテストのZIP圧縮

AWS Device farmでCalabash-androidを実行する際にfeaturesフォルダ配下の情報をZIP圧縮してアップロードする必要があるのでやっておきます。

```
$zip -r features.zip features
  adding: features/ (stored 0%)
  adding: features/my_first.feature (deflated 23%)
  adding: features/step_definitions/ (stored 0%)
  adding: features/step_definitions/calabash_steps.rb (deflated 10%)
  adding: features/support/ (stored 0%)
  adding: features/support/app_installation_hooks.rb (deflated 56%)
  adding: features/support/app_life_cycle_hooks.rb (deflated 39%)
  adding: features/support/env.rb (stored 0%)
  adding: features/support/hooks.rb (stored 0%)
```

# AWS Device Farmでやってみる

上記試験をAWS Device Farmでやってみます。

AWSのマネージメントコンソールにログインしてAWS Device Farmを選択します。東京リージョンがないのでOregonリージョンにします。

その後、Getting startedかCreate a new projectでプロジェクトを作成します。名前は適当で。

![Screen Shot 2015-07-15 at 6.48.08 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/cbe7d984-4edb-911d-eef0-439c1ae72638.png "Screen Shot 2015-07-15 at 6.48.08 AM.png")

次にテスト対象のapkをアップロードします。私の環境の場合、 **app/build/outputs/apk/app-debug.apk** をアップロードしました。

![Screen Shot 2015-07-15 at 6.50.36 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/cd589e3a-039b-9401-087c-fa4000d0f140.png "Screen Shot 2015-07-15 at 6.50.36 AM.png")

アップロード後、アップロードしたアプリの情報が上記のように確認できます。

次にClabashのテストをアップロードします。先ほど作成したZIPファイルをアップロードします。

![Screen Shot 2015-07-15 at 6.55.32 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/ae445746-68be-e75c-7863-d06a8bcc178a.png "Screen Shot 2015-07-15 at 6.55.32 AM.png")

次にテストしたい実機端末を選択します。
デフォルトだと5機種でやるようになってますが、時間がかかるのでとりあえず1台だけやるように設定しました。

![Screen Shot 2015-07-15 at 6.57.55 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/de89e492-9e23-83ec-0cc2-5e7a34e71fe7.png "Screen Shot 2015-07-15 at 6.57.55 AM.png")

次に端末の状態を設定します。今回はデフォルトのままとします。

![Screen Shot 2015-07-15 at 6.59.01 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/63db85a5-0e7a-7772-82b6-7de491921391.png "Screen Shot 2015-07-15 at 6.59.01 AM.png")

最後にReviewを行って、Runさせます。

しばらく待つとテスト結果が表示されます。

![Screen Shot 2015-07-15 at 7.07.52 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/c506f679-b2fb-cc6f-315d-c629bf143b8b.png "Screen Shot 2015-07-15 at 7.07.52 AM.png")

グラフ部分を選択すると詳細が確認できます。

![Screen Shot 2015-07-15 at 7.09.37 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/84b95a0d-2c1d-4ca9-7265-aaadf0c3449d.png "Screen Shot 2015-07-15 at 7.09.37 AM.png")

画面の下にログも表示されており、こちらで定義した試験HelloWorld featureの実施とSetup SuiteとTeardown Suiteという試験が行われていることがわかりました。

# 画面キャプチャを取ってみる

試験を変更して画面キャプチャを取ってみます。

```lang:my_first.feature
Feature: HelloWorld feature

  Scenario: Display "Hello world!"
    Then I see "Hello world!"
    Then take picture
```

なお、指定可能な操作は以下に記載があります。

[Predefined steps](https://github.com/calabash/calabash-android/blob/master/ruby-gem/lib/calabash-android/canned_steps.md)

変更後、feature.zipを再作成します。

その後、AWS Device farmで create new runを選択し、再度試験を実行します。

テスト対象のapkについては先ほど利用したapkが選択できるので再度アップロードする必要がありませんが、feature.zipは変更されているので再度アップロードしてください。

少し待つと試験結果がわかりますが、Screeenshotsタブでスクリーンキャプチャが取得できているのが確認できます!

![Screen Shot 2015-07-15 at 7.28.38 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/5268a655-8d68-169a-3ccb-98ea812e2105.png "Screen Shot 2015-07-15 at 7.28.38 AM.png")


# 失敗するテストにしてみる

以下のように表示される想定の文言を変更して失敗するか確認します。

```lang:my_first.feature
Feature: HelloWorld feature

  Scenario: Display "Hello world!"
    Then I see "aaaaaaa"
```

さきほどと同じようにfeature.zipを再アップロードして試験を行ってみます。

予想通り失敗しました。

![Screen Shot 2015-07-15 at 7.36.49 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/d91b6dab-cdf0-dacd-11b5-3f58d6efc702.png "Screen Shot 2015-07-15 at 7.36.49 AM.png")

`Display "Hello world!" failed: Timeout waiting for elements: * {text CONTAINS[c] 'aaaaaaa'} (Calabash::Android::WaitHelpers::WaitError)`

と表示され、aaaaaaというテキストが表示されるのを待ったけど表示されずエラーとなっているのも確認できます。

また、テスト失敗の際にはスクリーンキャプチャが取得されるようでした。

![Screen Shot 2015-07-15 at 7.36.58 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/14819fdd-19d9-3451-1a41-d7ad00467538.png "Screen Shot 2015-07-15 at 7.36.58 AM.png")

# 試験を日本語で書く

Calabshの良いところとして日本語でシナリオがかけるのでそれもやってみます。

まず、どの日本語の命令が指定された時にどの定義済みの命令と紐付けるのかを定義します。

[Predefined steps](https://github.com/calabash/calabash-android/blob/master/ruby-gem/lib/calabash-android/canned_steps.md)

```lang:features/step_definitions/calabash_steps.rb
# coding: utf-8
require 'calabash-android/calabash_steps'

ならば /^"(.*?)"と表示されていること$/ do |text|
  step %{I see "#{text}"}
end

ならば /^スクリーンショットを撮る$/ do
  step %{take picture}
end
```

**ならばhogefugaと表示されていること** と書いた場合には **I  see hogefuga** という命令と書いたと等しいということを表しています。スクリーンショットの部分も同じになります。

紐付けが出来たのでfeatureファイルも変更します。

```lang:my_first.feature
# language: ja
フィーチャ: HelloWorld画面の表示確認を行う

シナリオ: HelloWorld画面を表示する
  ならば"Hello world!"と表示されていること
  ならばスクリーンショットを撮る
```

同じようにzip化してアップロードしてみます。


![Screen Shot 2015-07-15 at 7.59.00 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/13c25771-feca-2d6c-9d0a-2b39dae53612.png "Screen Shot 2015-07-15 at 7.59.00 AM.png")

おお、無事日本語で表示されています!

ログの一部は文字化け?してしまっていますが、Clabashの実行?部分なのでしょうがないかもしれません。。。

![Screen Shot 2015-07-15 at 7.59.09 AM.png](https://qiita-image-store.s3.amazonaws.com/0/20193/76e7a6cf-3ae9-d6a7-8ef6-75b916a7ba6e.png "Screen Shot 2015-07-15 at 7.59.09 AM.png")


# 最後に

AWS Device Farmでは試験時のlogcatも取得できるようだったのでもし、エラーが発生した場合でも原因の特定がしやすいのではないかと思います。

また、Clabash-Androidは日本語で試験を書いてDevice Farmで試験をしておけば簡易なアプリの仕様書としても使えると思います。

まだ試してないですが、Espresso、JUnitなどの実行もやってみたいです。