最近、AppiumのGitHub上でdroiddriverなるものを知りました。 https://github.com/appium/droiddriver これ、どこから来ているのか気になっていたら、どうやらgooglesource上から来ている模様。 https://android.googlesource.com/platform/external/droiddriver droiddriver_examplesを見てみたところ、このDroidDriverTestはActivityInstrumentationTestCase2を継承している模様。 ということは、ひとまずJUnit4の枠組みでも利用できますね。 ここを見ると、どうやらDroidDriverはSDKとしてはAPI21が必要らしい。確かに、先ほどのGoogleのコードを追っても、4.4(KitKat)以降開発され、まだ正式なものとして出てはなさそう。ただ、手元でDroidDriverを継承したテストケースをconnectedAndroidTestで回すと、4.2.2の端末でも動作したので、OS自体はuiautomatorを提供するものになるのかな。 API18以上はuiautomator driverだし、17以下はinstrumentation driverだし。 これはuiautomatorを拡張したdriverなのかもしれないですね。 ちなみに、DroidDriverを使うには以下のようにclassSetUpをOverrideする必要があるみたい。 手元で軽くespresso向けのテストをDroidDriver使って動かしてみると動作しました。 先にあげたGitHubに記載されている例の中には、例えば以下のようなメソッドがあるので、DroidDriverはespressoの代替ではなく、uiautomatorをJUnitから操作する枠組みな気がしています。 ともあれ、少し追ってみようかな。More
Tag Archives: test
AndroidTestCase/InstrumentationTestCase/AndroidJUnit4のgetContext/getTargetContextを比べてみた
Androidのテストフレームワークにて使われる、getContext、getTargetContextで取得されるコンテキストの理解を整理するために以下のそれぞれに分けて比較してみました。得られるコンテキストはテスト対象のパッケージ、テストパッケージ(xxxx.testというパッケージ名になるやつ)の2種類のどちらかになるはずです。 AndtoidTestCaseを継承したテストケース InstrumentationTestCaseを継承したテストケース 何も継承しない(AndroidJUnit4で実施される)テストケース AndroidTestCase AndroidTestCaseでは、getContextでテスト対象のパッケージを得ることができるだけです。どうやら、AndroidTestCaseではsetTargetContextが@hideされているらしいです。そのため、テストパッケージはそのままでは取得できないらしいです。 参照 InstrumentationTestCase こちらは、getContextでテストパッケージ、getTargetContextでテスト対象のパッケージが取得できることがわかります。 AndroidJUnit4で実施されるテストケース こちらも、getContextでテストパッケージ、getTargetContextでテスト対象のパッケージが取得できることがわかります。 また、getInstrumentationが挟まることで何か大きく変わるのかと思いましたが、コンテキストの取得という意味では変わりないようです。そうですよね。 テストコードを理解するときは、そのテストで使われるコンテキストがなんなのかを理解することは大事なので、ここらへんの基礎的な理解はしっかり持っておきたいところですね。 参考 Testing Fundamentals http://developer.android.com/tools/testing/testing_android.html 2種類のパッケージがあることで、テストパッケージにテスト専用のリソースを配置(/resとか)して閉じた環境でテスト実行が可能になります。 蛇足 そういえば、最近 @FlakyTest と呼ばれるアノテーションを見つけました。不安定なテストのことを、Flaky testとよく呼びます。 1つめ: android.support.test.filters @Flakyは、テストのフィルタリングを行うためだけのアノテーション https://android-test-kit.googlecode.com/git/docs/javadocs/testing-support-lib-0.1-javadoc/reference/android/support/test/filters/FlakyTest.html 2つめ: android.test @FlakyTestは、テストが失敗したら勝手に再度トライしてくれるためのアノテーション http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.2_r1/android/test/FlakyTest.java?av=f This annotation can be used on an InstrumentationTestCase’s test methods. When the annotation is present, the test method is re-executed if the test fails.…More
android-test-kitで使われるInstrumentationRegistryの理解を深める
android-test-kitの理解を深めようと、以下を眺めていました。 https://code.google.com/p/android-test-kit/wiki/AndroidJUnitRunnerUserGuide この中で、JUnit4の枠組みの中でContextを取得するためのInstrumentationRegistryがどのように振る舞うのか気になったので少し追ってみました。 InstrumentationRegistry is an exposed registry instance that holds a reference to the instrumentation running in the process and it’s arguments and allows injection of the following instances: Androidのテストフレームワークは多くの方は既知だと思いますが、 ref: http://developer.android.com/tools/testing/testing_android.html のようになっていて、テスト対象のアプリケーションパッケージと、テストパッケージ、その間にInstrumentationTestRunnerが存在します。 android-test-kitを導入する前までは、このアプリケーションパッケージ/テストパッケージのコンテキストを取得するためには、テストケースのクラスがAndroidTestCaseもしくはInstrumentationTestCaseを継承する必要がありました。 一方で、android-test-kit導入すると、それらの継承なしでコンテキストを手に入れる手段があります。それがInstrumentationRegistryです。 いったん、このandroid-tets-kitが提供するAPI群を見てみます。すると、android.support.test配下にInstrumentationRegistryが提供されているのがわかります。 そのリファレンスを進むと、Public Methodとして以下が提供されていることがわかります。 getArguments() getContext() getInstrumentation() getTargetContext() registerInstance(Instrumentation instrumentation, Bundle arguments) おやおや。registerInstanceだけが先ほどのwikiで説明されていませんでした。となると、名前からしてもここが怪しそうです。registerInstanceの説明にも Records/exposes the instrumentation currently running and stores…More
Appium 1.3.5 released
Appium 1.3.5 がリリースされましたね。 リリースノート https://github.com/appium/appium/releases/tag/v1.3.5 ここまでのバージョンになると、開発量も少し落ち着いてきたように見えます。 iOS8.x系に関しても、iOS7=>iOS8のような大きな変更がシミュレータにも入るわけではないので。 driver.get()でpageを取得できなかったところなんかの修正が入っています。あとはiOS8.2。 iOS8.3もbetaで入手できるようになりましたが、iOS8.3からは OS X 10.10以降がRequirementになります。 なので、メンテナンスされるメインストリームもOS X 10.10に移り変わる流れになりそうな予感。 Androidに関しては以下の修正が入っているので、1.3.4使っている人は更新したほうが良さそう。もとより、私の環境では1.3.4があまりちゃんと動かなかったので、masterブランチや1.3.5betaを使っていましたが、ここでnpmから入手できる正式版が使えるようになった。 add workaround for issue where UiAUtomator fails to find visible elements. fixed undefined member error for the release object.More
UiSelectorを使うようにしたほうが良さそうだ
過去いったんまとめた、Appiumを使ってiOS/Androidの要素を取得する方法の数々に追記した。 Appiumの1.3.3まではできていて、1.3.5betaからできなくなったことに以下による要素の特定がある。 これは、以下のようにUiSelectorを使えば問題はないみたいだ。 UiSelectorはこちらから確認することができる。Uixxxxxシリーズは、uiautomatorの要素として提供されているものなので、UiSelectorをちゃんと使っていくという方がAndroidでは正しそう。 心無しか、AppiumもUiSelector使って安定したようにみえる。 Appiumで行うレベルのテストはテスト環境で影響される要素が多いので、地道にFlakyなテストを減らして安定したテストを回したい。。。More
exclude group: ‘javax.inject’してinjection系のjava.lang.NoClassDefFoundErrorを回避する
espressoを導入するためにcom.android.support.test.espresso:espresso-core、com.android.support.test:testing-support-libをインストールします。 そうすると、テスト実施時に というようなエラーを確認できることがあります。 このエラーはDaggerやRoboGuiceを導入していると確認されました。これは、espressoのjavax.injectが競合しているから発生している模様です。なので、以下のようにexclude groupで指定してあげると、回避できます。 ここらへんのpom.xmlなんか眺めていると、確かにjavax.injectが依存関係で確認できますね。 なるほど。 関連 stackoverflow★More
AndroidのアニメーションをOFFにしてFlakyなテストを減らしたい
モバイルアプリのViewに対する自動テストを行おうとした場合、画面遷移時なんかのアニメーションがFlakyなテストにつながることが多々あります。たとえば、Appiumやespressoなどを使って複数のViewを跨いだりする時なんかはよくある話です。 Androidに関しては、開発者オプションの設定により、以下アニメーションをOFFにすることが可能です。 ウィンドウスケール トランジションアニメーション Animator再生時間スケール この設定をOFFにすることで、アニメーションをOFFにした上でViewに対するテストを実施できるようになるので、より安定したViewに対するテストを実施することができます。ただし、この設定をOFFにするとアニメーションが無視されるようになるので、テストレベルとその時々にどんな不具合を検出したいかというテスト設計に沿って、アニメーションを無視する/しないを決めるとよいでしょう。 個人的な感覚では、Androidにおいてはespressoによるテスト実施時はアニメーションをOFFにしてViewの確認、Appium使うときはアニメーションも考慮して確認が良いかなと思っています。これにより、UnitTestingから徐々に確認する領域を増やしていき、テスト自動化のビラミッドのような形に、自動テストの厚みを調整できそうな気がします。 実施方法 以下コード例に沿って、テストユーティリティを実装しておきます。 Android端末におけるAnimationをOFFにするコード例 DisablingAnimations AndroidManifest.xmlに SET_ANIMATION_SCALE を指定する必要があるのですが、Gradle 2.1からは特定のビルドだけ、特定のマニフェストを追加することができる模様。 そのため、たとえば、 ./gradlew coonectedAndroidTest のときのみSET_ANIMATION_SCALEを増やしたい場合、以下のような感じでAndridManifest.xmlを作れば良いみたいです。 src/androidTest/AndroidManifest.xml ここまでの対応をしたのち、テストスクリプトのsetUpにでもアニメーションをOFFにする変更を書き込み、espressoを実施してみます。問題なく動く!!!と思っていたのですが、以下のようなエラーが… Cannot disable animations due to lack of permission. SET_ANIMATION_SCALEを眺めてみると、以下のようにどうやら3rd party製アプリには許可していない模様。 いろいろ調べましたが、これのWorkaroundは以下のようです。 AndroidManifest.xml にSET_ANIMATION_SCALEを許可しているアプリに対して以下adb shellコマンドを実施する 標準出力に特に何も出力されなければ、成功です。システムのアプリケーション情報に、アニメーションの権限が追加されていることを確認することができます。以降、DisablingAnimationsのユーティリティによりアニメーションをOFFにするということが正常に受け付けられるようになります。 ちなみに Appiumにも、1.4になりますが以下のように計画があるようです。 Appium should disable Android’s system animations to reduce flakiness Appiumでは、ツールの作り上、espressoよりも実現しやすそうとも思うのですが時期があえばなんらかのコミットもしたいかな。adb shellのやり方に関しても同じところを参照しているようなので、実装方針も思っているのと同じ方針な気がする。 締め アニメーションのOFFはViewに対するテストでFlakyなものを減らすという意味でも何気に必要だったりします。ただ、adbコマンドを毎回使ったりすることが面倒なので、一番楽なのはアニメーションをOFFにしたテスト用端末でテストを実施することだったり… 雑談ですが、最近、TestFlightから別サービスに移ろうとする流れがありますね。Appleが旧TestFlightをやめると言ったので。 TestFairyとかとか、代替サービスとして探している人も多いですが、そこらへんでテストサービス それらを見てて感じるのですが、落ちバグ発生時、そのクラッシュログを動画付きで取得して、その再現まで自動的に実施できる環境の構築なんかしてみたいですね。技術的な関心なだけですが。ただ、不具合レポートからUI含めた再現をどうやるかなーと思った時、無理そうと思ってしまう。もしかしたらUnit testレベルなら再現できるかもしれないですが、それがユーザ操作として正しく発生しうるクラッシュを防ぐことにつながるか、と考えるとそうとも言えないことを多々経験したので、やって価値あるかなーと考えてしまう。難しいですね。More
espressoをたしなんでみた
前年末頃、espressoも2.0になり、JUnit4も使えるようになったAndroidのテスト環境。 既存コードの対応を考えるとJUnit4対応も考えないといけないですが、それに見合うだけのメリットが出てきた気がします。 espresso 2.0 release note サンプルプロジェクトはこちらにありました。 私はiOSと合わせてAndroidに関してもAppiumを選定していたのですが、espresso2.0の登場により、役割とテストレベルに応じてViewを含んだテストを行うときに程よい区分ができそうです。結構、良い補完関係を持つツールだなと感じています。 Appiumの特徴は、リリースapkを直接テストできることだと思います。つまり、一般ユーザがそのまま使う操作に近いUI操作を模倣することができます。そのため、様々なテストレベルにおけるテストを実施したのち、E2Eレベルでの、システム全体としてのテストを実施することができます。 espressoの特徴は、やはりViewを構築しながらも実行の速さを出せるところだと思います。そのため、mock serverなどを用意して、短い時間にUIのレイアウト確認を実施することができます。Hermetic testとしてのテスト環境により適しているかもしれませんね。また、JUnitで記述するので、CIに程よく組み込めそうです。 いずれもテスト環境の構築で変化する要素は多分にありますが、Viewの確認を行うにしても、それぞれが得意とする分野は異なるので、テスト戦略や計画、設計に応じた使い分けができれば良いと思います。この箇所は、テストのしやすさがiOSと異なりますね。 espressoを少し espressoのサンプルです。先ほどのGitHub上のサンプルコードより引用しています。 R.id.operation_mul_btnと、要素の指定はidの直接指定をこなうことで要素の特定をしているようです。API18以上だとresoirce_idの直接指定ができるようになったものと同様な感じで要素は指定するようです。 espressoのCheatSheetに以下の画像がありました。 これを見ても、espressoは画面単位で、期待した描画ができているか、というところに焦点を当ててテストを書くことが適していそうです。 想定したユーザシナリオを実施できるかは、Appiumが良さそう。More
Appium 1.3.5 beta released!!
Appiumの1.3.5がリリースされていた。 1.3.4では、環境によってはadbコマンドかinstrumentsへのコマンドが正しく動作しないことがあったのでmasterブランチを追ってましたが、これでnpmの世界で過ごせる! 比較的大きなものとしては、iOS8.2の対応とかでしょうか。とはいえ、対応バージョンの追加などの比較的細かな所になりますが。 あと、Androidに関してはUiAutomatorあたりでworkaroundが入っていたりとするので、AndroidでUiAutomor使っている人には良いのでは。 何も問題なければ、多分1.3.5はこのままリリースされるはず。 https://discuss.appium.io/t/appium-1-3-5-beta-released/2511 iOSアプリで要素を取得するとき、Appium.app経由だと取得できる要素が、コマンドラインから起動したAppiumサーバ経由だと取得できないものに出くわしたのですよね。 ??と思って、コマンドラインのAppiumサーバ経由で起動したあと、inspector経由でアクセスすると、確かに見えない。 これは何だ。。。と疑問に思って調査しようとおもってはいるのですが、致命的というわけではないのでんーという感じでうやむやに。 そろそろ、コード書いて、コードを読む量を増やしたい機運。More
Why The Facebook App is Rated Below 2 Starsを読んだ
最近みたこの記事から、モバイルアプリ開発に関して学ぶことができた気がするので、メモ。 これはメモなので、興味のある方は本文読んだ方が良いです… 最近のiOSのFacebookアプリは、各国で以下のように平均で低いレートを得ています。この記事では、その原因を分析していました。 Breakdown of Issues Reported 以下は、1月1日〜1月15日の間の、USにおけるレビューの内容を集計したものです。 これを見ると、マイナス要因になるレビューは アプリのクラッシュ コア機能 の2つが大きいそう。他にも要因も書かれていましたが、大きくはこの2つのようですね。 リリースサイクルとQAチーム FacebookのiOSチームは、2週間のリリース間隔を持っているようです。また、1週間ごとのスプリントで開発サイクルを継続しているよう。 このYouTube記事によると、FacebookはQA期間を設けていますが、公式なQAチームは存在しないらしいです。その代わり、テストベースの開発に注力しているようです。 “As you may know, Facebook does not have big QA teams…we believe that developers are responsible for their own code, and they’re supposed to write the tests to do that.”- Quote from Alan Cannistraro 実施しているテストツールの一部 以下のようなテストツールを使っているそうです。 Snapshot unit test ios-snapshot-testingのやつですね。GitHubで公開されています。…More