UIAutomationで、actionSheetの取得は正常に実施できないので、accessibility_idによる要素取得にしたほうが良さそうだ。 alertは問題ないので、alert viewに関してはそこまで考えなくても良さそう。 例えば、以下のようにactionSheetを取得しようとすると、UIAElementNilが取得される。むむむ。。。 info: [debug] Got result from instruments: {“status”:17,”value”:”Cannot perform action on invalid element: UIAElementNil from target.frontMostApp().actionSheet().buttons()[\”キャンセル\”]”} info: [debug] Responding to client with error: {“status”:17,”value”:{“message”:”An error occurred while executing user supplied JavaScript.”,”origValue”:”Cannot perform action on invalid element: UIAElementNil from target.frontMostApp().actionSheet().buttons()[\”キャンセル\”]”},”sessionId”:”b412bcd4-d867-43df-9e3e-cafe2672ca05″}More
Author Archives: KazuCocoa
テストカメレオン
ふと、購読中の配信情報見てみると、テストカメレオンなるテストサービスを見つけました。 TestChameleon !! 変幻自裁なアーキテクチャを持ってるのかな?とか、多様なサービス持っているのかな?と思いざっと読んでみました。機能自体は、SauceLabsやBrowserStackみたいなものですが、そのテスト実行環境のアーキテクチャが貼られていたところが個人的に面白かったです。 以下、画像は以下URLから引張てきています。おもしろそうだと感じた方は一読してみると良いかもしれません。 http://www.ministryoftesting.com/2015/03/automated-testing-cloud-testchameleon/ Architecture Selenium Hub使っているのですね。最近だと、iOSが絡むところ以外がEC2上などにブラウザ環境を構築できるようになってきたので、こういうテストサービス自体の価格や自動化の障壁も下がってきましたね。嬉しいことです。 Dashboard Documents https://dashboard.testchameleon.com/media/tech-docs/_build/html/ APIs https://dashboard.testchameleon.com/media/tech-docs/_build/html/technical_doc.html 所管 提供されるテストの記述がJavaの例だったのですが、Groovyやらでかけるようなラッパー用意すれば使いやすそう。RubyやGroovy、Pythonのような感じの、少ない記述でテストかける方が私は嬉しいな。 SauceLabsやTesetDroidのように、モバイルアプリ/モバイルWebのテスト環境が整っているサービスはやはりまだ少ない模様。一方、Web Browserの環境を提供するものは増えてきて価格競争に突入しそうな雰囲気がひしひしと伝わってきますね。 競争。。。More
モバイルアプリにおけるE2Eテストの自動化に関して少しまとめる
少し前に、雑にモバイルアプリのリリースサイクル毎で行っているテストの流れという記事を書きました。 考え方が少し変わったりしているのですが、そこからE2Eテストという枠を抜き出して、さらにはテスト自動化という文脈で少し話を整理してみようと思います。 ここでは、効率的なコード、失敗時の解析の容易さなどに対する言及は致しません。また、サーバ側に対するテストの話にはちゃんとは触れません。 E2Eテストに含まれる目的 モバイルアプリにおけるE2Eテストという言葉には、恐らく以下の目的(と雑なテストタイプ)が含まれていることが多いと思います。 アプリのGUIから操作した (もしくは表示される要素に対して直接操作した)という文脈を持ったうえでの、 シナリオテスト 想定したStoryやFeatureを含んだシナリオを用意し、そのシナリオを達成できるかを検証したい 機能テスト(システム全体) サーバ側機能を含んだ、モバイルアプリのGUIから操作して意図した通りに機能が単体で振る舞うかを検証したい シナリオとして複数機能をまたがって何かする、という所までは見ない 統合テスト サーバからの応答をえた上で、モバイルアプリのGUI上で描画される要素を検証したい サーバはモック/スタブサーバでも特に限定しない。モバイルアプリ自体を構成する機能を統合させた上で正しく動作するかを見るもの。 GUIテスト 画面の表示、ボタンは位置などのレイアウトに対するGUIのレイアウト崩れ、描画される要素の過不足を検証したい 画面サイズ、解像度、フォントサイズ、アクセシビリティなどを考慮 なお、4に関しては端末のガイドラインに準拠しているかといった内容や、ユーザビリティに対する話は含まれません。 自動化する時に検証する方法 目的4以外のものに関しては、多くはGUIからの操作なので入力に対する出力を得て、その出力に対してアサーションをとることで検証を行うことでしょう。 4のGUIテストに関しては、モバイルアプリの場合は必ずスクリーンショットをとる必要が出てくるでしょう。描画される要素の有無であれば不要ですが、レイアウトが期待通りか、という所まで検証しようとすると、要素が描画された上で確認しなければ正しい/正しくないの判断ができないためです。例えば、画面サイズや解像度の多様性により表示がおかしくなるというのはAndroid/iOSともに多く有ります。 どこまで検証するか GUIから操作するという文脈を持つテストの場合、多くは実行に時間を要します。そのため、どこまで、何を確認するかということで神経を使う必要があります。そこで、アプリをどこまで確認するか、というところで少し雑にまとめてみます。 なお、ここの分け方は検証したいことと、その環境で雑に区分しています。 1. シナリオテスト ユーザが実際に操作する内容をシナリオに落とし込んで、期待されるシナリオを完遂できるか検証する ユーザの操作が変わるパターンはなるべく用意する モック/スタブサーバは利用しない 外部システムとの連携、端末の設定に依存する箇所も含む 2. 機能テスト(システム全体) サーバ側からの応答によりモバイルアプリケーションの振る舞いが変わる場合、それは可能な限り網羅する GUIからすると同じ表示でも、その裏側(サーバからの応答)が異なる場合も含む 機能として仕様に定義した範囲 モック/スタブサーバは利用しない 外部システムとの連携、端末の設定に依存する箇所も含む 3. 統合テスト サーバ側からの応答によりモバイルアプリケーションの振る舞いが変わる場合、それは可能な限り網羅する GUIからすると同じ表示でも、その裏側(サーバからの応答)が異なる場合も含む モック/スタブサーバを用意してでも、サーバからの通信結果をもとに、アプリが期待通り動作することを検証することが目的 端末の設定に依存する箇所を含む 4. GUIテスト レイアウトパターンはなるべく網羅する 同一レイアウトの使い回しに関しては、不要なものは実施しない ツールとテスト モバイルアプリでは、Headless browserのようなGUIの無い高速な確認手段は存在しません。また、espressoや、Debug用にSDKとしてハックしたライブラリを使う以外は、システムが提供するアニメーションなど含めてそれらを許容した上で各種テストを回す必要があります。 そのため、基本的にGUIから操作した上で確認を行う必要があるため実行速度はWebアプリほど速度を出すことが難しいです。一方、espressoなどのように限定した使い方であれば安定して高速に確認する手段もそろってきたので、そこらへんも解消する日が来るかもしれません。 シナリオテストやGUIテストを目的としたE2Eのテストを行う場合、基本的にAppiumのようなGUI越しに操作するツールを使うことになるでしょう。そこでは実行速度と安定性がやはりトレードオフになります。一方で、現在のモバイルアプリを検証するツールとしてはこれ以上の手段は殆どないです。 機能テストや統合テストを目的としたE2Eのテストを行うときの多くもAppiumのようなGUI越しに操作するツールが基本になると思います。ただ、espressoのような高速にView単体を確認できる手段も選択肢としてでてきました。そのため、単なる表示のバリエーションなんかはAppiumのようなもので実施するよりも、遥かに高速に実施できる環境として利用できるようになってきました。 ここで話している文脈における自動化されたテストは、手動テストによる回帰テストを減らすことが目的で使うことが多いと思います。なので、互いに補完関係になるように、プロジェクトとして十分な目的を選んでいきたいですね。…More
Appiumのテストを1台の計算機上で並列して実行させる
Appiumでテストを実行していると複数台の計算機でテストを並列して実行したい、と思う方もいるでしょう。 Appium自体はサーバなので、1台の計算機上で複数起動させ、テストを並列して実行させることができます。これを行えば、独立したテストケースを分散させて、それぞれのテストを実行、結果を収集するという簡単なテストケースの実行並列化もできます。Selenium Gridよりもかなり手軽にテストを実行できる環境になるでしょう。 設定する点は以下 Appiumサーバに必要な引数を与えて起動する テストケース側のcapabilityに対象となるAppiumサーバの待ち受けポートを指定する 例えば、appium_libを使っている人だとcapabilitiesのportに値を設定する必要があります。 例 Appiumサーバの起動 ※appiumコマンド箇所は、適切にnode .などに置き換えてください capabilityの指定 例えば、appium_libを使っていると、appium.textの[appium_lib]にportを指定する方法があったり( ★ )、以下のように直接メソッドに値を与えるならserver_capsに対して要素を指定する方法があります。 いずれにせよ、これによりシナリオをAppiumサーバに渡すことができるようになります。 並列実行 Step1 Step2 以下2種類でそれぞれ起動 注意点 iOSではiOS Simulatorの制限上、複数Simulatorを同時に起動させることができません。そのため、iOSは並列実行するには物理的に複数のMacマシンが必要です。 ref: https://github.com/appium/appium/blob/master/docs/en/appium-setup/parallel_tests.md ref: https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/server-args.mdMore
JaSST15 Tokyoに参加、パネリストとして前に立ってきた
JaSST 15 Tokyoに参加してきました。 また、JaSST 15 Tokyoの企画セッションの1つである「Web.JaSST ~ウェブ開発のテスト~」で登壇してきました。 ※諸事情により、参加したのは2月20日だけです。 参加したセッション How To Get What You Want From Testing(for Testers, Developers, and Managers) テストプロセスの評価と改善 聞いた以外で面白そうだったセッション テストコードクリニック How To Get What You Want From Testing(for Testers, Developers, and Managers) Michael Bolton氏による発表です。 以下Twitterで簡単にまとめられていました。 同氏は、テスターがTestingの中心であると述べていました。そこに対して、TestingとCheckingの違いから、明らかな機能的な不具合の他に”おかしいと感じる”ことも重視してTestingするという話しを混ぜていました。 例えば、人は以下のような感情を受けます。これらは良くないものもあり、良くないと感じたらそこは不具合が存在する可能性が高い。それは今のところ機械では見つけられないTestingによって得られるフィードバック、ととれます。 Impatience Frustration Fear Suprise Confustion Annoyance Boredom Tiredness Anxiety これらの感情は、以下のような問題へと繋がります。 Capability Scalability Reliability Usability…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
『リッツ・カールトンが大切にするサービスを超える瞬間』を読んだ
リッツ・カールトンが大切にするサービスを超える瞬間を読みました。サービス産業におけるサービスの提供がどんなものか、サービスの品質をどのように保ち、より良くしているのかという仕組みに興味があったので、パラパラとめくる感じで読んでいきました。 大事そうなところをさっとまとめると、以下のようなものでした。 従業員も顧客同様の立場で接し合うことで、どのようなサービスがより顧客に価値があるかを考えられるようにする チームワークの良さがサービスの良さにつながる SQI(サービス・クオリティ・インジケーター)を計測、再発防止に取り組むことで日常的に高価値のサービスを提供できる体制を作る 会社の哲学を浸透させる 抜粋 いろいろまとめると長くなりそうなので、いくつか抜粋するにとどめます。半日かからないくらいでさっと読めるので、読んでみると良いかもしれません。 従業員を”内部顧客”と呼び、同じ目線でお互いを理解しあい、心から尊敬しあう リッツカールトンのサービス哲学 「明日はまたどんな感動があるのだろう」と思っていただけるようなサービスが提供できているかどうか 紳士淑女であるお客様に仕える私たちも紳士淑女である We Are Ladies and Gentlemen Serving Ladies and Gentlemen みんなが常にお客様の視点に立ったサービスを心掛けている 会社都合のシステムからは感動は生まれない チームワークの良さが最高のチームをつくる 会社の哲学はクレドとして共有される クレドは会社の哲学や、従業員の行動指針 クレドは時代に合わせて変化する クレドを自分と同じレベルで共有できるかが最上位の優先 同じ結果を出すためにマニュアルは必要 ただし、「ああしなさい、こうしなさい」ではない サービスで重要なことは高く感性を共有すること 技術は訓練できてもパーソナリティは訓練できない サービスを提供するひとは ジャズプレイヤー マニュアル通りで済ませるのではなく、より良いことがあればそれを実施できるように ホスピタリティ(おもてなし)産業 SQI(サービス・クオリティ・インジケーター) 毎日の仕事やサービスを提供する場面で起きてくる 欠陥事項、失敗事例、問題事項などを一つ一つ数値化して、記憶に残す作業。 これらは収集され、同様なことが再現しないように内部プロセスが見直したりされる。 締め サービス産業としては、例えばWebサービスも重要な点は共通しているところが多いです。何かサービスを創り出す技術が高くとも、サービスとして価値を出せなければ消えていくだけです。 こう考えると、SQIのような仕組みを組織全体として循環させることは非常に重要だと痛感します。技法的な文言はこのSQIしか書籍にでませんでした。これからも、科学的なアプローチをあげた場合、SQIは大事な要素なのだと見て取れます。 Webサービスの現場では、テストエンジニアやQA的な役割に責任を持つところはまだ少数だと思います。が、これから広がっていくだろうし、そういう人たちの活躍が会社の成長を、サービスを創り出すエンジニアやディレクター、営業の方々と相まって後押しするものになるのでしょうね。 頑張ろう 蛇足 こういうサービス産業のおもてなし、経験できるときに経験したいですね。サービス的な面白さがありそう。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