忘れないようにIntentのUnitTestを書いてみた

昨日の記事をちょっと手を動かしておこうと思って、IntentのUnitTestを書いてみた。ついでに、@RunWith(AndroidJUnit4.class)を有効にして。 AndroidJUnit4.classを使うにあたってエラーが出て修正したポイントは2つ。あとおまけで1つ。 injectInstrumentationによるInstrumentationへのinject これしないと、super.setUp()で落ちる InstrumentationRegistry.getInstrumentation().runOnMainSync()によるintentからのActivityの起動 これしないと、startActivityがヌルポで落ちる ContextThemeWrapperを使うことで、R.style.AppThemeをテスト時にレイアウトとして使う レイアウトを独自でカスタマイズしている場合、AppThemeが無いみたいなエラーが出てきました どうやら、ContextThemeWrapperで仮のレイアウトを使うことで回避できるもよう 今回はあくまでもintentの確認なので、まー、よしですかね UIスレッドの話しなんかも、対応を終えたあとはなるほどなーという感じ。 ちょっと記述量を減らしたく、ButterKnifeを使ってみました。おまけ程度。 内容は、 com.example.activityのアクティビティを起動する 表示されるボタンをタップして、別アクティビティ(com.example.activity.Next)を起動する という内容に対して、期待したintentが飛ぶことを確認する、というものです。 ActivityUnitTestCaseなので、その実際が描画されたりはしません。これ、Integrationレベルで確認すると、Espressoを使って描画ベースの存在確認を行いますね。 ふぅ。Intent、いろいろちゃんとしておかないと魔の巣窟になって危なそうですね。サービスが肥大化してくると特に。怖い怖い。 最近、StethoをVolleyに適用しようとしています。単純に適用しようとすると、VolleyのHttpStackを活用してOkHttpStackのようなクラスを作成し、QueueRequestにHttpStackを与えます。 なのですが、今取り組んでいるところはそのような形でさくっとできるような所ではなく、少し手惑い気味。More

Testing and Securing Android Studio Applicationsを読んだ

Testing and Securing Android Studio ApplicationsのKindle版が安かったのと米国レビューもそこそこあったので読んでみました。あと、TestingとSecuringを同時に扱っていたので、基礎的な知見もまとめられているものと期待して。 結果的には、出版日も2014年8月とそんなに古くないので、入り口的な書籍としては良いと思いました。ツールやコードの話もありますが、まだ古くて使えない、というレベルのものではないですし。 内容的には、intentに対するUnit testレベルとInstrumentationを使ったレベルでのテスト方法が、個人的には何気に参考になりました。 以下は、私の備忘録込みでつらつらと… 第1章では基本的なソフトウェアセキュリティ全般の話。 Access control Asymmetric cryptography Authentication Availability Brute force Cipher Code injection Confidentiality Crack Decryption Denial-of-service(DoS) Distributed denial-of-service(DDoS) Dictionary attack Encryption Hash function Hijack attack Hypertext Transfer Protocol Secure Integrity MD5 Man-in-the-middle attack Password Phishing Risk SHA1 Sniffing attack Spoofing attack Threat Vulnerability このうち、Threat、Vulnerabilities、risksに関してはさらに言及されていました。 Threat…More

UIAutomator2.0がリリースされていた

3月13日、以下の通りAndroidのUIAutomator 2.0がリリースされていたのですね。 https://plus.google.com/+AndroidDevelopers/posts/WCWANrPkRxg uiautomatorは、AndroidのAccessibility機能やその拡張を介して、インストールされた様々なapkを操作するフレームワークでした。そのため、例えばリリース用apkに対してシナリオテストを自動化するときなんかに使います。例えば、AppiumはAndroidに対してはこのuiautomator1.0を利用してテストを実施することをしています。 uiautomatorあらため、UI Automator 2.0の新しいところは、Instruments経由でUiElementsなどを使えるようになったことらしいです。これにより、./gradlew connectedCheck なんかのコマンドでUI Automatorによるテストを実施できるようになったとか。 まだASOPには公開されていませんが、Appiumのメンバらも公開されたら良さそうなら統合とかするでしょうし、DroidDriverとももしかすると競合するところがあるのかもしれません。 2014年12月のEspresso2.0のリリースとそれに伴うJUnit4の提供、UI Automatorの更新と、比較的テストツールの充実が図られていて良い感じですね。 Testing Support Libraryが提供する大きな機能 AndroidJUnitRunner: JUnit 4-compatible test runner for Android Espresso: UI testing framework; suitable for functional UI testing within an app UI Automator: UI testing framework; suitable for cross-app functional UI testing across system and installed apps AndroidJUnitRunner Require Android2.2(API Level8)…More

Stethoを使ってAndroidアプリのデバッグを容易にする

Android、iOSのようなクライアントアプリの開発では、特にDB関連や通信環境が絡むデバッグが面倒です。実際にデバッグを行うとき、例えば、Proxyサーバを立てて通信を覗いたり、SQLiteのファイルを直接覗いたりしますね。はたまた、Logの出力を仕込んで、そのログを追うという方法をとることが多いです。 また、単純な通信量であればAndroid Device Monitorなどが使えますが、通信の中身までは見れません。 それらの壁を低くするツールとして、SquareのGitHubから得られるPony Debuggerが有名です。これは、Chrome Developer Tools を使い、通信の内容を簡単に観察したりできるツールです。また、Android/iOSのChromeブラウザであれば、同様にChrome Developer Tools を使い端末上で動作するブラウザの情報を得ることができます。 そして最近、Facebookが出したAndroid向けのStethoを見つけました。リポジトリを見てみると、最初のコミットが2015年1月30日と非常に若いです。これを組み込んだapkではChrome Developer Tools を介し、SQLiteやNetworkの中身を観察することができます。特別なProxyを用意したり、SQLiteのファイルを直接操作する必要もありません。 まだ若いので、使い方とか諸々変わりそうなのでリンクだけ貼っておきます。 http://facebook.github.io/stetho/ https://github.com/facebook/stetho 基本的には、Applicationを継承したクラスをonCreateするときに、合わせて初期化メソッドを追加するだけ。 ネットワークをChromeで見るには少し手間かけますが、Squareのokhttpを通信向けパッケージとして使っている場合、OkHttpClientを初期化するときにデバッグ設定を追加するだけという手軽さ。 これらの機能を、例えばBuildConfig.DEBUGのときだけ有効にするとかしておけば、社内で配布するapkは誰もがChromeさえあれば通信内容を確認するという環境が作れてすごく良さそう。 なお、logcatに以下のようなsocketに接続できたという出力が得られたらネットワークの通信もChrome上で見ることができる状態になります。 Chromeを経由してネットワークの中身を見るとこんな感じ。More

Appium1.3.6released

https://github.com/appium/appium/releases/tag/v1.3.6 AndroidのXPath、ChromeDriver向けの修正のようですね。 確かに、私の実施するXPath指定のテストも正常に動作しなくなってましたので、これで直るかも。 ただ、XPathではなく、UiSelectorを使う形に修正したのであまり関係しなさそう? …. ちょっと確認してみた感じでは、修正されたわけではなさそう。。。More

AndroidJUnit4RunnerでParameterized Test

AndroidでもJUnit4が使えるようになったことで、parametarized testingも容易に可能になったのか確認してみました。 例 端末のローケルを設定し、その情報を取得する関数を確認するためのテストです。 コード テストコード 複数のローケルを設定した上で、正常に設定したローケルを取得できるか?というテストを愚直に書くと以下のようになります。 これ、多言語化が進むなどでlocalの設定する種類が増えると、そのぶんコピペのテストケースが増え、必要以上に冗長になります。 そこで、parametarized testです。 Parametarized test JUni4におけるParametarized Testの細かな構文説明はここでは除きます。 ポイントはざっと以下です。 RunWithでTheories.classを指定する ただ、本来はTheoriesは組み合わせテスト用… @DataPoint / @DataPointsでパラメータ化する要素をまとめる @Theoryにテストケースを書く @Testは使いません これにより、DataPointsを増やすだけでテストケースを増やすことが可能になります。 このDataPoint/DataPointsはBeforeが解釈される前に計算されるので、Beforeで設定した値を動的に入れるということはできません。 ちなみに、@Testとしてアノテーションを設定したら、通常のテストケースとして処理が行われます。 @Theoryは複数作っても良いので、たとえばLocalSettingParameterにより変わるテストケースを1つのファイルに集めて分散を防ぐとかもできます。 Androidのテスト、だいぶんまとめやすくなりましたね。More

DroidDriverなるものがあると知った

最近、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

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

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